【网络安全】恶意软件 静态分析 动态分析
恶意软件分析入门:从静态分析到动态分析,再到反分析对抗
前言:这篇文章整理自 TryHackMe 的 Malware Analysis 相关内容,并结合个人理解做了重新梳理。全文围绕"拿到一个可疑样本之后该怎么办"这条主线展开,适合刚入门恶意代码分析、想搞清楚整体方法论的同学。文中所有操作都应当在隔离环境中进行,切勿在生产机或日常办公机上尝试。
一、什么是恶意软件
Malware 这个词由 MALicious + softWARE 拼接而来。换句话说,只要一个程序的目的是恶意的,它就属于恶意软件的范畴。
按行为特征,恶意软件还能进一步细分成勒索软件、木马、蠕虫、后门、间谍软件等等。不过本文不打算纠缠分类学,而是聚焦一个更实际的问题:
当我们怀疑某台机器上存在恶意软件时,应该按什么步骤去分析它?
二、为什么要做恶意软件分析
恶意软件分析在安全行业里不是一个"小众爱好",而是多个岗位的日常工作。不同团队做分析的动机也不一样:
| 团队 | 分析目的 |
|---|---|
| 安全运营(SOC) | 提炼恶意行为特征,编写检测规则 |
| 应急响应(IR) | 判断环境被破坏到什么程度,如何修复与还原 |
| 威胁狩猎(Threat Hunting) | 提取 IOC,在网络中主动搜寻同类样本 |
| 安全厂商研究员 | 把检测能力集成进安全产品 |
| 操作系统厂商(如 Microsoft、Google) | 定位被利用的漏洞,在 OS / 应用层加固 |
可以看到,同一份样本,不同角色关心的"答案"是不一样的。这也决定了你分析的深度该到哪里为止。
三、动手之前:先谈安全
恶意软件是武器,操作不当会伤到自己。 在开始任何分析之前,请务必遵守以下几条纪律:
- 专机专用。绝不在非分析专用的机器上碰样本。
- 样本加密存放。不分析、只是转移样本时,统一放在带密码的 zip / rar 压缩包里,避免误双击"引爆"。
- 只在隔离环境里解压。而且只在真正要分析的那一刻解压。
- 使用可回滚的虚拟机。分析专用 VM,做好干净快照。
- 管住网络。断网,或者至少做到全程可监控。
- 用完即还原。每次分析结束把 VM 回滚到干净快照,防止上一次执行留下的残留污染下一次分析结果。
第 6 点尤其容易被忽略。上一个样本改过的注册表、留下的服务,很可能让你对下一个样本的行为判断完全跑偏。
四、分析方法的两大分支
恶意软件分析很像拼图:用各种工具和技巧找到碎片,把碎片拼起来,才能看清样本到底想干什么。
我们最常拿到的样本形态有三种:
- PE 文件(Portable Executable,可执行文件/二进制文件)——最主流
- 恶意文档(带宏、带漏洞利用的 doc/pdf 等)
- 网络流量包(pcap)
而找碎片的手段,大体分成两类:
4.1 静态分析(Static Analysis)
不运行样本,只观察它的静态属性。
典型手段包括:
- 对样本跑
strings提取可见字符串 - 解析 PE 头,查看节区、导入表等信息
- 用反汇编器阅读代码
静态分析的优势是绝对安全——样本从头到尾没跑起来。
但它有个天敌:加壳与混淆。恶意软件作者非常清楚分析人员会先做静态分析,所以会想尽办法把关键信息藏起来。这时候就需要动态分析来破局。
4.2 动态分析(Dynamic Analysis)
这里有一个很有意思的悖论:
恶意软件面临一个两难困境:它必须执行才能实现目的;而无论代码混淆做得多好,一旦运行起来,它就成了容易被发现的目标。
这句话基本是动态分析的全部哲学基础。
动态分析就是在受控环境里把样本跑起来,观察它的实际行为:手工用监控工具盯着,或者丢进沙箱让它自动跑。因为环境完全由我们控制,可以把正常用户活动、Windows 服务这些"噪声"降到最低——于是观察到的几乎一切变化,都可以归因于恶意软件本身。这一点是动态分析最大的价值。
当然,对手也会反制:由于动态分析基本都在受控环境里做,恶意软件会想办法识别自己是否处在受控环境中,一旦识别成功,就走一条"人畜无害"的代码分支糊弄你。这部分放在第七节细讲。
4.3 高级分析(Advanced Analysis)
当基础的静态 + 动态都被绕过时,就得上反汇编器和调试器了:
- 反汇编器:把二进制翻译成汇编,静态阅读指令
- 调试器:附加到运行中的进程,可以随时下断点、单步执行,同时观察内存与 CPU 状态
这块内容深度较大,本文不展开。
五、静态分析实战:PE 文件头
PE 文件头里保存着这个可执行文件的元数据,是静态分析最重要的信息来源之一。这里挑两个最关键的部分说。
5.1 导入表与导出表(Imports / Exports)
一个 PE 文件几乎不可能包含它运行所需的全部代码。绝大多数时候,它会复用操作系统提供的功能——既节省体积,也没必要重复造轮子。
举个例子:开发者想读一个注册表值,他会直接导入微软提供的
RegQueryValue,而不是自己实现。因为可以合理假定这个函数在任何 Windows 上都存在,不需要打包进 PE 文件本身。
这就给了我们一个巨大的突破口:既然大部分工作都要通过 Windows API 完成,那么导入表基本就泄露了样本的能力边界。
| 导入的函数 | 暴露的意图 |
|---|---|
InternetOpen | 会进行网络通信 |
URLDownloadToFile | 会从网上下载东西 |
RegSetValueEx | 会写注册表(常见于持久化) |
CreateService / StartService | 会创建并启动服务 |
CryptEncrypt 系列 | 涉及加密(勒索软件重点关注) |
Windows API 的命名通常见名知意;拿不准的时候,直接查微软官方文档确认即可。
至于 Exports,一般和 DLL 绑定出现——非 DLL 的 PE 文件带大量导出函数是不太正常的。
5.2 节区(Sections)
PE 文件被切分成若干节区,各司其职。具体有哪些节区取决于编译器或加壳工具,但最常见的是这几个:
| 节区 | 作用 |
|---|---|
.text | 存放实际执行的 CPU 指令,标记为可执行 |
.data | 存放全局变量等全局数据 |
.rsrc | 存放图标、图片等资源 |
5.3 上手:用 pecheck 解析 WannaCry
Remnux 里自带 pecheck,可以直接解析 PE 头:
user@machine$ pecheck wannacry
PE check for 'wannacry':
Entropy: 7.995471 (Min=0.0, Max=8.0)
MD5 hash: 84c82835a5d21bbcf75a61706d8ab549
SHA-1 hash: 5ff465afaabcbf0150d1a3ab2c2e74f3a4426467
SHA-256 hash: ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa
.text entropy: 6.404235
.rdata entropy: 6.663571
.data entropy: 4.455750
.rsrc entropy: 7.999868
从输出里我们一眼能拿到几样东西:
- 四个标准节区:
.text/.rdata/.data/.rsrc,结构很"正常" - 各类哈希值:可以直接拿去威胁情报平台查
- 熵值(Entropy):衡量数据随机程度,范围 0~8。熵越高,越可能被压缩或加密过。 注意这里
.rsrc的熵高达7.999868——资源节区里藏了高度随机的东西,这是个非常值得追下去的线索
继续往下看导入表:
[IMAGE_IMPORT_DESCRIPTOR]
ADVAPI32.dll.CreateServiceA Hint[100]
ADVAPI32.dll.OpenServiceA Hint[431]
ADVAPI32.dll.StartServiceA Hint[585]
ADVAPI32.dll.CloseServiceHandle Hint[62]
ADVAPI32.dll.CryptReleaseContext Hint[160]
ADVAPI32.dll.RegCreateKeyW Hint[467]
ADVAPI32.dll.RegSetValueExA Hint[516]
ADVAPI32.dll.RegQueryValueExA Hint[503]
ADVAPI32.dll.RegCloseKey Hint[459]
ADVAPI32.dll.OpenSCManagerA Hint[429]
不用运行,光看这十行就能推断出不少东西:
- 打开服务控制管理器 → 创建服务 → 启动服务:典型的持久化手法
- 大量注册表读写:配置存储 / 持久化
- 出现
Crypt*系列:涉及加密操作
对一个已知是勒索软件的样本来说,这些导入完全对得上号。这就是静态分析的威力——在样本还"睡着"的时候,你就已经猜到它醒来要干什么了。
pecheck 的输出远不止这些,但作为入门,抓住节区信息和导入表这两条主线就够了。
六、动态分析实战:沙箱
⚠️ 再次警告:动态分析要运行真实的恶意样本,具有破坏性。务必在专用隔离机器上进行,分析前打干净快照,分析后回滚。绝不要在非分析用途的活跃机器上做这件事。
6.1 什么是沙箱
Sandbox 这个词其实是从军事领域借来的:一箱沙子堆出作战地形,部队在上面推演各种预案,以判断可能的结果。
放到恶意软件分析里,沙箱就是一个模拟真实目标环境的隔离环境,分析人员在里面跑样本,以了解它的行为。它高度依赖能打快照、能一键还原的实验机器。
6.2 一个好用的沙箱需要什么
- 尽可能贴近样本真实目标环境的实验机
- 快照 + 还原能力
- 系统监控工具:Procmon、ProcExplorer、Regshot 等
- 网络监控工具:Wireshark、tcpdump 等
- 通过伪 DNS 服务器和 Web 服务器控制网络
- 一套把日志和样本安全进出实验机的机制
最后一条是个大坑:如果你在运行恶意软件时还挂着共享目录,那么共享目录里的所有文件都可能一起遭殃。切记在引爆前断开共享。
6.3 开源沙箱
Cuckoo Sandbox
社区里名气最大的沙箱,起源于 2010 年的 Google Summer of Code 项目。优势是社区庞大、文档友好、可定制程度高,自带海量社区特征库。
⚠️ 但注意:Cuckoo 项目已归档,且不支持 Python 3,目前基本处于过时状态。
CAPE Sandbox
可以理解为 Cuckoo 的进阶版。它支持调试和内存转储,因此能够辅助脱壳。目前仍在积极维护,支持 Python 3。入门者也能用,但要充分发挥它的能力需要一定功底。官方提供在线社区版,可以先试用再决定是否自建。
6.4 在线沙箱
自建沙箱耗时耗力,在线沙箱是很好的补充:
- Online Cuckoo Sandbox
- Any.run
- Intezer
- Hybrid Analysis
🔴 一条重要纪律:除非你非常清楚自己在做什么,否则不要随便把样本上传到在线沙箱。上传本身可能造成敏感信息泄露(想象一下定向攻击你公司的样本里嵌了内部路径或凭据),也可能打草惊蛇,让攻击者知道自己被发现了。
更稳妥的做法是:先拿哈希去搜。 如果别人已经提交过,你直接看报告就行。
6.5 用 Hybrid Analysis 看 WannaCry 报告
按上面的原则,我们不提交样本,而是拿 WannaCry 的 MD5 去搜。会发现它已经被提交过很多次,可以从中挑一份(比如 Windows 7 64-bit 环境下的那份)来看。
报告里值得关注的部分:
① 结论区
- 判定:Malicious
- 威胁评分:100/100
- AV 检出率:95%
② MITRE ATT&CK 映射
点开 “view all details” 可以看到样本行为到 ATT&CK 技战术的完整映射。这一块对写检测规则的同学价值极大。
③ 动态分析区(核心)
这里能看到样本运行时的进程树。其中 cmd.exe 的调用尤其值得注意——报告显示样本在运行脚本文件,并删除备份和卷影副本(Volume Shadow Copies)。
这是一个教科书级的信号:删卷影副本是勒索软件的标志性动作,目的就是掐断受害者通过备份恢复文件的退路。看到这个行为,基本可以直接给样本定性了。
④ 网络分析区
样本的网络行为、连接的域名和 IP,都是提取 IOC 的直接来源。
⑤ 提取的字符串与文件
前面进程树里看到的那些批处理脚本,内容就能在这里找到。
⑥ 社区评论
报告最后的社区讨论有时候能捡到别人踩过的坑。
七、对抗:恶意软件作者的反制手段
安全研究员在造工具,恶意软件作者也在想办法让这些工具失效。这是一场持续的军备竞赛。下面是几类常见的反分析手段。
7.1 加壳与混淆(Packing & Obfuscation)
壳(Packer) 会对恶意软件的内容进行混淆、压缩或加密。最直接的后果是:静态分析基本瞎了。
来看一个加壳样本 zmsuz3pinwl,先跑 strings:
user@machine$ strings zmsuz3pinwl
!This program cannot be run in DOS mode.
RichH
.rsrc
.data
.adata
dApB
Qtq5
wn;3b:TC,n
*tVlr
D6j[
^sZ"4V
JIoL
...
全是垃圾字符串,一点有用信息都没有。对比一下正常样本能提取出的路径、URL、注册表键名,差距一目了然。
再跑 pecheck:
user@machine$ pecheck zmsuz3pinwl
PE check for 'zmsuz3pinwl':
Entropy: 7.978052 (Min=0.0, Max=8.0)
MD5 hash: 1ebb1e268a462d56a389e8e1d06b4945
SHA-256 hash: 98c6cf0b129438ec62a628e8431e790b114ba0d82b76e625885ceedef286d6f5
entropy: 7.999788
entropy: 7.961048
entropy: 7.554513
.rsrc entropy: 6.938747
entropy: 0.000000
.data entropy: 7.866646
.adata entropy: 0.000000
----------Parsing Warnings----------
Suspicious flags set for section 0. Both IMAGE_SCN_MEM_WRITE and
IMAGE_SCN_MEM_EXECUTE are set. This might indicate a packed executable.
...(section 1 ~ 6 同样告警)
Imported symbols contain entries typical of packed executables.
这份输出里的三个信号非常关键:
| 现象 | 含义 |
|---|---|
没有 .text 节区 | 正常 PE 的代码放在 .text,这里压根没有——代码是运行时才解出来的 |
| 多个节区同时可写 + 可执行 | 强烈的加壳特征。正常程序几乎不需要"既能写又能执行"的内存,而脱壳过程恰恰要往某块内存写入解密后的代码再跳过去执行 |
| 节区名为空、熵值逼近 8.0 | 内容高度随机 = 被压缩或加密过 |
| 导入表异常稀少 | 真实 API 调用被隐藏,运行时才动态解析 |
所以,面对加壳样本,分析的第一步通常是脱壳(unpacking)。 这是个进阶话题,需要用到调试器和内存转储(CAPE Sandbox 在这方面能帮上忙)。
💡 小结一个实用经验:熵值 > 7.0 就该警觉,> 7.5 基本可以认定是加密或压缩数据。这是一个成本极低、效果极好的初筛指标。
7.2 沙箱逃逸(Sandbox Evasion)
既然静态被挡住了,那丢沙箱总行吧?——作者也早有准备。常见招数:
① 长时间 sleep
沙箱的运行时间是有限的。于是样本执行后先睡上很久,啥也不干,把沙箱耗到超时。等沙箱判定"无害"收工了,它再开始干活。
② 检测用户活动
沙箱里没有真人,所以不会有鼠标移动和键盘输入。样本会一直等,直到检测到用户活动才开始作恶。更高级的样本甚至会分析鼠标移动的轨迹模式——自动化沙箱模拟出来的鼠标轨迹往往过于规整、笔直,一眼假。
③ 用户痕迹取证(Footprinting)
检查机器上有没有"生活气息":MS Office 最近打开的文档记录、浏览器历史记录等等。如果发现这台机器干净得不像有人用过,那它就判定这是沙箱,直接退出。
④ 检测虚拟机
沙箱跑在实验机上,而实验机会留下痕迹。比如 VMware 或 VirtualBox 安装的特定驱动,就是明显的破绽。恶意软件作者往往把"是虚拟机"直接约等于"是沙箱",一旦检测到就自我了断。
这个列表并不完备,但足以说明一个道理:分析环境越"像"真实用户的机器,你能观察到的行为就越真实。 给你的分析 VM 塞点浏览历史、装几个常用软件、随手建几个 Word 文档,有时比换工具管用。
八、总结
回顾一下整条分析主线:
拿到可疑样本
│
├─ 【纪律】隔离环境 + 加密存放 + 干净快照
│
├─ 【静态分析】不运行,先摸底
│ ├─ strings → 全是乱码?→ 怀疑加壳
│ ├─ pecheck → 看熵值、节区、导入表
│ └─ 导入表基本泄露了样本的能力边界
│
├─ 【动态分析】跑起来,看行为
│ ├─ 优先查哈希,别急着上传样本
│ ├─ 沙箱报告:进程树 / 网络 / ATT&CK 映射
│ └─ 删卷影副本 → 勒索软件实锤
│
└─ 【遇阻】加壳 / 沙箱逃逸
└─ 上调试器与反汇编器(高级分析)
几个值得记住的要点:
- 静态和动态不是二选一,而是互补。静态被加壳挡住,就上动态;动态被逃逸绕开,就回头脱壳静态看。
- 熵值是性价比最高的初筛指标。
- 导入表是最便宜的情报来源。
- "节区同时可写 + 可执行"是加壳的强信号。
- 纪律比技术更重要。再厉害的分析技巧,也救不了一次在主力机上的误双击。
更多推荐
所有评论(0)