1. 先搞清楚office病毒到底是什么形态
1.1 常见的三副面孔:宏、OLE对象与模板注入
我在实际分析里,恶意office文档翻来覆去就那么几类“套路”,归根结底是攻击者想把一段代码塞进文档,然后诱导目标打开。最常见的第一类是宏病毒,文档里嵌了一段VBA宏,打开时通过AutoOpen、Document_Open这类事件自动执行。早些年大家觉得宏病毒很老土,快被淘汰了,结果这几年利用宏的样本不减反增,只是因为杀毒软件盯得紧,攻击者开始用分段混淆、字符串拼接、API动态调用来躲避静态特征。第二类是OLE对象嵌入,PDF、Flash、甚至另外一个office文档被直接塞进当前文档里,打开时渲染或调用的程序来处理内嵌对象,借机触发漏洞或执行载荷。第三类是模板注入,模板被远程加载,诱导Word通过模板更新机制从外部地址拉回恶意模板,宏隐藏在远程模板里,本地文档反而很干净,这种手法在钓鱼邮件里非常常见。
这三副面孔不是互相排斥的,很多样本是“宏+模板注入”或者“OLE+漏洞利用”混合着来。分析的时候如果只看其中一层,很容易漏掉真正的关键行为。我的习惯是拿到样本先做分层:文件结构一层、宏代码一层、内嵌对象一层、外链地址一层,每层单独排查,最后再把结果拼起来看整体链路。
1.2 从投递到驻留:一条完整的感染链
office恶意文档很少在真空里工作。它通常是整个攻击链条中的一环:钓鱼邮件附件、网页下载、U盘摆渡,总有一个入口把文档送到目标机器上。文档的第一个动作往往是降低宿主安全策略,比如通过宏去关闭宏安全警告、修改信任中心设置,或者释放一个后续的PE文件到临时目录再运行。我记得分析过一份Excel样本,宏代码先把自身的一部分字节用数组形式硬编码在VBA里,运行后再逐字节拼成一个exe文件释放到临时目录,然后通过Shell函数拉起这个进程。整个过程从用户双击文档到恶意进程落地,不到一秒钟。
为什么理解这条链很重要?因为防御和溯源都靠它。我作为分析人员,手里的文档不是孤立的,它连接着投递源和后续载荷。看清投递方式,能推断攻击者是想打特定的人还是广撒网;看清驻留行为,能判断是一次性的信息窃取还是长期控制。分析报告里如果只写“这个文档有恶意宏”,价值其实很低,把上下游串起来,报告才真正有用。
1.3 为什么到今天还要手工分析office样本
有人会问:现在EDR、杀毒软件不是到处都有吗,恶意office文档还能翻起浪?这个问题我回答过很多次。自动检测工具能拦住的是“已知的恶意特征”,但是攻击者可以随手改掉宏里的字符串、换一个混淆方式、换一个载荷下载地址,特征库就失效了。我记得有一类样本,把恶意字符串拆成几百个字符片段,运行时用随机顺序拼接,同一功能每生成一个样本代码长得都不一样。这种情况下,自动检测引擎很容易给出“未见明显恶意”的误判,尤其当样本是加密宏或者用了复杂参数传递时,人工分析就是最后一道保险。
另外,分析office病毒不只是为了处置一个样本,更是为了提炼指标。宏的下载地址、释放文件的哈希、外联的域名、互斥体的名字、注册表写入的路径,这些IOC(失陷指标)可以反哺到检测规则和安全设备上,让整个防御体系变强。从这个角度看,从0到1掌握分析方法是安全从业者特别值得做的一件事。
2. 动手之前的准备工作:环境、工具、安全意识
2.1 隔离环境是底线,三个方向缺一不可
我刚开始分析样本的时候吃过亏,图省事直接在主力机上开了宏调试,结果虽然是测试样本,也差点让释放出来的程序触碰真实网络。后来我给自己定了一条死规矩:恶意样本分析必须在隔离环境里做,并且隔离要分成三个方向来检查。物理隔离,分析机不和其他机器共享局域网,最好网线拔掉或者放在独立网段;网络隔离,必要的时候用宿主机上的虚拟机配合软件防火墙,只允许特定域名走代理,其余全部丢弃;存储隔离,分析机上不要挂载宿主机和公司共享目录,防止样本通过共享盘扩散。
这三个方向里我会特别强调网络。office样本启动后几乎都要外联,不把网络掐住,恶意行为就观测不全面;但也不能完全断网,因为断网状态下样本可能放弃后续行为,显示不出来完整意图。折中做法是用自定义DNS和代理,把流量导到监控设备上,域名解析返回假的IP,既能看到连接企图又不会真正连到攻击者服务器。这是我的默认起手式,后面动态分析再细化说。
2.2 值得长期留在工具箱里的几类软件
说起来,分析office样本用到的东西并不复杂,我按“从静态到动态”的顺序把它们分成四类,每类都可以找到开源或者个人可获取的版本,不需要花大钱。文件结构查看器负责解开office文档的外壳,看清OLE复合文档和OOXML压缩包的内部组织;宏提取与反混淆工具负责把VBA代码从文档里抽出来,把被拆散的字符串重新拼好;行为监控工具负责记录运行后的进程、文件、注册表、网络动作;最后还需要一个十六进制编辑器和内存转储工具,用来处理极端情况——比如宏代码里藏着shellcode,或者恶意代码被加密需要从内存里抠出来。
工具不在多,关键是会用。我在后面几个章节里写到的命令和参数,都是我反复验证过、在实际样本上能稳定出结果的组合。新人在这个阶段最容易犯的错就是囤积一堆工具但不知道每个工具的适用场景,我建议先把一套组合用熟,再去横向扩展。比如宏提取这一层,你用熟一个工具就够了,其他同类工具只是备选。
2.3 样本来源与去标识化的几条原则
正规渠道获取分析样本很重要。我通常依赖三类来源:自己蜜罐或者终端捕获的可疑文档、公开的恶意样本库、以及同行的威胁情报共享。无论哪一类,拿到的文件名、邮件头信息、原始路径都可能是敏感内容,直接乱传会出问题。我的习惯是第一步就做去标识化:复制样本到工作目录时改成无规律的编号名称,比如sample_20241105_a.doc,同时去掉扩展名以降低误双击风险;如果分析过程要截图给别人看,先把文件名、电脑名、IP地址打码。
在下载和分析过程中还有一条纪律:永远不要在自己日常使用的机器上打开可疑文档的原件。正确做法是先在文件服务器上用哈希校验一遍,确认它和你预期分析的样本一致,再放进虚拟机。我在团队里带新人的时候,反复强调“你打开的每一个office文档,都可能正在试图运行代码”——安全分析师自己反而要最敬畏这一点。
3. 静态分析过程:在运行之前把代码看透
3.1 第一眼识别:这个文件到底是什么格式
拿到一个.doc或者.xls文件,我第一件事不是急着提取内容,而是先确认它的真实文件头。现在很多攻击者会把一个可执行文件的字节头伪装成文档扩展名,或者反过来把恶意宏代码藏在看似普通的RTF文本里。用十六进制编辑器看一眼就够了,四种常见格式的魔数我都记在心里:OLE复合文档以D0 CF 11 E0 A1 B1 1A E1开头,这是老版本Office和.doc、.xls、.ppt用的容器;OOXML格式是50 4B 03 04,本质是ZIP包,对应现代Office的.docx、.xlsx;RTF以7B 5C 72 74 66开头,即{\rtf文本;纯文本常常是EF BB BF或者直接ASCII字符开头。
为什么要先看文件头?因为它决定了我下一步用什么工具。OLE格式用解析OLE的工具看流和目录,OOXML格式则直接解压看里面的XML文件,判断方向错了,后面全白搭。我见过一个样本,文件名叫invoice.doc,实际上是个ZIP压缩包,里面塞着一个脚本和一个图片,这种改名伪装在早期的钓鱼攻击里很常见。用扩展名判断文件类型是最低级也最高危的错误。
3.2 提取宏代码:从olevba到手动脱壳
宏提取这一步,我用得最多的是Python环境下的oletools套件,里面olevba命令可以直接把OLE文档中的VBA代码抽出来。举一个最常用的执行方式:
olevba -c sample_20241105_a.doc-c表示输出检测到的可疑IOC,比如URL、IP、文件路径。如果样本是OOXML格式,命令也通用,工具会自动解压并识别嵌入的宏。第一次跑完之后我会重点看输出里的“VBA MACRO”段落和可疑名称列表,宏名、模块名、引用的外部库都值得记录。有一类样本的宏模块名称是随机的,每次都不一样,这就是为了对抗特征码;也有的宏代码被数字签名保护,打开后只有密文看不到源码,需要更复杂的处理方式,这个放到后面常见问题里展开。
宏提取之后就是枯燥的读代码阶段。VBA代码不会太长,很多恶意样本核心逻辑不超过几十行,但混淆方式五花八门。最常见的是字符串拼接Chr(104)&Chr(116)&Chr(116)&Chr(112)拼出http,以及用变量名做运算、用Evaluate动态执行。我在读宏代码时会把所有字符串提取出来拼好,再人工梳理执行流。这个过程没有捷径,多读几十个样本之后你会有一种直觉:看到某个函数名或者API组合,脑子里立刻能浮现出它大概要干什么。
3.3 宏混淆还原与人工追踪的实操手法
静态分析最大的价值就是在不运行的情况下还原恶意逻辑。对于纯字符串拼接类的混淆,写个小脚本把它还原即可,比如这样一段VBA:
mal_url = Chr(104) & Chr(116) & Chr(116) & Chr(112) & _ Chr(58) & Chr(47) & Chr(47) & Chr(120) & _ Chr(121) & Chr(122) & Chr(46) & Chr(99) & Chr(111) & Chr(109)手动或者用脚本执行Chr逆运算,就能拼出http://xyz.com。还有的样本把关键字符串做Base64编码,用DecodeBase64还原,我在分析时也会直接调用工具的自动解码能力,再人工确认。
人工追踪的时候我喜欢在代码关键位置做“标注注释法”:把每一段宏的目标记成一句话,比如“这一段解出下载地址”“这一段创建计划任务”“这一段禁用宏警告”,标完之后整个样本的行为骨架就出来了。这样做的原因是VBA执行顺序可能在多个过程之间跳转,跟着逻辑走容易迷失,标注之后可以清晰地看出样本的意图。我实际遇到的很多宏样本最终都指向同一类动作——下载并执行、释放文件、添加自启动、收集系统信息。理解到这一层,静态分析的核心目标就已经达成了一大半。
4. 动态分析过程:让样本在眼皮底下跑一遍
4.1 沙箱运行前必须做好的三件事
静态分析可能挖出明显的恶意特征,但很多行为只有真正运行才能看到,比如它下载的载荷是什么、写入的注册表键值具体是什么、释放的文件的真实内容如何。动态分析的第一步是快照虚拟机,我习惯在干净状态打一个快照,跑完还原,再换下一个参数重跑。第二步是配置流量监控,我用的是虚拟网卡加流量分析工具,确保样本外联的DNS查询和HTTP请求都被记录下来。第三步是开启进程监控工具,把进程创建、文件写入、注册表变更全部录下来,不遗漏任何动作。
这里的经验是宁可监控开得多,也不要少。开得多之后过滤筛选就行,少开一个关键维度,样本可能就在你眼皮底下把行为藏掉了。比如只看进程不看文件系统,样本释放了一个脚本到启动文件夹,你没看到,后续判断驻留机制就会出错。我每次搭建动态分析环境都会花大约二十分钟做检查,确认监控项覆盖了进程、文件、注册表、网络四个维度,才开始跑样本。
4.2 观察进程链:从宿主程序到恶意子进程
在沙箱里用办公软件打开恶意文档后,最先关注的是进程树的变化。正常情况下,Word进程不会凭空再创建别的进程;一旦发现winword.exe派生了powershell.exe或者cmd.exe,这基本可以断定文档有恶意行为。进程链的每个节点都值得记录:父进程是谁、启动的命令行参数是什么、子进程是否继续生成下一级进程。
有一次分析一个.docm样本,宏代码先通过WScript.Shell拉起powershell.exe,PowerShell又通过DownloadString从远程服务器拉了一段代码执行,然后这段代码下载了一个可执行文件并运行。整个链条在监控工具里一目了然:WINWORD.EXE -> powershell.exe -> rundll32.exe。如果只看文档本身,你只能看到宏,看不出它会走这么深。记录进程链的意义正在于此,它把文档打开到最终载荷落地的路径完整地呈现出来,帮助判断攻击者的意图和工具集。
4.3 网络与文件落地:两个容易被忽略的细节
网络行为是动态分析里信息量最大的部分之一。我常用的做法是让DNS请求正常发出,但通过本地映射把域名解析到沙箱内置的监听服务器上,这样可以看到请求的具体路径、User-Agent、POST数据。很多恶意宏会向远程服务器发送系统信息,在数据包里能直接抓到主机名、用户名、磁盘序列号,这些可以反推攻击者收集信息的范围。也有样本会尝试连接多个备用地址,如果第一个不通就切到第二个,因此观察网络行为要有耐心,最好等足五分钟或者触发了后续动作再停止。
文件落地这个维度容易栽跟头的地方在临时目录。样本经常把释放文件放在%TEMP%、%APPDATA%或者C:\Users\Public,监控工具记录到新建文件后,我会立刻把它们复制出来做进一步检测。关键是要记录文件的创建时间、大小、哈希,以及是否有修改系统启动项的动作。有些样本不会马上释放可执行文件,而是先写入一个脚本到启动文件夹,等下次开机再运行,这种延迟执行策略在沙箱短时间里不容易暴露,所以我通常会把监控时间拉长,或者手动重启一次沙箱来观察驻留效果。
5. 从分析结果到检测能力:提炼IOC与写报告
5.1 把散点信息变成可执行的IOC清单
分析完之后最重要的事情是输出IOC。IOC就是别人拿到之后可以直接在自家环境里查杀的指标,类型大概有:文件哈希、文档内嵌的URL/域名/IP、释放文件的哈希和路径、注册表写入的关键路径、进程命令行特征、互斥体名称、宏模块的变量特征。我每次分析结束都会单独建一个表格,把静态和动态所有的发现汇总进去,每条记录附上来源(静态/动态)和可信度。
举一个具体例子,一份Excel样本最终清点出来:原始文档SHA256哈希值、宏内下载地址hxxp://malicious.example.com/update、释放文件%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\run.vbs、写入键HKCU\Software\Microsoft\Windows\CurrentVersion\Run、进程链特征excel.exe -> wscript.exe -> mshta.exe。这五条指标放到检测规则里,几乎每一种设备都可以用:防火墙拦截域名、EDR监控进程链、杀软查哈希和释放文件、主机审计查注册表启动项。IOC的价值不在多,而在于别人拿到之后马上能用。
5.2 报告写作的骨架:越简洁越有力量
安全分析报告写给两类人看,一线处置的运维和决策的管理层,这两类人对报告的需求完全不同。我自己的报告模板固定是五段式:样本概述与危险等级、静态分析发现、动态分析行为、IOC清单、处置建议。样本概述里写清楚文件格式、类型、投递来源和威胁级别,让人三十秒了解结论;行为描述里按时间线或者已经执行的阶段列出,包含关键截图和命令输出;处置建议则直接给“找人、查机器、封地址”的动作方案。
写报告最大的禁忌是堆技术细节不总结。新人容易把几百行宏代码截图放进报告里,其实读者根本不需要看到全部代码,只需要知道“这段宏的性能是什么、最终做了什么”。我在写报告时还会标注每一条结论的来源和依据,这样即使后续有人质疑,也可以回溯到证据。一份好的分析报告,核心是让读者能够根据它做出准确的处置决策,其他一切都是辅助。
5.3 从单个样本到规则库和威胁情报
分析完一个样本,不能就放在硬盘里吃灰。我习惯把每次的分析结果沉淀成几条规则。YARA规则就是一个好出口,它可以通过文件特征来识别同一家族的变种,比如宏里独特的功能字符串、固定的代码结构、甚至文档内特定流区的字节特征。下面是我曾经用过的一条简化规则思路:
rule suspicious_office_macro_chr_download { meta: author = "analyst" description = "detects doc with chr stitched url and shell" strings: $chr = "Chr(" ascii $url = "http" ascii $shell = "WScript.Shell" ascii $run = ".Run " ascii condition: uint32(0) == 0xE011CFD0 and 3 of them }写规则的目的不是一劳永逸,而是让下一次同类型样本出现在视野里时有自动检测机会。在这个基础上,如果条件允许,可以把IOC推送进威胁情报平台或者邮件网关的URL信誉库,分析一次收益放大到全网。把单个样本的处置变成一个家族的检测能力,这才是从0到1的完整闭环。
6. 实战中踩过的坑与排查速查表
6.1 四类高发误判场景及避坑经验
分析office病毒几年下来,我踩过不少坑,也见过同事踩坑,总结出四类高发误判场景,在这里特意拎出来说。
第一类是误把“文档结构的正常特征”当作恶意。比如文档里存在外部实体引用ExternalStylesheet或者webSettings.xml里的rsid,很多刚入门的同事看到这些字段就紧张,实际上现代Office文档里这类结构大量存在,是正常编辑器生成的结果,不等于恶意。判断标准应该是看有没有实际的外联动作或恶意载荷,而不是单看某个特征的“存在与否”。
第二类是动态分析时样本没有“发作”,直接判定为安全。这种情况最常见的原因是沙箱环境与真实环境差异过大。攻击者可以在宏里检测当前运行环境是否具备真实用户交互特征,比如检查进程列表有没有杀软进程,或者检测是否在虚拟机里。如果样本发现异样,它会直接停止执行。应对的办法是用尽量接近真实用户环境的镜像,然后对比多次运行结果,不要只跑一次就下结论。
第三类是过度依赖自动提取结果。某次我用工具自动提取了宏里的字符串,工具把一段加密后的配置直接解码成乱码,我没细看就扔在一边,结果真正的下载域名就藏在那段乱码的Base64解码结果里,只是需要再做一次变种编码。从那以后,凡是自动解码出来的可疑字段,我都会手动多重解码尝试,常见的是Base64加URL编码,有时候要解三轮才能看到明文。
第四类是只看恶意行为不看投入产出。样本的行为链很长,但最终目标可能就是窃取浏览器里的密码。如果我把分析重点全部放在“怎么下载到后续载荷”这个环节,忽略了最后数据的去向,报告的结论就会偏颇。分析最重要的一个问题是回答“攻击者到底想要什么”,这需要把行为链的终点画出来才算数。
6.2 高频问题排查速查表
为了更方便查阅,我把平时最常遇到的问题和解决方法整理成了一张速查表,按流程排列,供遇到同类情况时的参考。
| 问题现象 | 可能原因 | 排查切入点 |
|---|---|---|
| 宏代码提取后是乱码 | 宏被VBA项目加密保护,或者存储编码特殊 | 先看OLE流的MS-OVBA结构,尝试密码破解工具或从内存转储中恢复明文 |
| 样本运行后没有产生任何行为 | 样本有反虚拟化检测或反沙箱逻辑 | 检查宏代码里的环境探测API,尝试在更贴近真实环境的镜像里运行 |
| 释放的载荷在临时目录一闪而过 | 载荷运行完自删除,或者由另外进程清理 | 开启文件系统监控的延迟删除记录,用内存转储抓取运行中的载荷 |
| 网络监控看到了DNS请求,但没有后续流量 | DNS解析响应不符合样本预期或域名已失效 | 用本地DNS拦截返回可控IP,观察是否有重试或备用域名的解析记录 |
| 宏代码用动态调用执行,静态还原困难 | 代码使用CallByName、Eval等动态特性 | 手动执行部分表达式还原,或者在沙箱里让代码运行后用调试器跟踪 |
| office文档同时是多种格式混合 | 复合文档嵌套ZIP或RTF内嵌OLE | 逐层剥离容器,先用文件头识别最外层,再对每个内嵌层单独做文件类型判断 |
olevba报警但人工确认无效 | 工具对部分高风险函数有误报 | 核对报警函数上下文,看是否真的执行到关键分支,避免盲信自动标记 |
6.3 我最后留下的几条个人建议
分析office病毒是个细活。它不像二进制逆向那样需要极高的底层功底,但要求分析者细心、耐心,并且不放过任何一个小细节。我自己在长期实践里养成了两个习惯:一是每次分析都写分析笔记,哪怕一句话也好,几个月后回头翻看会发现很多当时觉得“奇怪”的现象其实是在暗示同类样本的共性规律;二是主动去看不同类型、不同混淆手法的样本,宏病毒、OLE漏洞、模板注入都各找几个经典样本做对比分析,只看单一类型很难形成全局视野。
另外,我一直强调分析环境的口令:样本不变,环境干净;环境一变,结论可能要重来。每当你怀疑样本行为没有完全暴露,多换一种环境,多观察一轮,多跑一次,往往就能看到不一样的风景。安全分析本质上是在和对手比细节,谁更有耐心,谁就更能看穿对方的意图。
我个人在实际操作中的体会是,office病毒分析入门门槛不高,但做好做透非常磨练人。如果你正打算迈出这一步,从一份带有宏的可疑文档开始,按照这篇文章的路径走一遍,比看一百篇零散的教程都管用。分析完成后,把IOC贡献给自己所在的检测体系或者社区平台,你的每一次分析都会让整个安全生态变得更强一点点。