(零基础教学系列)手把手教你分析 APT:蔓灵花下载器样本分析
分析到一个简单又经典的样本,想想最近比较无聊就好好写写 APT 分析的部分吧!
本文仅从样本分析角度出发,样本来源以及溯源部分就不多啰嗦了(写了但是太长了,一起发阅读性很差就不发了,而且也不是很有代表性,以后有机会发个别的。)
初始载荷信息
攻击的初始载荷是一个文件名为双后缀名的文件“开证装期邮件.pdf.exe”,这是一种常见的文件伪装方式,利用 Windows 的扩展名显示设置(“隐藏已知文件类型的扩展名”)伪装真实的.exe 后缀,再选择高级自解压选项中自定义自解压文件图标,选择让 exe 文件看起来像 PDF 文档,诱骗用户打开。
不过由于自解压格式的图标来源于文件,而不是系统自带的图标:
时常出现画风不同的 C 位出道场面(一看就是自带剧本的):
VT 搜索该文件 MD5 可以看到有 52/69 的高检测率,匹配的 YARA 规则名可以解释为隐藏为 PDF 的 SFX 自解压文件:
SFX 自解压文件,是一种压缩软件生成的 exe 文件,拥有执行后可以解压释放文件并执行的特性,通常被病毒文件用来捆绑掩饰文档或其他白文件进行伪装。可将文件后缀改为 rar,使用压缩软件打开,查看其中的文件和相关代码和解压,或者在文件属性的注释中也可以看到。如本文中的样本运行后会在“C:\intel\logs”路径下释放“dlhost.exe”并执行:
直接双击运行 exe 使初始载荷在指定路径下释放文件也行,多一个步骤要找一下文件。一般来说解压比较方便,但是有些样本会检测是否在设置的目录下运行,不是则退出,分析时需注意这一点(本文样本无此检测)。
有效载荷 dlhost.exe
结论先行,带入结论看内容比较容易看进去。
“dlhost.exe”经过分析后发现为 APT 组织蔓灵花常用的下载器,用来收集受害者计算机信息和创建套接字通信,从远程服务器下载插件完成其他功能的操作。
在分析之前,建议先做一些准备工作,磨刀不误砍柴工~
去除随机基址
由于 PE 的特性,程序有基址随机化的问题,那么在分析前,需要查看并修改为不随机的情况,便于下断点分析后调试的配置文件(.udd)在重新运行后还能生效。
方式有多种,比较简单的是使用 010Editor 查看 PE 文件,将在 PE 结构中有字段“(NtHeader→OptionalHeader→DllCharacteristics→)IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE”,如果数值为 1,即开启了“基址重定位”(动态随机基址),现将其修改为 0 后保存文件:
也可以自己写脚本或者可执行程序将其修改。
查看断点
如果没有特地隐藏或者处理要使用的函数的情况(可“一般”是有的),查看 IDA 的导入表窗口中显示的函数,可以推测出一些功能,发现有:
1.套接字通信的函数,那么存在套接字通信(好绕):
2.文件操作函数,包括创建/打开、读取和写入等。可以推测有创建文件、读取文件、移动文件等操作:
3.获取信息操作:
那么此时可以通过导入表有个初步的判断,这是一个有获取计算机和用户信息,并且有文件操作的联网恶意软件——基本上已经可以推测出这是下载器或文件窃取器了。
反调试
一般来说恶意软件都会有反调试功能,反调试的方向也分多类,如:探测 Windows 调试器、识别调试器行为、干扰调试器的功能等。在《恶意代码分析实战》第 16 章反调试技术、《逆向工程核心原理》第 51 章静态反调试技术 &第 52 章动态反调试技术都有详细介绍,一般工作中遇到“Sleep”和“IsDebuggerPresent”比较多。
本样本虽无干扰调试的“Sleep”,但有检测调试环境的“IsDebuggerPresent”,问题不大,“15PB OD”的插件大礼包中“Hide Debugger”已将该函数的返回值 HOOK,即反反调试(狗头):
对 API 下断并检查
将样本拖入 OD 后,对敏感 API 函数下断,如:
接着可以“Alt+B”或菜单栏下的“B”(Break,断点之意),查看已下的断点,想取消断点时从这里也可以快速的找到:
查看后“Alt+C”或菜单栏下的“C”,可返回反汇编窗口。
查看函数调用
返回后可以使用右键“查找”功能中的“所有模块间的调用”,查看有无异常情况(那当然是有的):
大事不妙!异常就是大量调用动态获取函数地址的“GetModuleHandleW”+“GetProcAddress”,这是一种常见的规避检测的方式,并且也是一种反静态分析手段:
在 IDA 处找到对应的函数或代码后,使用 IDA 的脚本功能(Shift+F2):
使用 IDA 的重命名函数“MakeNameEX”编写的命令“MakeNameEx(long ea, string name, long flags);”。可以用 Notepad++/Excel 等编辑工具或 Python/BAT 脚本,将命令批量化处理后如下,复制粘贴后 RUN:
将地址进行重命名,便于静态分析:
出现个别因为已有该名称所以冲突不能重命名的,单独重命名(N 键)一下即可:
调试运行
IDA 导出表可以查看到主函数“Start”地址,下断后 F9 可直接运行到断点处,进行调试分析。
解密操作
在 IDA 界面还可以发现比较重要的功能代码在函数 401C80 处,其中有大量的 if+Do While 循环解密(解密方式-= 0xD),问题不大,在解密函数完成后的那行代码下断:
此处建议看看解密出的内存都是什么数据,如果发现特殊的字符串或数据需要特地跟踪一下。比如此样本中解密的部分数据就很明显包括注册表路径、外连的 URL 字符串、和一串疑似指令的字符串“Yes file”。这其实就是解密出了配置文件:
环境检测
如上上图所示,解密后就调用“CreateSemaphoreA”创建信号量“7t56yr54r”,接着调用“GetLastError”检测信号量是否创建成功,如果错误码为定义“ERROR_ALREADY_EXISTS”的 183(0xB7),即代表内存中已存在运行中的该进程,那么其后续的函数 40C234 必然是退出进程函数(或者有可能进入扰乱分析或者伪装功能的代码):
通常恶意的可执行文件会通过 CreateMutex 创建互斥体或 CreateSemaphore 创建信号量(蔓灵花该下载器都是用信号量)+“GetLastError”获取错误码的方式让恶意进程在内存中保持唯一运行的状态,避免互相干扰。那么由此可以逆推,其实主要的功能代码,一般是在判断完互斥体或信号量后的部分(或者其他检测行为后)。时间比较紧迫的情况,可以考虑定位到检测+“GetLastError”后,“if”判断不成立的逻辑条件进行分析。
由于本人调试分析时,常利用火绒剑等监测工具监测后台运行的该进程,故“GetLastError”的返回值为 0xB7,此步可以通过修改寄存器的 ZF 标志位跳过此步跳转:
网络行为
初始化操作和解密操作等非恶意功能代码比较多,先用 IDA 找比较重要的函数分析,再用 OD 按 F4 到 CALL 行查看其传入的参数,如外连“http://162.0.229.203/RguhsT/RguhsT/”:
由于分析时大部分情况是不建议联网的,且有可能外连的域名或 IP 已失效,在套接字通信后的 if 判断处修改跳转。不跳就结束嘞(“Tab”键查看流程图或者在“Graph overview”中可以看出,如果不跳就跳过大段代码结束了):
将光标定位到“if”判断 connect 返回的结果处,按“Tab”键查看 IDA 的反汇编窗口,可以看到“if”的关键地址是“0x403678”,下断运行到此处后修改 ZF 标志位,让其不跳转即可:
数据及其来源
套接字连接成功后的第一个函数 402F40 里调用了系统 API“GetComputerNameA”,查看其保存获取到数据 ComputerName 在何处被引用,发现函数 402F40 末尾有大量调用同一函数 40C318 和同一内存地址 0x435598。在“GetComputerNameA”和函数 40C318 间,这部分代码中有“GetUserNameA”、“RegQueryValueExA”、和“GetSystemInfo”等获取信息的函数后,推测函数 402F40 为计算机信息的字符串拼接:
有了这个推测后,在最后一次调用 40C318 处下断,数据窗口监视对应的首参内存地址“0x435598”:
确实拼接出带有计算机信息的字符串“?a=HostName&b=COMPUTERNAME&c=Windows%207%20Professional&d=AdministratorAdministratorf9117a5d-b155-4a3e-b6c9-5ae181247d3b165536040965860”,可以分解为以下的格式:
其中 d 值比较奇怪,使用交叉引用查看该写入值的调用,可以发现其值为 UserName 和调用“RegQueryValueExA”获取的 GUID:
以懒人思维来说,定位这类数据来源的步骤是可以省略的,仅需将计算机信息(如计算机名,用户名,MAC 地址、IP 地址、GUID、甚至是偏门如 C 盘卷序列号的数据)修改或记录其数据即可。上面图中显示的调试环境的计算机就是如此,一般分析了这么多样本,看到自己的 GUID 数据也能认出来,只是为了演示一下如何交叉引用定位。或记住 GUID 格式为“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”(8-4-4-4-12)。
所以 d 值的数据为[UserName][UserName][GUID][dwActiveProcessorMask][dwAllocationGranularity][dwOemId][dwPageSize][dwProcessorType][wProcessorArchitecture],现在又可以把[dwActiveProcessorMask][dwAllocationGranularity][dwOemId][dwPageSize][dwProcessorType][wProcessorArchitecture]数据记到小本本里了~
数据使用
将 IDA 中该储存计算机数据的内存地址重命名后,查看该内存地址的交叉引用可以发现被多个函数调用,而最后一个调用的函数 401080,该函数的首参(通常是比较重要的参数)后续成为了“Send”函数参数中要发送的数据缓冲区,此处可以推测 401080 函数为拼接待发送数据:
跳转到调用 401080 处,可以明显看到是构建 GET 方法的 HTTP 报文数据。其实不用跳转,通过传参的数量/格式和前后调用的函数其实也可以推测出这段代码是构建 HTTP 报文:
Send 发送上线包
查看“Send”函数的要发送的数据缓冲区(第二个参数地址),可以看到拼接好要发送的数据:
木马程序发送的第一个包还带有计算机信息的,通常可以叫做上线包:
此处可以发现有比较明显的流量特征,家里有沙箱/流量检测设备的同学可以设置为流量检测规则:
这个规则的误报率估计不低,给 c 值加上“Windows”可以降低一些误报率
如果家里有条件的同学,可以以安全研究/APT 追踪发现的角度设置该流量规则,然后再过一遍沙箱规则或 YARA 规则;如果是部署到客户现场的流量检测设备,则不建议部署。
沙箱如果像我的调试环境一样用户名电脑名主机名是固定字符串的话,再写死对其他值的判断,基本就没有误报了。除非这个上线包来自开源项目,被很多恶意软件使用,那就需要增加其他判断条件,此步在下文的“通过 VT 扩线”中有详述。
Recv 接受返回数据
一般“Send”发送上线包后就是“Recv”从远程服务器接受命令或文件,查看“Recv”从远程服务器获取的数据有什么交叉引用,发现函数 408550 明显有 C2 指令判断:
有部分内存数据为运行后才被解密的字符串,可以在上述的字符串解密操作后,在 IDA 里将对应的内存地址重命名,或者在动态运行时已经是解密后的数据。
为了进入预定义 C2 指令的逻辑,可以在“Recv”执行后将函数 408550 的第二个参数手动修改为“Yes file”,或者修改字符串对比判断后的跳转也行,具体看后续执行的代码,本样本直接修改跳转更方便:
一般接收 C2 指令后的判断处建议做个快照,看看跳不跳转分别执行了哪些功能。如当有多个 C2 指令进入不同的逻辑分支执行不同的代码时,分析完其中一个跳转后可以恢复快照,通过修改跳转或下一跳地址(EIP)无缝衔接分析下一个分支逻辑。该样本如果不满足“Yes file”指令后的代码逻辑就是退出,此处不做展示。
进入“Yes file”的代码逻辑后,可以明显看到有大量对接收数据的操作,如提取数据的代码:if 判断长度+DoWhile 循环中嵌套一个 if 判断数据,最后 memmove 保存:
由于数据不方便公开及教学意义,此处按照无法获取数据的情况进行接下来的分析。
对接受的数据结合上下文代码进行推测:
1.一般来说,对数据进行各种提取/解密/判断后的最后一个内存块地址 0x4351F7 可以优先分析。发现最后被操作的内存块在后续代码中被函数 40EB61 多次调用;
2.函数 40EB61 最后一次调用的首参,同时也是字符串拼接函数“strcat”的首参,而拼接的另一个字符串为解密后的字符串“.exe”;
3.那么可以推测该文件为一个 exe 文件,查看其交叉引用,发现是执行程序的函数“ShellExecuteA”的参数,并且执行动作的参数为“open”——也就是运行了一个 EXE 文件:
而在调试器运行到“ShellExecuteA”之前,中间大部分的函数为对文件的一些操作,可能会触发一系列文件操作函数,这一步调试分析的意义不是很大。从远程服务器获取数据到本地执行的这个过程,或许有文件解密操作,通过逆出解密算法,可以还原出 PE 文件的加密数据(或者从流量里 Dump),写出下载加密 PE 文件的流量规则。
至此,该样本的功能已经很清晰了,下载器运行后会收集受害机器的信息拼接为字符串,构建上线包发送给远程服务器,从远程服务器获取 exe 文件的数据并运行。
这种有外连下载 exe 运行操作的恶意文件通常归类为下载器(Downloader/Loader),APT 组织蔓灵花常使用下载器在受害机器上安装其他的恶意功能插件,如键盘记录器、文件记录器或者远控木马。一般这些文件存放在下载器发送上线包的远程服务器下,此时通过 VT 搜索 IP 或者域名,查看其关联文件,可能会有收获。
通过 VT 扩线
搜索远程服务器 IP“162.0.229.203”,在“Relations”,可以看到多个域名,部分字符串“pop3”、“webmail”、“mail”和邮件服务相关,符合钓鱼邮件攻击的信息:
“Communicating Files”下也有多个关联文件,通过时间可以发现来自多个攻击活动:
点开关联文件中其他攻击活动的样本的“Behavior”,可以发现有两个比较固定的信息。
1.GET 请求的 URL:
2.释放文件到“C:\intel\logs\dlhost.exe”:
通过上面两个信息,写沙箱规则可以比较准确地抓到初始攻击载荷:
在 IP 的“Details”页面可以看到其“Google Results”中,有关联到蔓灵花历史攻击活动的报告,以及在线沙箱跑出的带有该 IP 的报告:
从以往攻击活动的在线沙箱报告中可以看到其他插件的信息,如在 %TEMP%路径下释放文件“rgdl.exe”,该文件有 PDB 信息“D:\C++\Reg_Entry\reg_en\Release\reg_en.pdb”,在蔓灵花早期的攻击中曾名为“regdl”:
“rgdl.exe”是一个注册表操作器,将“audiodq.exe”路径写入注册表的 Run 项,用于建立恶意可执行程序(“audiodq.exe”)的开机自启动:
上述两个 exe 都是可以通过在线网站扩线到的蔓灵花常用的插件。再搜索这两个字符串进行扩线,可以找到更多的历史攻击载荷、开源情报、甚至更完整的攻击活动报告。从开源情报中发现该下载器被命名为“ArtraDownloader”,源自 2019 年 Palo Alto Networks 公开发布的报告:
利用收集到的信息,组合搜索到以往历史攻击活动,发现多个本次活动未出现的插件,如键盘记录器“Igfxsrvk.exe”,信息收集器“Lsap.exe”,远控木马“MSAServices”和“MSAServicet”等。虽然与本次攻击活动的样本无强关联的关系,一般来说都是这几个搭配着使用,可以作为日常积累进行分析记录。
分析 APT 组织常用的 TTPs(攻击手法),将完整的攻击链分解为多个阶段,将多次攻击活动的样本名称、MD5、功能都记录保存之后,以文件名、PDB 信息、C2 指令,沙箱行为等信息进行组合,写出多角度多层级的检测规则。在理论理想(重音)的信息复利下,可以更好地发现、预警 APT 攻击活动,跟踪 APT 组织的手法演进。
结语
蔓灵花的常用下载器 ArtraDownloader 分析到这里就结束啦~
分析透一个经典的样本后,就相当于掌握了一个类型的病毒,恶意功能和实现的代码都是大同小异的。通过大量的分析和积累经验《机器学习》理解原理后就可以更快的找到断点和不同处。再将其特征应用到检测环境中,发现或追踪 APT 组织的攻击活动,甚至在大量的历史攻击手法演变数据下进行未来攻击的预测(如 StrongPity(下期再见)),掌握先机拉取更多的恶意载荷,为下一次极速响应争取时间。
最后多说几句:
为了感谢读者们,我想把我收藏的一些网络安全/渗透测试学习干货贡献给大家,回馈每一个读者,希望能帮到你们。
干货主要有:
① 2000 多本网安必看电子书(主流和经典的书籍应该都有了)
② PHP 标准库资料(最全中文版)
③ 项目源码(四五十个有趣且经典的练手项目及源码)
④ 网络安全基础入门、Linux 运维,web 安全、渗透测试方面的视频(适合小白学习)
⑤ 网络安全学习路线图(告别不入流的学习)
各位朋友们可以关注+评论一波 然后加下 QQ 群:581499282 备注:Infoq 即可免费获取全部资料
评论