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;
}

 

posted @ 2022-11-20 18:56  逆向菜狗  阅读(105)  评论(0编辑  收藏  举报