windows内核基础5——手写PE文件
PE头的顺序为:
dos头,pe标识符,文件头,可选头,节表
1.首先来构造IMAGE_DOS_HEADER结构
该结构的大小为40h字节
在IMAGE_DOS_HEADER结构中最关键的字段只有两个,就是第一个表示MZ标识头和最后一个指向PE标识符的偏移。

第一个字段占两个字节,最后一个字段占4个字节,采用小端方式存储字节.
2.构造PE标识符
PE标识符占4个字节,所以再增加4个字节的大小,并修改前两个字节为5045

3.构造IMAGE_FILE_HEADER结构体
该结构体大小为14h字节,
Machine取值为4c01,标识i386的cpu
NumberofSections取值为0300,表示该PE文件为3字节
SizeofOptionalHeader字段取值为e000,表示再win32环境下可选头的大小,
Characteristics取值为0301,表示没有重定位信息的3位平台的可执行文件
其他的字段默认为00就可以.

4.构造IMAGE_OPTIONAL_HEADER结构体
这个结构体比较大,它是PE文件格式中最重要的结构体之一



5.构造IMAGE_SECTION_HEADER结构
这样子的节表项一共有3个,一个的大小为40字节,三个就是120字节,

6.数据0的填充
PE文件格式的头部到此填充完毕,再IMAGE_OPTIONLA_HEADER结构体中,SizeofHeader字段的值是0x00001000,因此为了对齐需要将头部的大小用0补齐,所以还需要插入0x0e50个字节.

再填充完PE文件头部后,需要继续填充0x00001000字节的0字符,该0x00001000字节用来存放text节的内容,
7.填充data节的数据
data节用来保存程序运行时弹出的提示对话框中显示的字符串,用MessageBox函数来实现.MessageBox函数的第二个和第三个参数分别是两个字符串,第二个是对话框中显示的字符串,第三个是对话框标题显示的字符串,所以这里先插入4096个0字符。

并在2000地址处填写如上字符串。
8.填充.idata节的数据
idata节用来保存PE文件中最重要的两个部分,即导入表和导入地址表。在填充之前,先进行分析。
导入表和导入地址表的地址分别由数据目录给出,在数据目录中,导入表的RAV为0x00003010,导入地址表的RVA 为0x00003000.
由于本例中PE文件的RAV和FOA地址相同,不需要进行转换,接下来插入4096字节的0,并构造导入表和导入地址表。
在本例中需要导入两个DLL文件,因此需要构造3个_IMAGE_IMPORT_DESCRIPTOR,因为导入表需要有一个全0的IMAGE_IMPORT_DESCRIPTOR 来结束。
在本例中导入了两个dll文件,分别是user32.dll和kernel32.dll。在user32.dll中调用了MessageBoxA函数,在kernel32.dll中调用了Exitprocess函数。
先来构造user32.dll的导入信息,按照IMAGE_IMPORT_DESCRIPTOR结构体进行构造。
- 在0x00003050地址处构造导入表的Name字段的值“user32.dll”
- 在0x00003060地址处构造导入表的OriginalFirstThunk字段的值“0x00003070”
- OriginalFirstThunk指向一个IMAGE_THUNK_DATA,在高位不为1的情况下,指向一个IMAGE_IMPORT_BY_NAME结构体。
- 在0x00003070地址处根据IMAGE_IMPORT_BY_NAME结构体构造导入函数的名称。
- 0x00003000地址处是导入地址表,该值由FirstThunk来指向,当在磁盘中时,该值与OriginalFirstThunk相同。


用lordpe打开该exe文件可以看到已经能够识别出为pe文件。
9.填充text节的数据

浙公网安备 33010602011771号