4、静态分析基础:文件类型识别、字符串提取、哈希计算、PE头解析、导入表与导出表分析
静态分析是恶意代码分析的起点,也是整个分析流程中最安全、最可控的环节。它不执行样本,而是通过检查文件的二进制结构、元数据、字符串和代码特征来获取情报。对于Windows平台下的恶意软件,PE(Portable Executable)格式是绕不开的核心。本章将围绕五个基础动作展开:文件类型识别、字符串提取、哈希计算、PE头解析以及导入表与导出表分析。掌握这些技能,你就能在沙箱运行或动态调试之前,快速判断样本的“身份”和“意图”。
上图展示了静态分析五个基础步骤与PE文件内部结构的对应关系。在实际分析中,这五个动作并非严格串行,而是互相印证。例如,哈希值用于确定样本唯一性,而导入表则揭示其行为倾向。下面我们逐一深入。
4.1 文件类型识别:从魔数到真实格式
核心原理
文件扩展名是最不可信的属性。恶意代码常伪装成图片、文档或PDF。文件类型识别的本质是检查文件头部的“魔数”(Magic Number)。Windows可执行文件的魔数是MZ(0x4D 0x5A),这是DOS头的起始标记。Linux下的ELF文件以\x7FELF开头,PDF以%PDF开头。识别文件类型是后续所有分析的前提——如果样本是PowerShell脚本或VBS脚本,则无需进行PE解析。
判断方法
- 使用
file命令:Linux下最便捷的工具,能识别PE32、PE32+、MS-DOS可执行文件、安装包等。 - 十六进制查看:用
xxd或hexdump查看前64字节,人工确认魔数。 - DIE(Detect It Easy):Windows下图形化工具,能识别编译器、加壳器(如UPX、ASPack)。
# 示例:识别一个可疑文件
$ file malware.bin
malware.bin: PE32 executable (GUI) Intel 80386, for MS Windows
$ xxd malware.bin | head -2
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ..............
00000010: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......
案例拆解
某次应急响应中,分析师收到一个名为invoice.pdf.exe的文件。扩展名看似PDF,但file命令输出为PE32 executable。进一步用DIE检查,发现节区名为UPX0和UPX1,确认是UPX加壳的PE文件。这一识别结果直接决定了后续步骤:先脱壳,再分析导入表。
.txt或.jpg,也可能通过文件关联漏洞执行恶意代码。始终使用静态工具识别。
常见误区
误区一:认为file命令输出“data”就是安全的。实际上,加密或混淆后的恶意脚本常被识别为“data”。误区二:忽略复合文档格式(如Office宏病毒)。file命令可能输出Composite Document File V2 Document,此时应使用oleid或oletools进一步分析。
4.2 字符串提取:发现线索与行为暗示
核心原理
字符串是程序中的可打印字符序列。恶意代码中常包含URL、IP地址、注册表路径、文件名、命令行参数、加密密钥等关键情报。提取字符串是快速了解样本“意图”的最廉价手段。但需注意,加壳或加密的样本会隐藏真实字符串,提取结果可能只有壳的提示信息。
操作流程
- 使用
strings命令提取ASCII字符串:strings -n 8 sample.exe(仅显示长度≥8的字符串)。 - 提取Unicode字符串:
strings -el sample.exe(针对UTF-16LE编码)。 - 结合
grep过滤关键词:strings sample.exe | grep -iE "http|https|cmd|powershell|reg|mutex"。 - 使用
FLOSS(FireEye Labs Obfuscated String Solver)自动解码混淆字符串。
案例拆解
分析一个疑似远控木马时,strings输出中出现以下关键内容:
C:\Windows\System32\cmd.exe
/k ping 1.1.1.1 -t
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
http://malicious-domain.com/update.php
Mutex: Global\MyMutex_2024
这些字符串揭示了:持久化机制(注册表Run键)、C2地址(HTTP)、互斥体名称(防止多实例运行)、可能的DDoS行为(ping -t)。虽然尚未执行样本,但已能形成初步判断。
strcat或sprintf拼接URL,此时静态提取只能看到片段。可结合导入表中的sprintf、strcat函数来推测拼接逻辑。
常见误区
误区一:认为字符串越多越好。加壳样本的字符串几乎全是壳的版权信息,此时应优先脱壳。误区二:忽略字符串的上下文。例如,字符串123456可能是密码,也可能是某个加密算法的盐值。需要结合其他信息判断。
4.3 哈希计算:样本的唯一指纹
核心原理
哈希算法(MD5、SHA-1、SHA-256)将任意长度的文件映射为固定长度的摘要。哈希值用于:① 确认样本唯一性;② 在威胁情报平台(如VirusTotal)查询历史分析结果;③ 验证文件完整性。恶意代码分析中,SHA-256是主流标准,因为其碰撞概率极低。
计算方法
# Linux
sha256sum sample.exe
md5sum sample.exe
# Windows (PowerShell)
Get-FileHash sample.exe -Algorithm SHA256
Get-FileHash sample.exe -Algorithm MD5
案例拆解
在VirusTotal上提交一个勒索软件样本,其SHA-256为7f9c...a3d2。查询结果显示:该样本已被全球37家杀毒引擎标记为Trojan.Ransom.Cerber。同时,关联分析发现该哈希与2023年某次钓鱼邮件攻击中使用的样本完全一致。这为溯源提供了直接证据。
常见误区
误区一:混淆“哈希值”与“模糊哈希”。模糊哈希(如ssdeep)用于相似性比较,而非唯一性标识。误区二:在分析过程中修改了样本文件(如脱壳后),导致哈希变化。应始终保留原始样本的哈希,并在报告中注明脱壳后的新哈希。
4.4 PE头解析:理解文件骨架
核心原理
PE文件格式是Windows可执行文件的标准结构。解析PE头能获取编译时间、链接器版本、节区权限、入口点地址、目标架构(32/64位)等关键信息。PE头由DOS头、NT头(Signature + FileHeader + OptionalHeader)和节表组成。其中,e_lfanew字段(DOS头偏移0x3C)指向NT头的起始位置。
解析流程
| 偏移 | 字段 | 关键信息 |
|---|---|---|
| 0x00 | e_magic | 必须为0x5A4D(MZ) |
| 0x3C | e_lfanew | NT头偏移量 |
| e_lfanew | Signature | 必须为0x00004550(PE\0\0) |
| e_lfanew+0x04 | FileHeader.Machine | 0x014C=32位,0x8664=64位 |
| e_lfanew+0x18 | OptionalHeader.AddressOfEntryPoint | 程序入口点RVA |
| e_lfanew+0x5C | OptionalHeader.ImageBase | 首选加载基址 |
| e_lfanew+0x60 | OptionalHeader.SectionAlignment | 内存中对齐粒度 |
案例拆解
使用Python的pefile库解析一个样本:
import pefile
pe = pefile.PE("sample.exe")
print("Machine:", hex(pe.FILE_HEADER.Machine)) # 0x14c 表示32位
print("EntryPoint:", hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint))
print("ImageBase:", hex(pe.OPTIONAL_HEADER.ImageBase))
print("CompileTime:", pe.FILE_HEADER.TimeDateStamp)
for section in pe.sections:
print(section.Name.decode().rstrip('\x00'),
"VA:", hex(section.VirtualAddress),
"Size:", hex(section.Misc_VirtualSize),
"Flags:", hex(section.Characteristics))
输出显示:入口点位于0x1000,节区.text具有可执行权限,.data可读写。编译时间戳为2024-03-15,说明样本较新。若发现节区名异常(如.UPX0)或节区权限异常(如.data节可执行),则高度怀疑加壳或注入。
常见误区
误区一:混淆RVA(相对虚拟地址)与文件偏移。RVA是相对于ImageBase的地址,需通过节表转换为文件偏移才能定位数据。误区二:忽略OptionalHeader中的DataDirectory数组。该数组的第0项指向导出表,第1项指向导入表,是后续分析的关键入口。
4.5 导入表与导出表分析:窥探API调用
核心原理
导入表(Import Table)列出了PE文件运行时需要从其他DLL加载的函数。恶意代码通过导入表调用Windows API,因此导入表直接反映了样本的行为能力。例如,导入CreateRemoteThread和VirtualAllocEx暗示进程注入;导入URLDownloadToFile暗示下载执行。导出表(Export Table)则列出DLL对外提供的函数,恶意DLL的导出表可能伪装成合法DLL(如DllRegisterServer)以迷惑分析。
分析方法
- 使用
pefile库:遍历pe.DIRECTORY_ENTRY_IMPORT,获取DLL名称和导入函数。 - 使用CFF Explorer:图形化查看导入/导出表,支持排序和搜索。
- 关注“延迟导入”:某些样本使用延迟加载,只有在调用时才解析API,静态分析可能遗漏。
案例拆解
分析一个键盘记录器样本,导入表关键项如下:
| DLL | 导入函数 | 行为暗示 |
|---|---|---|
| user32.dll | GetAsyncKeyState, GetForegroundWindow | 键盘钩子、窗口监控 |
| kernel32.dll | WriteFile, CreateFileW | 文件写入(日志) |
| ws2_32.dll | send, connect | 网络发送(数据外传) |
| ntdll.dll | NtQueryInformationProcess | 反调试检测 |
这四组导入函数组合起来,几乎可以断定样本会记录键盘输入、写入本地文件并通过网络外传。进一步检查导出表,发现该样本没有导出函数,说明它是EXE而非DLL。
GetProcAddress动态获取API地址,此时导入表中只有LoadLibrary和GetProcAddress。遇到这种情况,需要结合字符串分析(如API名称字符串)和动态分析。
常见误区
误区一:认为导入表越少越安全。实际上,恶意代码可能通过LoadLibrary在运行时加载DLL,静态导入表仅显示少量API。误区二:忽略导出表。对于DLL型恶意代码(如勒索软件加载器),导出表可能包含DllMain或Start等入口函数,分析这些函数的导出序号有助于理解调用约定。
4.6 综合复盘:静态分析的局限与衔接
静态分析并非万能。加壳、混淆、动态API解析、反虚拟机技术都会削弱静态分析的效果。但作为分析流程的第一步,它能提供低成本、高安全性的情报。在实际工作中,建议将本章五个基础动作组合成“快速筛查清单”:先识别类型,再提取字符串,计算哈希,解析PE头,最后深入导入导出表。若静态分析结果指向明确的恶意行为(如窃密、下载器),则可直接撰写报告;若结果模糊,则需进入动态分析阶段。
- 文件类型识别:
file命令 + DIE,确认是否为PE文件及是否加壳。 - 字符串提取:
strings+ FLOSS,收集URL、路径、注册表项。 - 哈希计算:SHA-256,用于情报查询与样本追踪。
- PE头解析:
pefile,获取入口点、节区权限、编译时间。 - 导入/导出表:分析API调用,推断行为意图。
静态分析的质量取决于分析者的经验与耐心。一个看似无害的导入表,结合字符串中的异常URL,往往能拼凑出完整的攻击链条。下一阶段,我们将把这些静态线索带入动态分析环境,验证行为并提取网络IOC。