第二十四章 恶意代码分析(一):静态分析与动态分析

说实话,恶意代码分析这活儿,刚入行的人总觉得特别神秘。好像得有什么特异功能才能看懂病毒在干什么。其实不然。我做了这么多年逆向,说白了就是两招:静态分析动态分析。一个靠眼睛看,一个靠手去试。

这一章,咱们就聊聊怎么用这两招对付恶意软件。嗯,先从静态分析开始。

24.1 静态分析:不动手,先动眼

静态分析,就是不运行样本,直接看它的结构和代码。好处很明显——安全。你想想看,万一是个勒索病毒,一运行就把硬盘全加密了,那多尴尬。我早期就吃过这个亏,后来学乖了,先静态看一遍再说。

24.1.1 查壳:第一件事

拿到一个样本,我个人的习惯是:先查壳。壳是什么?就是给程序穿的一件马甲。恶意代码作者喜欢加壳,目的是隐藏真正的代码逻辑。

常用的查壳工具有这些:

工具 用途 我的评价
PEiD 查壳、识别编译器 老牌工具,识别率还行,但已停更
Detect It Easy (DiE) 查壳、熵值分析 我现在的主力工具,支持签名扩展
Exeinfo PE 查壳、入口点分析 轻量级,适合快速判断

怎么判断有没有壳?看入口点特征。正常程序的入口点通常是 push ebp; mov ebp, esp 这种标准开头。加壳后的入口点往往是 pushad 或者一堆奇怪的跳转。我曾经遇到过一个样本,入口点直接是 jmp 0x401000,一看就是壳的跳板。

小技巧: 用 DiE 打开样本后,看右下角的「熵值」。熵值接近 7.0 以上的,基本可以确定是加壳或加密的。正常编译的 PE 文件熵值一般在 4.0-5.5 之间。

24.1.2 字符串分析:找线索

查完壳,下一步就是看字符串。恶意代码里往往藏着大量线索——URL、IP地址、注册表路径、文件名、加密密钥等等。

strings 命令就能提取:

strings malware.exe > strings_output.txt

但要注意,加壳后的样本字符串是加密的。你看到的可能是一堆乱码。这时候需要先脱壳,或者用动态分析去抓解密后的字符串。

我一般会重点关注这几类字符串:

  • 网络相关: http://、https://、.onion、IP地址、端口号
  • 文件操作: .exe、.dll、.sys、C:\Windows\、%TEMP%
  • 注册表: HKEY_LOCAL_MACHINE、Run、RunOnce
  • API函数: CreateFile、WriteProcessMemory、VirtualAlloc
  • 特殊标记: Mutex名称、管道名称、服务名称
注意: 有些恶意代码会故意插入大量假字符串来混淆分析。比如一个木马可能包含 1000 条正常的系统路径字符串,只为了掩盖那 1 条真正的 C2 地址。这时候需要结合上下文判断。

24.1.3 导入表分析:看它想干什么

导入表(Import Table)记录了程序调用了哪些系统 API。这就像看一个人的工具箱——如果工具箱里有锤子、锯子、钉子,那这人八成是要做木工活。同理,如果导入表里有 CreateRemoteThreadWriteProcessMemoryVirtualAllocEx,那这程序大概率是要做进程注入

我常用的工具是 PE-bearCFF Explorer。打开导入表后,重点关注这些 API 组合:

API 组合 可能的行为
CreateFile + WriteFile + DeleteFile 文件写入后自删除
RegCreateKey + RegSetValue 注册表持久化
socket + connect + send/recv 网络通信(C2)
CreateProcess + WriteProcessMemory 进程注入或代码注入
CryptEncrypt + CryptDecrypt 数据加密/解密

举个例子。我之前分析过一个远控木马,导入表里同时出现了 GetAsyncKeyStateClipboardGetText。嗯,这明显是个键盘记录器。后来动态跑起来,果然抓到了它记录按键的行为。

核心思路: 静态分析不是万能的。加壳、混淆、动态加载 API 都会让静态分析失效。但它是你分析流程的第一步,能帮你快速判断方向。

24.2 动态分析:动手跑起来

静态分析看完了,心里大概有个数。但有些东西,你不跑起来是看不到的。比如解密后的 payload、网络通信内容、内存中的代码片段。这时候就需要动态分析上场了。

