首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >提取PE32头信息

提取PE32头信息
EN

Code Review用户
提问于 2015-09-29 18:02:59
回答 1查看 159关注 0票数 6

上下文信息

我编写了一个程序,将一个可执行文件(主要是.exe,.dll )映射到程序的内存空间,这样可以更容易地提取PE头信息。我通过简单地将某个头的结构转换到映射文件的内存位置来提取信息。

我想要什么

可读性和一般结构。有些命名是可怕的,我不知道哪一个是正确的选择。主要功能看起来好像因为某种原因到处都是,感觉很难读懂。当然,还有其他的事情,我肯定有很多不好的事情我没有意识到。

pe32inf.c

代码语言:javascript
复制
#include <windows.h>
#include <stdio.h>
#include "pe32inf.h"

void Terminate(const char *s);
LPCTSTR DecodeInput(int argc, char *argv[]);
LPVOID Map(LPCTSTR lpFileName);
MZ_DOS SetDOSheader(LPVOID lpFileBase);
COFF SetCOFFheader(LPVOID lpCOFFoffset);
SectionTable SetSectionTable(LPVOID SectionTableOffset, int NumberOfSections);


int main(int argc, char *argv[])
{
    LPCTSTR lpFileName;
    LPVOID lpFileBase;
    MZ_DOS DOSheader; //Naming issues with the headers.
    COFF COFFheader;
    OptionalHeader OPTheader; //I tried to get around the 2 declarations because 1 is going to be unused.
    OptionalHeader64 OPTheader64; //However, I can only think of malloc and then there's inconsistency since this will be a PTR.
    SectionTable SECtable;

    lpFileName = DecodeInput(argc, argv);
    lpFileBase = Map(lpFileName);

    DOSheader = SetDOSheader(lpFileBase); 
    COFFheader = SetCOFFheader(lpFileBase + DOSheader.pe_offset + 0x4); //0x4 To skip PE sig.

    LPVOID lpOptionalHeader = lpFileBase + DOSheader.pe_offset + 0x4 + sizeof(COFF);
    WORD magic = *(WORD*)lpOptionalHeader; 
    if (magic == 0x10b) { //PE32
        OPTheader = *(OptionalHeader*)lpOptionalHeader;
    } else if (magic == 0x20b) { //PE32+
        OPTheader64 = *(OptionalHeader64*)lpOptionalHeader;
    } else {
        Terminate("Unknown PE magic.");
    }

    LPVOID SectionTableOffset = lpOptionalHeader + COFFheader.SizeOfOptionalHeader;
    SECtable = SetSectionTable(SectionTableOffset, COFFheader.NumberOfSections);

    return 0;
}

COFF SetCOFFheader(LPVOID lpCOFFoffset)
{
    COFF COFFheader;
    COFFheader = *(COFF*)lpCOFFoffset;
    return COFFheader;
}

SectionTable SetSectionTable(LPVOID SectionTableOffset, int NumberOfSections)
{
    SectionTable SECtable;
    SECtable.NumberOfSections = NumberOfSections;
    SECtable.sectionHeader = malloc(sizeof(SectionHeader) * SECtable.NumberOfSections);

    for (int i = 0; i < SECtable.NumberOfSections; i++) {
        SECtable.sectionHeader[i] = *(SectionHeader*)(SectionTableOffset + (i * sizeof(SectionHeader)));
    }

    return SECtable;
}

MZ_DOS SetDOSheader(LPVOID lpFileBase)
{
    MZ_DOS DOSheader = *(MZ_DOS*)lpFileBase;
    if (DOSheader.signature != 0x5a4D) { //MZ
        Terminate("MZ signature not found. File is not an executable image.");
    }
    if (*(DWORD*)(DOSheader.pe_offset + lpFileBase) != 0x4550) { //PE\0\0
        Terminate("PE signature not found. File is not an executable image.\n");
    }

    return DOSheader;
}

LPCTSTR DecodeInput(int argc, char *argv[]){
    if (argc < 2) {
        Terminate("No file name specified.");
    }

    LPCTSTR lpFileName = argv[argc - 1];
    if (lpFileName == NULL) {
        Terminate("I mean, it probably won't even be NULL.");
    }

    return lpFileName;
}

LPVOID Map(LPCTSTR lpFileName)
{
    HANDLE hFile;
    HANDLE hFileMapping;
    LPVOID lpFileBase;

    hFile = CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ,
                       NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        Terminate("Could not open file.\n");
    }

    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY,
                                     0, 0, NULL);
    if (hFileMapping == NULL) {
        Terminate("Could not create Mapping.\n");
    }

    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if (lpFileBase == NULL) {
        Terminate("Could not Map view of file.\n");
    }

    return lpFileBase;  
}

void Terminate(const char *s) 
{
    //Windows will take care of closing the handles. *gasp*
    printf("%s", s);
    exit(0);
}

pe32inf.h

代码语言:javascript
复制
#include <WinDef.h>

typedef struct //http://www.delorie.com/djgpp/doc/exe/
{
    WORD signature; /* == 0x5a4D */
    WORD bytes_in_last_block;
    WORD blocks_in_file;
    WORD num_relocs;
    WORD header_paragraphs;
    WORD min_extra_paragraphs;
    WORD max_extra_paragraphs;
    WORD ss;
    WORD sp;
    WORD checksum;
    WORD ip;
    WORD cs;
    WORD reloc_table_offset;
    WORD overlay_number;
    BYTE padding[0x1F];
    DWORD pe_offset;
} MZ_DOS;

