首页
社区
课程
招聘
[原创]PE文件编辑器
发表于: 2013-12-2 20:11 7860

[原创]PE文件编辑器

2013-12-2 20:11
7860

概述
预备知识
    MS-DOS头
    PE文件头
        IMAGE_FILE_HEADER
        IMAGE_OPTIONAL_HEADER32
        IMAGE_DATA_DIRECTORY
            IMAGE_DIRECTORY_ENTRY_EXPORT
            IMAGE_IMPORT_DESCRIPTOR
            IMAGE_BASE_RELOCATION
        节表信息
总体设计
    不足
    改进
详细设计
    文件保存
    关联信息的修改
    文件位置计算器(FLC)
    节信息(Section)
    目录信息
        导出表
            导出表信息的展示
            导出表信息的修改
        导入表
    资源
        资源信息的获取
        资源信息的展示
    重定位信息
控件设计
    Edit控件
        信息的展示
        限制用户输入
        信息的获取
    单选框控件
    复选框与下拉框控件
        复选框的设置
        下拉框的设置
    列表控件(ListCtrl)
        列表右键弹出菜单
总结

概述
最近学习了PE文件的知识,为了加深对知识的理解,任老师给我们布置了一个任务,自己完成一个PE编辑器。在写之前还觉得挺简单,到真正开始写的时候才发现有好多东西都不是想象中那么简单,有许多需要注意的地方。也多亏了这次写PE编辑器积累的经验,在写壳时给了我很大的帮助。

先说明一下文章中用到的一些词汇,不一定用的对。
文件缓存:读取磁盘上的一个PE文件,然后将这个PE文件保存到内存中的一段空间,使用new一段堆空间,或者使用文件映射的方式都行。
区段,节:都是指Section
偏移:一个特定位置基于某个指定位置的差值
FOA(File Offset Address):数据在PE文件中的地址叫文件偏移地址。这是文件在磁盘上存放时相对于文件开头的偏移
RVA(Relative Virtual Address):相对虚拟地址是内存地址相对于映射基址的偏移量。
映射基址:PE文件被系统PE加载器加载到内存后的首地址。

预备知识
关于PE文件的知识,网上有很多资料,这里就不做深入的解释了,只说一些我写程序时遇到的问题,有一部分问题是写壳时遇到的,这里也一起总结一下。

[*]MS-DOS头
将PE文件读入内存中后,将文件缓存的首地址强制转换为IMAGE_DOS_HEADER 类型的指针就可以获取MS-DOS头的内容,在这个结构体中只需要关注两个字段e_magic 字段和e_lfanew字段

[*]e_magic字段用来检测是否有效的PE文件



[*]e_lfanew字段表示windows下PE文件头的偏移位置





[*]PE文件头
IMAGE_NT_HEADERS 用这个结构体来表示,通过MS-DOS头的e_lfanew字段的值加上文件缓存的起始地址可以获取该结构体类型的指针。
这个头在32位和64位系统上是不一样的,上面的结构体是一个宏,根据不同的编译选项生成不同的结构体

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;
    WORD    NumberOfSections;
    DWORD   TimeDateStamp;
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER {

    WORD    Magic;
    BYTE    MajorLinkerVersion;
    BYTE    MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   Name;
    DWORD   Base;
    DWORD   NumberOfFunctions;
    DWORD   NumberOfNames;
    DWORD   AddressOfFunctions;     
    DWORD   AddressOfNames;         
    DWORD   AddressOfNameOrdinals;  
} IMAGE_EXPORT_DIRECTORY;
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics; 
        DWORD   OriginalFirstThunk;
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp; 


    DWORD   ForwarderChain; 
DWORD   Name;
    DWORD   FirstThunk; 
} IMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;
    DWORD   SizeOfBlock;
//  WORD    TypeOffset[1];
} IMAGE_BASE_RELOCATION;
typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER;
/**
*@brief 将指针指向的内容保存到文件中
*/
DWORD SavePointerContent(LPVOID pContent,DWORD dwSize);
TCHAR szGet[9] = {0};
for (DWORD i=0,j=0;i<16;i++,j+=2,pData++)
{
    // 将::GetDlgItem放到GetWindow中会获取不正确
    hEdit = ::GetDlgItem(this->m_hWnd,EXPORT_RVA_EDIT+j);
    ::GetWindowText(hEdit,szGet,9);

    swscanf_s(szGet,L"%x",&dwGet);
    pData->VirtualAddress = dwGet;

    hEdit = ::GetDlgItem(this->m_hWnd,EXPORT_RVA_EDIT+j+1);
    ::GetWindowText(hEdit,szGet,9);
    swscanf_s(szGet,L"%x",&dwGet);
    pData->Size           = dwGet;
}
DWORD  AddressOfFunctions;        // RVA from base of image
DWORD  AddressOfNames;          // RVA from base of image
DWORD  AddressOfNameOrdinals;    // RVA from base of image
// 改变缓存中名称的值
memcpy_s(pName,pOri->strAPI.GetLength()+sizeof(char),
strOut,stcSave.strAPI.GetLength()+sizeof(char));

// 改变文件中的名称信息
dwOffset = (PBYTE)pName - m_pFileBuffer;
SetFilePointer(hFile,dwOffset,0,FILE_BEGIN);
WriteFile(hFile,pName,stcSave.strAPI.GetLength()+sizeof(char),
&dwWrite,NULL);
IMAGE_RESOURCE_DIRECTORY
IMAGE_RESOURCE_DATA_ENTRY
IMAGE_RESOURCE_DATA_ENTRY
…..

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (2)
雪    币: 2673
活跃值: (3560)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
2
看来A1Pass师兄教学质量不错...
2013-12-2 20:31
0
雪    币: 209
活跃值: (271)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
缺个导入表编辑工具,下载下来看看,谢谢楼主
2019-9-21 13:46
0
游客
登录 | 注册 方可回帖
返回