1. PE结构1
Portable Executable file format
从命名上看,微软想让PE文件可移植。
注意,虽然IMAGE_OPTIONAL_HEADER结构体总大小0xE0字节,但IMAGE_OPTIONAL_HEADER结构体的最后是数组,数组中究竟有几个元素,可以手动修改。
所以是exe的中IMAGE_OPTIONAL_HEADER究竟占多少字节,是由IMAGE_FILE_HEADER结构体中的WORD SizeOfOptionalHeader字段决定的。大小可以小于0xE0,也可以大于0xE0。例如改为F0,然后增加0x10字节,再删除无关位置的0x10字节,依然可运行。
IMAGE_OPTIONAL_HEADER中的
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
以及
DWORD BaseOfCode;
DWORD BaseOfData;
都是说明性自字段,可以自由更改。如果前3个改成0x0CCCCCCC之类的能成功分配内存大小的数值,OD会当成代码真有这么大,分析时很慢。如果数值太大,不能分配这么大的内存,OD会采用其他方案。
文件地址FA
虚拟地址VA
相对虚拟地址RVA,是相对于模块基址的偏移
DWORD AddressOfEntryPoint是相对虚拟地址RVA,相对于image base。将其改为2,启动后可执行IMAGE_DOS_HEADER里的代码,但修改后的程序在win10上无法启动,XP上可以运行,但可能要改内存保护属性。
DWORD ImageBase是首选装载地址,可以改,但对内存进行绝对访问的代码也要修复。
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion; //可以改
BYTE MinorLinkerVersion; //可以改
DWORD SizeOfCode; //说明性
DWORD SizeOfInitializedData; //说明性
DWORD SizeOfUninitializedData; //说明性
DWORD AddressOfEntryPoint; //RVA
DWORD BaseOfCode; //说明性
DWORD BaseOfData; //说明性
//
// NT additional fields.
//
DWORD ImageBase; //首选装载地址,可以改,但对内存进行绝对访问的代码也要修复
DWORD SectionAlignment; //加载到内存中节的对齐值
DWORD FileAlignment; //文件对齐值
WORD MajorOperatingSystemVersion; //说明性
WORD MinorOperatingSystemVersion; //说明性
WORD MajorImageVersion; //说明性
WORD MinorImageVersion; //说明性
WORD MajorSubsystemVersion; //Subsystem的版本,后面字段还有类型
WORD MinorSubsystemVersion; //说明性
DWORD Win32VersionValue; //MSDN说保留成员,必须为0,win10,xp测试也不行,老师的xp可以
DWORD SizeOfImage; //加载到内存后占多少字节,必须是SectionAlignment的倍数,随便改会错
DWORD SizeOfHeaders; //所有头部的大小(文件中),例如0x400
DWORD CheckSum; //驱动,系统关键dll会做检测,普通PE不检测
WORD Subsystem; //链接时指定的子系统GUI,CUI,NATIVE等,改后可改窗口程序为控制台
WORD DllCharacteristics; //针对所有PE文件的,例如IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
DWORD SizeOfStackReserve; //栈保留内存,可以改,数值要在正常范围
DWORD SizeOfStackCommit; //栈提交内存,可以改,数值要在正常范围
DWORD SizeOfHeapReserve; //堆保留内存,可以改,数值要在正常范围
DWORD SizeOfHeapCommit; //栈提交内存,可以改,数值要在正常范围
DWORD LoaderFlags; //MSDN说该成员已过时
DWORD NumberOfRvaAndSizes; //目录条目数
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;