C语言打印节表--PE文件解析
void Funcation4()
{
char* file_buffer;
long file_size = 0;
FILE* fp;
fp = fopen("notepad-32bit.exe", "rb");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
printf("文件大小为:%d字节\n", file_size);
//这里重新指向开头
rewind(fp);
//申请内存空间
file_buffer = (char*)malloc(file_size);
printf("file_buffer:%x\n", file_buffer);
//初始化内存空间
memset(file_buffer, 0, file_size);
//将文件读入内存中
fread(file_buffer, file_size, 1, fp);
//这里是用windows.h头文件,使用了Windows.h之后才有下面的内容,定义一个结构体指向那块内存
//这个就是DOS头获取的方式?
PIMAGE_DOS_HEADER Dos = (PIMAGE_DOS_HEADER)file_buffer;
printf("DOS:%x\n", Dos);
printf("********************DOS头********************\n");
printf("MZ标识---E_magic:%x\n", Dos->e_magic);
printf("PE偏移---e_lfarlc:%x\n", Dos->e_lfarlc);
printf("Dos->e_lfanew:%x\n", Dos->e_lfanew);
//打印NT头内容
//判断是否是有效的PE文件
if (*((PDWORD)((DWORD)file_buffer + Dos->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
free(file_buffer);
return;
}
//获取NT头位置,这句话主要解释下这里:file_buffer(DOS初始位置) + Dos->e_lfanew,file_buffer + Dos->e_lfanew就是NT开始位置
printf("********************NT头********************\n");
PIMAGE_NT_HEADERS Nt_Header = (PIMAGE_NT_HEADERS)(file_buffer + Dos->e_lfanew);
printf("nt:%x\n", file_buffer + Dos->e_lfanew);
printf("nt--Signature:%x\n", Nt_Header->Signature);
//nt指向fileheader
printf("nt--FileHeader:%x\n", Nt_Header->FileHeader);
//nt指向OptionalHeader
printf("nt--OptionalHeader:%x\n", Nt_Header->OptionalHeader);
//这里加4个字节越过nt--Signature,得到machine的位置
printf("********************File_header********************\n");
PIMAGE_FILE_HEADER File_header = (PIMAGE_FILE_HEADER)(file_buffer + Dos->e_lfanew + 4);
printf("File_header---Machine:%x\n", File_header->Machine);
printf("File_header---NumberOfSections:%x\n", File_header->NumberOfSections);
printf("File_header---TimeDateStamp:%x\n", File_header->TimeDateStamp);
printf("File_header---SizeOfOptionalHeader:%x\n", File_header->SizeOfOptionalHeader);
printf("File_header---Characteristics:%x\n", File_header->Characteristics);
//这里在fileheader 的基础上越过20个字节得到Option_header
printf("********************Option_header********************\n");
PIMAGE_OPTIONAL_HEADER Option_header = (PIMAGE_OPTIONAL_HEADER)(file_buffer + Dos->e_lfanew + 4 + 20);
printf("Option_header---Magic:%x\n", Option_header->Magic);
printf("Option_header---SizeOfCode:%x\n", Option_header->SizeOfCode);
printf("Option_header---SizeOfInitializedData:%x\n", Option_header->SizeOfInitializedData);
printf("Option_header---AddressOfEntryPoint:%x\n", Option_header->AddressOfEntryPoint);
printf("Option_header---BaseOfCode:%x\n", Option_header->BaseOfCode);
printf("Option_header---BaseOfData:%x\n", Option_header->BaseOfData);
printf("Option_header---ImageBase:%x\n", Option_header->ImageBase);
printf("Option_header---SectionAlignment:%x\n", Option_header->SectionAlignment);
printf("Option_header---FileAlignment:%x\n", Option_header->FileAlignment);
printf("Option_header---SizeOfHeaders:%x\n", Option_header->SizeOfHeaders);
printf("Option_header---CheckSum:%x\n", Option_header->CheckSum);
printf("Option_header---SizeOfStackReserve:%x\n", Option_header->SizeOfStackReserve);
printf("Option_header---SizeOfStackCommit:%x\n", Option_header->SizeOfStackCommit);
printf("Option_header---SizeOfHeapReserve:%x\n", Option_header->SizeOfHeapReserve);
printf("Option_header---SizeOfHeapCommit:%x\n", Option_header->SizeOfHeapCommit);
printf("Option_header---NumberOfRvaAndSizes:%x\n", Option_header->NumberOfRvaAndSizes);
//这里重新指向开头
//rewind(fp);
//这里遍历节表
printf("********************遍历节表********************\n");
//首先获取有几个节表,通过NumberOfSections获取节表个数,获取节表起始位置,节表起始位置位于File_header---Characteristics
//往后加E0个字节
printf("节表个数:%x\n", File_header->NumberOfSections);
printf("节表起始位置:%x\n", Dos + File_header->Characteristics + 0xE0);
//我们通过windowsAPI------------IMAGE_FIRST_SECTION(pNtH)直接获得区块表的首地址
//PIMAGE_SECTION_HEADER Section_Header = IMAGE_FIRST_SECTION(Nt_Header);
//PIMAGE_SECTION_HEADER Section_Header = (PIMAGE_SECTION_HEADER)(Option_header + File_header->SizeOfOptionalHeader);
printf("Option_header:%x\n", Option_header);
printf("(DWORD)Option_header:%x\n", (DWORD)Option_header);
//dword必须申明
PIMAGE_SECTION_HEADER Section_Header = (PIMAGE_SECTION_HEADER)((DWORD)Option_header + File_header->SizeOfOptionalHeader);
printf("Section_Header:%x\n", Section_Header);
for (size_t i = 0; i < File_header->NumberOfSections; i++)
{
printf("\t-----------------------节表%d-----------------------\t\n", i+1);
printf("Section_Header->Name名称:%s\n", Section_Header->Name);
printf("Section_Header->Misc(内存中的大小--没对齐前的真实尺寸):%.8x\n", Section_Header->Misc);
printf("Section_Header->VirtualAddress(内存中的地址,需要加上imagebase,内存中的偏移):%.8x\n", Section_Header->VirtualAddress);
printf("Section_Header->SizeOfRawData(在文件中的尺寸,大小):%.8x\n", Section_Header->SizeOfRawData);
printf("Section_Header->PointerToRawData(在文件中的偏移):%.8x\n", Section_Header->PointerToRawData);
printf("Section_Header->PointerToRelocations(重定位表个数):%.8x\n", Section_Header->PointerToRelocations);
printf("Section_Header->PointerToLinenumbers(行号表的位置):%.8x\n", Section_Header->PointerToLinenumbers);
printf("Section_Header->NumberOfLinenumbers(行号数量):%.8x\n", Section_Header->NumberOfLinenumbers);
printf("Section_Header->Characteristics(节属性):%.8x\n", Section_Header->Characteristics);
Section_Header++;
}
free(file_buffer);
}
///20221120获取pe文件结构
int main(void)
{
Funcation4();
return 0;
}