typedef struct
{
    WORD Machine;
    WORD NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD SizeOfOptionalHeader;
    WORD Characteristics;
} COFF;

typedef struct
{
    WORD Magic;
    BYTE MajorLinkerVersion;
    BYTE MinorLinkerVersion;
    DWORD SizeOfCode;
    DWORD SizeOfInitializedData;
    DWORD SizeOfUninitializedData;
    DWORD AddressOfEntryPoint;
    DWORD BaseOfCode;
    DWORD BaseOfData;
} StandardFields;

typedef struct
{
    WORD Magic;
    BYTE MajorLinkerVersion;
    BYTE MinorLinkerVersion;
    DWORD SizeOfCode;
    DWORD SizeOfInitializedData;
    DWORD SizeOfUninitializedData;
    DWORD AddressOfEntryPoint;
    DWORD BaseOfCode;
} StandardFields64;

typedef struct
{
    DWORD ImageBase;
    DWORD SectionAlignment;
    DWORD FileAlignment;
    WORD MajorOperatingSystemVersion;
    WORD MinorOperatingSystemVersion;
    WORD MajorImageVersion;
    WORD MinorImageVersion;
    WORD MajorSubsystemVersion;
    WORD MinorSubsystemVersion;
    DWORD Win64VersionValue;
    DWORD SizeOfImage;
    DWORD SizeOfHeaders;
    DWORD CheckSum;
    WORD Subsystem;
    WORD DllCharacteristics;
    DWORD SizeOfStackReserve;
    DWORD SizeOfStackCommit;
    DWORD SizeOfHeapReserve;
    DWORD SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;
} WindowsFields;

typedef struct
{
    DWORDLONG ImageBase;
    DWORD SectionAlignment;
    DWORD FileAlignment;
    WORD MajorOperatingSystemVersion;
    WORD MinorOperatingSystemVersion;
    WORD MajorImageVersion;
    WORD MinorImageVersion;
    WORD MajorSubsystemVersion;
    WORD MinorSubsystemVersion;
    DWORD Win64VersionValue;
    DWORD SizeOfImage;
    DWORD SizeOfHeaders;
    DWORD CheckSum;
    WORD Subsystem;
    WORD DllCharacteristics;
    DWORDLONG SizeOfStackReserve;
    DWORDLONG SizeOfStackCommit;
    DWORDLONG SizeOfHeapReserve;
    DWORDLONG SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;
} WindowsFields64;

typedef struct
{
    IMAGE_DATA_DIRECTORY ExportTable;
    IMAGE_DATA_DIRECTORY ImportTable;
    IMAGE_DATA_DIRECTORY ResourceTable;
    IMAGE_DATA_DIRECTORY ExceptionTable;
    IMAGE_DATA_DIRECTORY CertificateTable;
    IMAGE_DATA_DIRECTORY BaseRelocationTable;
    IMAGE_DATA_DIRECTORY Debug;
    IMAGE_DATA_DIRECTORY Architecture;
    IMAGE_DATA_DIRECTORY GlobalPTR;
    IMAGE_DATA_DIRECTORY TLStable;
    IMAGE_DATA_DIRECTORY LoadConfigTable;
    IMAGE_DATA_DIRECTORY BoundImport;
    IMAGE_DATA_DIRECTORY IAT;
    IMAGE_DATA_DIRECTORY DelayImportDescriptor;
    IMAGE_DATA_DIRECTORY CLRruntimeHeader;
    IMAGE_DATA_DIRECTORY Reserved;
} DataDirectories;

typedef struct
{
    StandardFields standardFields;
    WindowsFields windowsFields;
    DataDirectories dataDirectories;
} OptionalHeader;

typedef struct
{
    StandardFields64 standardFields; //Naming issue?
    WindowsFields64 windowsFields;
    DataDirectories dataDirectories;
} OptionalHeader64;

typedef struct
{
    DWORDLONG Name;
    DWORD VirtualSize;
    DWORD VirtualAddress;
    DWORD SizeOfRawData;
    DWORD PointerToRawData;
    DWORD PointerToRelocations;
    DWORD PointerToLinenumbers;
    WORD NumberOfRelocations;
    WORD NumberOfLinenumbers;
    DWORD Characteristics;
} SectionHeader;

typedef struct
{
    int NumberOfSections;
    SectionHeader *sectionHeader;
} SectionTable;
EN

回答 1

Code Review用户

回答已采纳

发布于 2015-09-29 19:12:02

  • pe32.h由于您调用了Windows,因此有理由期望该程序以Windows平台为目标。您确实应该利用ImageHlp API接口构筑物构筑物,而且在任何情况下都不依赖第三方5岁的文档。
  • 复制结构似乎不合理。数据已经在内存中,所以设置指针就足够了。例如: COFF * COFFheader;.COFFheader * SetCoffHeader (lpFileBase,偏移){返回(COFFheader *) (lpFileBase+偏移);}同样适用于其他结构。
  • 神奇的数字,我的意思是,0x4,根据评论,它是PE签名的大小。我建议显式定义一个struct PE_signature,取其sizeof并删除注释。
  • 空指针算法LPVOID被定义为typedef void *LPVOID;。我感到惊讶的是,lpFileBase + smth竟然会编译。
  • 命令行解析--我不认为lpFileName == NULL是可能的。
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/106037

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档