24.2.1 沙箱:安全的隔离环境

动态分析的第一步,是搭建一个安全的沙箱环境。我个人的建议是:用虚拟机,而且要用快照回滚功能。每次分析完,直接恢复到干净快照。

常用的沙箱方案:

  • 本地虚拟机: VMware 或 VirtualBox,安装 Windows 10/7 作为分析环境
  • 在线沙箱: VirusTotal、Any.Run、Joe Sandbox(适合快速分析)
  • 自动化沙箱: Cuckoo Sandbox(开源,适合批量分析)

搭建沙箱时,有几个坑要注意:

  • 关闭网络: 或者用模拟网络(如 INetSim),防止恶意代码真的连到 C2 服务器
  • 关闭杀软: 杀软会干扰分析,甚至直接删除样本
  • 安装分析工具: Process Monitor、Wireshark、API Monitor 等
  • 不要联网: 除非你明确知道自己在做什么
我曾经犯过的错: 有一次我忘了关虚拟机的网络,结果样本直接连上了 C2 服务器,下载了第二阶段 payload。虽然虚拟机是隔离的,但那个 C2 服务器记录了我的 IP。从那以后,我每次跑样本前都会检查网络设置。

24.2.2 行为监控:看它干了什么

样本跑起来了,怎么知道它在干什么?靠行为监控工具。我常用的组合是:

工具 监控内容
Process Monitor (ProcMon) 文件、注册表、进程、网络操作
Wireshark 网络流量、DNS 查询、HTTP 请求
API Monitor API 调用细节、参数、返回值
Process Hacker 进程树、线程、句柄、内存

具体怎么操作?我一般这么来:

  1. 先开监控工具: 启动 ProcMon 和 Wireshark,设置好过滤规则
  2. 运行样本: 双击运行,或者用命令行带参数运行
  3. 观察行为: 看它创建了什么文件、写了什么注册表、连了什么 IP
  4. 停止监控: 等样本稳定后(或者它自己退出),停止记录
  5. 分析日志: 过滤出关键事件,排除系统正常行为

举个例子。有一次我分析一个下载器,ProcMon 里看到它先创建了 C:\Users\xxx\AppData\Local\Temp\svchost.exe,然后写入了数据,最后用 CreateProcess 启动了它。嗯,典型的释放并执行行为。

过滤技巧: ProcMon 默认会记录海量事件。我一般会设置过滤规则:只显示进程名为样本名的操作,或者只显示 Result = SUCCESS 的事件。这样可以大幅减少噪音。

24.3 静态与动态的配合

静态分析和动态分析不是二选一,而是互补关系。我个人的工作流是这样的:

  1. 先静态: 查壳、看字符串、看导入表,快速判断样本类型
  2. 再动态: 在沙箱里跑起来,观察实际行为
  3. 交叉验证: 静态分析看到的 API 是否真的被调用了?字符串是否被解密了?
  4. 深入分析: 如果遇到混淆或加密,可能需要用调试器(如 x64dbg)单步跟踪

下面这张图展示了整个分析流程:

恶意代码分析流程 获取样本 静态分析(查壳、字符串、导入表) 动态分析(沙箱、行为监控) 交叉验证(静态 vs 动态) 深入分析(调试器、反汇编) 输入 不动手 动手跑 验证 深挖 查壳 → 字符串 → 导入表 沙箱 → ProcMon → Wireshark API调用是否匹配? x64dbg / IDA Pro

你看,整个流程是递进式的。静态分析帮你缩小范围,动态分析帮你验证猜想,最后再用调试器深挖细节。每一步都有它的价值。

记住: 没有万能的工具,只有灵活的分析师。静态分析看不到的,动态分析来补;动态分析跑不出来的,静态分析来猜。两者结合,才能还原恶意代码的全貌。

好了,这一章的内容就到这里。静态分析和动态分析是恶意代码分析的两大支柱。查壳、看字符串、分析导入表是静态分析的三板斧;沙箱隔离、行为监控是动态分析的核心。把这些基础打牢了,后面遇到再复杂的样本,你也能从容应对。

公众号:蓝海资料掘金营,微信deep3321