首页 > 代码库 > 手写PE文件(一)
手写PE文件(一)
DOS Header(IMAGE_DOS_HEADER)->64 Byte
DOS头部
DOS Stub 112字节
"PE"00(Signature) 4个字节
IMAGE_FILE_HEADER 20个字节
PE文件头 IMAGE_OPTIONAL_HEADER32 96个字节
数据目录表 16*8=128个字节
IMAGE_SECTION_HEADER 40个字节
块表 IMAGE_SECTION_HEADER 40个字节
IMAGE_SECTION_HEADER 40个字节
.text 512个字节
块 .rdata 512个字节
.data 512个字节
COFF 行号
调试信息 COFF符号表
Code View调试信息
1这部分可以使读者对PE文件整体结构有一个大概了解。
2方便审查自己的构造进度 本次构造的PE文件总共有3个块,他们分别用来存放可执行代
码,输入表信息,以及全局变量,接触过PE文件的朋友对区块的概念应该不陌生,我们知道windows下的很多应用程序的文件对齐制度,也就是大名鼎鼎的FileAlignment字段的值最多200个字节,也就是十进制的512字节,对于不足512个字节的,要填充00补完512个字节,对于超过512个字节,要多分配512个字节
本例中的PE文件头64+112+4+20+224+40*3=544个字节但是显然要填充到1024个字节,整个文件体积就是512*2(PE文件头)+512*3(块)=2560个字节,这也就是我们构造的PE文件总的大小
提前搞清一些字段与区段的偏移量也是比较重要的,
1 PE文件头开始位置B0
2 IMAGE_OPTIONAL_HEADER32开始处000000C8h
3 数据目录表开始处 00000128h
4 块表开始处 000001A8h
5 .text区段开始处 00000400
6 .rdata区段开始处 00000600
7 .data区段开始处 00000800
二:重点字段的介绍
1 DOS头部
1-1 DOS Header
1-1-1 e_magic[WORD]-->4D5A(DOS可执行文件头标记)
1-1-19 e_lfanew[WORD]->BO OO OO OO (指定PE文件头的偏移量64+112)
2 PE文件头
2-1 "PE"00
2-1-1 Signature[DWORD]-->50450000(PE文件头标记)
注释:此处的值总为0000h
2-2 IMAGE_FILE_HEADER
2-2-1 Machine[DWORD]--->4C 01(可执行文件的目标CPU类型)
注释:次PE文件运行于哪个CUP下,其标志就为相应的值
interl i386 14C h MIPS R3000 162h
MIPS R4000 166h Alpha AXP 184h
Power PC 1F0h
2-2-2 NumberOfSections[WORD]--->03 00区段数目
注释:此值取决于PE文件的区块数目,本程序为3个区段
2-2-3 SizeOfOptionalHeader[WORD]--->E0 00(PE 可选头大小)
注释:此值表示PE可选头的大小
2-2-7 Characteristics[WORD]--->OF O1(文件属性)
注释: 此值为文件的执行属性,EXE文件的属性一般为010Fh,DLL文件般
为0210h
2-3 IMAGE_OPTIONAL_HEADER
2-3-1 Magic[WORD]--->OB 01(*标记字)
注释:此处是一个标记字,用于描述PE文件的映像类型,ROM映像0107h,普通可
执行映像010Bh,PE32+则是020Bh。
2-3-7 AddressOfEntryPoint[DWORD]--->00 10 00 00(*程序执行入口)
注释:通俗的讲就是指向可执行代码区块(.text)的首地址
2-3-10 ImageBase[DWORD]--->00 00 40 00(*程序默认装入基地址)
2-3-11 SectionAlignment[DWORD]-内存中的对齐大小,也叫做块粒度,其默认值是CPU页大小
2-3-12 FileAlignment[DWORD]--->00 02 00 00(*文件区中区块对齐值)
注释: 磁盘上的PE文件的区块对齐大小,这个值必须是2的幂,并且最小是200h
2-3-17 MajorSubsystemVersion[WORD]--->04 00(*运行所需最低子系统主版本号)
注释:要求最低的子系统主版本号,一般情况下为4
2-3-18 MinorSubsystemVersion[WORD]--->00 00(*运行所需最低子系统次版本号)
注释:要求最低的子系统次版本号,一般情况下都为0
2-3-20 SizeOfImage[DWORD]--->00 40 00 00(映像装入内存后总尺寸)
注释:指的是装入文件从Image Base到最后一个区块大小
2-3-21 SizeOfHeaders [DWORD]--->00 04 00 00(*DOS头 PE头,区块表的总大小)
注释:指的是DOS头,PE头与区块表的总大小,并且所有这些项目都是出现在PE文件中任何代码和数据之前,此值遵循文件对齐制度
2-3-23 Subsystem[WORD]--->03 00(*文件子系统)
注释:标明可执行文件所期望的子系统
2-3-30 NumberOfRvaAndSizes[DWORD]--->10 00 00 00(数据目录表的项数,默认值16)
注释:数据目录的项数,这个自动从NT系统发布以来就是16
2-4 数据目录表
2-4-2 Import Table
注释:输入表
2-4-2-1 VirtualAddress[DWORD]--->10 20 00 00(*数据块起始RAV)
注释:输入表的起始地址,要去除IAT所占空间,直接从第一个IID开始
2-4-2-2 Size[DWORD]--->3C 00 00 00 (*数据块大小)
注释:从第一个IID到最后一个IMAGE_IMPORT_BY_NAME的总长度
3 块表
3-1 IMAGE_SECTION_HEADER(1.text)
3-1-1 Name[BYTE]--->2E 74 65 78 74 00 00 00(*8个字节的块名)
注释:此区块的名称,限制在8个字节内
3-1-2 VirtualSize[DWORD]--->26 00 00 00(被实际使用的区块大小)
注释:此区块包含数据的大小
3-1-10 Characteristics[DWORD]--->20 00 00 60(该区块的读写执行属性)
*----------------------------------------------------------------*
| 字段值 | 用 途 |
-----------------------------------------------------------------
| 00000020h | 包含代码,常与10000000h一起设置 |
-----------------------------------------------------------------
| 00000040h | 包含已初始化数据 |
-----------------------------------------------------------------
| 00000080h | 包含未初始化数据 |
-----------------------------------------------------------------
| 02000000h | 可以被丢弃 |
-----------------------------------------------------------------
| 10000000h | 共享块 |
-----------------------------------------------------------------
| 20000000h | 可执行 |
-----------------------------------------------------------------
| 40000000h | 可读 |
-----------------------------------------------------------------
| 80000000h | 可写 |
-----------------------------------------------------------------
4 块
4-1 .text(*此区段是一段汇编代码的16进制形式,功能是弹出一个MessageBox提示框)
6A 00 68 00 30 40 00 68 07 30 40 00 6A 00 E8 07 00 00 00 6A 00 E8 06 00 00 00 FF 25 08 20 40 00 FF 25 00 20 40 00
4-2 .rdata (该区块包含输入表)
4-2-1 IMAGE_THUNK_DATA32(IAT1)
注释:其实IMAGE_THUNK_DATA32是一个联合体,可以同时代表IAT和INT
4-2-1-1 AddressOfData[DWORD]--->76 20 00 00(*指向IMAGE_IMPORT_BY_NAME的RVA)
注释:作为IAT时我们就使用它的成员AddressOfData成员,用来存放指向IMAGE_IMPORT_BY_NAME的RVA,当程序装入内存后,只与IAT交换信息,输入表的其他部分就不再需要了。[由于本例子中两个API引自两个不同DLL中,所以要补充00 00 00 00结束]
4-2-3 IMAGE_IMPORT_DESCRIPTOR(IID 1)
注释:这里稍微复杂些,它的作用是使用INT指定某个DLL文件中的API函数,并配合IAT指向相关API的地址
4-2-3-1 OriginalFirstThunk[DWORD]--->4C 20 00 00(*指向输入名称表INT的RVA)
注释:这里指定某个DLL中API函数
4-2-3-4 Name[DWORD]--->6A 20 00 00(指向DLL名字的RVA与指针)
注释:这里指定某个系统DLL
4-2-3-5 FirstThunk[DWORD]--->08 20 00 00(指向输入地址表的IAT的RVA)
注释:这里指定相关的IAT,并由IAT在IMAGE_IMPORT_BY_NAME中获得相应API的地址
4-2-4 IMAGE_IMPORT_DESCRIPTOR(IID 2)
4-2-4-1 OriginalFirstThunk [DWORD]--->54 20 00 00(*指向输入名称表INT的RVA)
4-2-4-4 Name [DWORD]--->84 20 00 00(*指向DLL名字的RVA与指针)
4-2-4-5 FirstThunk [DWORD]--->00 20 00 00(*指向输入地址表IAT的RVA)
[填充20个00h空字节做结尾标记]
4-2-5 IMAGE_THUNK_DATA32(INT 1)
4-2-5-1 ForwarderString [DWORD]--->5C 20 00 00
注释:直接指向相关API函数
【由于本例子中两个API函数引自两个不同的DLL中,所以要补充00 00 00 00结束】
4-2-7 IMAGE_IMPORT_BY_NAME(1)
4-2-7-2 Name[BYTE]--->4D 65 73 73 61 67 65 42 6F 78 41(MessageBoxA的16进制码)
注释:相关API函数的16进制码
【后面跟输出函数的DLL名称16进制码00 75 73 65 72 33 32 2E 64 6C 6C 00 00 user32.dll】注释:相关系统的API函数罗列完毕后,通常在最后一个AIP后面加00,并跟着DLL名称的16进制数据
三 PE文件结构字段清单
1 DOS头部
1-1 DOS Header
1-1-1 e_magic [WORD]---> 4D 5A(*DOS可执行文件头标记)
1-1-2 e_cblp [WORD]---> 00 00(文件最后页的字节数)
1-1-3 e_cp[WORD]--->00 00(文件页数)
1-1-4 e_crlc[WORD]--->00 00(重定位元素个数)
1-1-5 e_cparhdr[WORD]--->00 00(以段落为单位的头部大小)
1-1-6 e_minalloc[WORD]--->00 00(所需的最小附加段)
1-1-7 e_maxalloc[WORD]--->00 00(所需的最大附加段)
1-1-8 e_ss[WORD]--->00 00(初始的堆栈段(ss)相对偏移量)
1-1-9 e_sp[WORD]--->00 00(初始的堆栈指针(SP)值)
1-1-10 e_csum[WORD]--->00 00(校验和)
1-1-11 e_ip[WORD]--->00 00(初始的指令指针(IP)值)
1-1-12 e_cs[WORD]--->00 00(初始的代码段(CS)的偏移量)
1-1-13 e_lfarlc[WORD]--->00 00(重定位表在文件中的偏移量)
1-1-14 e_ovno[WORD]--->00 00(覆盖号)
1-1-15 e_res[WORD]--->00 00(保留字,一般都为确保对齐而保留)
1-1-16 e_oemid[WORD]--->00 00(OEM标识符,相对于e_oemid)
1-1-17 e_oeminfo[WORD]--->00 00(OEM信息,即OEM细节)
1-1-18 e_res[WORD]--->00 00(保留字,一般为对齐而保留)
1-1-19 e_lfanew[DWORD]--->B0 00 00 00(指向PE文件头的偏移量,BO=64+112)
2 PE文件头
2-1 PE 00
2-1-1 Signature[DWORD]--->50 45 00 00(*PE文件头标记)
2-2 IMAGE_FILE_HEADER
2-2-1 Machine[WORD]--->4C 01(可执行文件的目标CPU类型)
2-2-2NumberOfSections[WORD]--->03 00区块数目
2-2-3TimeDateStamp [DWORD]--->00 00 00 00(文件创建时间和日期)
2-2-4 PointerToSymbolTable[DWORD]---->00 00 00 00(指向符号表,用于调试)
2-2-5 NumberOfSymbols[DWORD]--->(符号表中的符号个数,用于调试) 00 00 00 00
2-2-6 SizeOfOptionalHeader[WORD]--->E0 00(PE头IMAGE_OPTIONAL_HEADER32)大小
2-2-7 Characteristics [WORD]--->OF O1 (*文件属性)
2-3 IMAGE_OPTIONAL_HEADER32
手写PE文件(一)