静态分析基础:PE文件结构解析
说实话,我做了这么多年逆向,见过太多新手一上来就开调试器。结果呢?被反调试搞得晕头转向。我的建议是——先静下来,好好看看PE文件结构。
PE文件,全称Portable Executable。Windows下的可执行文件格式。你看到的exe、dll、sys,都是它。理解PE结构,就像医生看懂人体骨骼。不懂?那你分析恶意软件就是在瞎蒙。
DOS头:老古董,但必须懂
每个PE文件开头,都有一个DOS头。为什么?为了兼容性。Windows为了能跑老旧的DOS程序,保留了这玩意儿。
DOS头结构体叫IMAGE_DOS_HEADER。关键字段就两个:
e_magic:固定值0x5A4D,也就是"MZ"。我见过有人拿这个判断是不是PE文件,其实不够严谨。e_lfanew:偏移量,指向真正的NT头。这个才是关键。
核心要点:DOS头不是摆设。有些恶意软件会篡改e_lfanew字段,让你找不到NT头。我曾经分析过一个样本,它把e_lfanew指向了一个伪造的NT头,真正的藏在后面。嗯,这招挺阴的。
NT头:PE文件的心脏
顺着e_lfanew找到的,就是NT头。结构体是IMAGE_NT_HEADERS。它包含三部分:
| 字段 | 说明 | 我的经验 |
|---|---|---|
| Signature | 固定值0x00004550,即"PE\0\0" |
检查这个,确认是PE文件 |
| FileHeader | 文件头,描述文件基本信息 | 重点关注Machine字段,判断是32位还是64位 |
| OptionalHeader | 可选头,其实必选。包含入口点、镜像基址等 | 入口点AddressOfEntryPoint,恶意软件常修改这里 |
FileHeader里的NumberOfSections字段,告诉你这个PE文件有多少个节。节是什么?往下看。
个人技巧:我习惯先看OptionalHeader里的Subsystem字段。如果是2(GUI),说明是窗口程序;如果是3(控制台),那就是命令行程序。恶意软件常用GUI来隐藏窗口。
节表:代码和数据的地图
节表紧跟在NT头后面。每个节对应一个IMAGE_SECTION_HEADER结构体。关键字段:
Name:节名,比如.text、.data、.rdataVirtualAddress:内存中的偏移地址SizeOfRawData:文件中对齐后的大小PointerToRawData:在文件中的偏移Characteristics:属性标志,可读、可写、可执行
你想想看,恶意软件经常在节表上做手脚。比如:
- 把代码藏在
.data节里,然后修改属性为可执行 - 创建自定义节名,比如
.upx0、.themida,一看就是加壳了 - 节的对齐大小异常,比如文件对齐和内存对齐不一致
避坑指南:我曾经遇到一个样本,它的.text节SizeOfRawData是0。什么意思?代码不在文件里,运行时动态解密。这种样本,静态分析只能看到个壳,必须动态调试。
用DIE和PE-bear查看文件信息
理论说完了,来点实战。我常用的工具就两个:DIE(Detect It Easy)和PE-bear。
DIE:快速识别加壳类型。打开一个样本,DIE直接告诉你"UPX 3.96"或者"VMProtect 2.x"。省事。但它只能看个大概,细节不够。
PE-bear:这才是我的主力。它能完整解析PE结构,从DOS头到节表,每个字段都给你列出来。我一般这么用:
- 打开文件,先看DOS头的
e_lfanew,确认NT头位置 - 切到NT头,看入口点、镜像基址、节数量
- 逐个检查节表,看每个节的属性和大小
- 重点关注
Characteristics,有没有不该可执行的节被标记为可执行
实战案例:有一次分析勒索软件,PE-bear显示.data节有可执行属性。正常程序不会这样。我顺着这个线索,发现它在.data节里藏了一段shellcode。嗯,这就是静态分析的价值——不跑代码,就能找到问题。
知识体系结构图
下面这张图,是我自己总结的PE文件解析流程。你照着这个顺序走,基本不会漏东西。
这张图的核心逻辑就是:从上往下,逐层解析。DOS头定位NT头,NT头里找节表,节表里看属性。最后用工具验证你的判断。
我的习惯:拿到一个样本,先用DIE扫一眼,看有没有壳。如果有,记录壳的类型和版本。然后用PE-bear深入分析,重点关注入口点、节表属性和导入表。整个过程不超过5分钟。嗯,效率就是这么练出来的。
静态分析是基础,也是关键。你把这个练扎实了,后面动态分析才能事半功倍。别急着开调试器,先静下来,把PE文件读透。