第13章:PE文件格式(4)--TinyPe分析
TinyPe是为了挑战做出更小的PE文件而出现的,现在对它进行分析.从书上的网站中找到网址并下载.
可以看到这个PE文件的大小已经被减少到了84H字节.
且可以正常运行:
PE知识可知:DOS头的大小为40字节,NT头为F8字节,此处必然进行了删减和覆盖.
先观察DOS头,由于DOS头的数据中,重要的成员就2个,DOS签名(MZ)和NT头的偏移.
此处 e_lfanew的地址是 3C字节 处:此处值为4. 而 DOS存根 被人为删减掉了.
PE出现的位置也确实是在第4个字节处.
下面分析NT头中的文件头:
第2个成员 machine 码为0x14c,表明为intel 386的CPU.
第3个成员 NumberOfSections ,此处显示为1.
第4个成员 TimeDateStamp 、第5个成员 PointerToSymbolTables (指向符号表(主要用于调试))和第6个成员 NumberOfSymbols (符号表中符号的个数), 被 user32.dll(导入函数名) 占据.
第7个成员 SizeOfOptionalHeader 值为40.
第8个成员 Characteristics 值为10F,表明是32位字的机器,且重定位表、LineNumbers、本地符号表被删除,文件可执行。
下面分析NT头中的可选头(找到10b/20b即可):图中只标明了PE文件应该占有的值
在X64dbg中查看:
如图,只有7C这一个地方改变了.从前面的知识可以知道,PE装载器会将获得的函数地址放在IAT数组值中.而存放IAT地址的就是FirstThunk.
于是发现在6C处存放着7C的地址,6C处即是FirstThunk.往前推,68H处存储着0C,而0C处存储着库名称字符串,因此可以确定,从5C开始,就是IID结构体.
该IID结构体的内容为:
Address |
SIZE |
NAME |
VALUE |
5C |
DWORD |
OriginalFirstThunk |
0 |
60 |
DWORD |
TimeDateStamp |
FF0002 |
64 |
DWORD |
ForwarderChain |
7C |
68 |
DWORD |
Name1 |
C |
6C |
DWORD |
FirstThunk |
7C |
接着,存储着IID结构体地址的是DataDirectory[1].VirtualAddress(5C)------84
可以看到它的Size被省略掉了,且Address只有一个字节.
至此,整理清楚了基本上所有的问题.
总结一下:
1#.Dos头可以只保留MZ和e_lfanew. Dos存根可以不要
2#.文件头可以只保留machine, NumberOfSections, SizeOfOptionalHeader, Characteristics
3#.可选头删除 Major/Minor LinkerVersion , CheckSum,Subsystem,DllCharacteristics,SizeOfStack Reverse/Commit.
4#.ExportDirectory.VirtualAddress不能省,改为0后无法运行. 原因在于:本来作为一个程序导出表应该为0,但是此处是用作存储 FirstThunk 。
5#.ImportDirectory.Size可以省,VirtualAddress可以只保留一个字节.