CVE-2018-5002是Adobe Flash 0day漏洞,影响Adobe Flash Player 29.0.0.171及所有之前的版本。近期,研究人员发现有攻击活动传播利用CVE-2018-5002漏洞的文档,通过网络抓包获取了加密的恶意软件payload。加上收集的武器化文档,研究人员发现了攻击者的网络基础设施,并能够破解512位的RSA密钥,解密漏洞利用和恶意软件payload。因为攻击活动分多个阶段,每个阶段都依赖于前一阶段作为输入,因此研究人员将攻击活动命名为CHAINSHOT
。
首先需要了解的是整个攻击链,并理解哪里需要用到RSA密钥。恶意Excel文档中含有一个小的Shockwave Flash ActiveX对象,该对象含有下列特性:
图1. 恶意Shockwave Flash ActiveX对象特性
Movie
特性含有一个到Flash应用的URL,Flash应用会以明文形式下载并执行。
FlashVars
特性含有表示4个URL的长字符串,并会被传递给下载的Flash应用。Flash应用是混淆的下载器,下载器会在内存中创建一个随机的512位RSA密钥对。而私钥仍然在内存中,公钥mod n会发送给攻击者的服务器。在服务器端,模数(modulus)会和硬编码的e(指数)0x10001
一起来加密128位AES密钥,该密钥之前被用来加密漏洞利用和shellcode payload。加密的漏洞利用或payload会发回给下载器,下载器会用内存中的私钥来解密AES密钥和漏洞利用或payload。
当模数被发送给攻击者的服务器,同时可以通过网络抓包来获取。与硬编码的e一起,就有了可以获取私钥的公钥。因为攻击者使用的是512位长的密钥,不够安全,所以获取私钥是可能的。首先要及那个模数n分解为两个素数p和q,这可以通过Factoring as a Service项目解决。
顺着这个逻辑,可以将公钥随后的模数也发给攻击者的服务器来获取shellcode payload。
图2. HTTP POST请求含有模数n的加密shellcode payload就可以获取十六进制的模数:
前两个字节是用来提取32位版本的shellcode payload,移除这两个字节后,
0x7df305d5bcc659e5497e482bd0b507c44808deee8525f24b2712dc4a29f5c44e1e08c889a64521bbc67136ced11ace55b9bc2c1c7c96630aa515896b2f7341fd
进行因子分解后,就获得了两个素数P和Q:
P
58243340170108004196473690380684093596548916771782361843168584750033311384553
Q
113257592704268871468251608331599268987586668983037892662393533567233998824693
有了P和Q,就可以计算私钥了。研究人员用公开的工具来创建PEM格式的私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJAffMF1bzGWeVJfkgr0LUHxEgI3u6FJfJLJxLcSin1xE4eCMiJpkUh
u8ZxNs7RGs5VubwsHHyWYwqlFYlrL3NB/QIDAQABAkBog3SxE1AJItIkn2D0dHR4
dUofLBCDF5czWlxAkqcleG6im1BptrNWdJyC5102H/bMA9rhgQEDHx42hfyQiyTh
AiEA+mWGmrUOSLL3TXGrPCJcrTsR3m5XHzPrh9vPinSNpPUCIQCAxI/z9Jf10ufN
PLE2JeDnGRULDPn9oCAqwsU0DWxD6QIhAPdiyRseWI9w6a5E6IXP+TpZSu00nLTC
Sih+/kxvnOXlAiBZMc7VGVQ5f0H5tFS8QTisW39sDC0ONeCSPiADkliwIQIhAMDu
3Dkj2yt7zz04/H7KUV9WH+rdrhUmoGhA5UL2PzfP
-----END RSA PRIVATE KEY-----
有了私钥,就可以解密128位的AES密钥。研究人员选择用OpenSSL来解密:
openssl rsautl -decrypt -in enc_aes.bin -out dec_aes.bin -inkey private_key.pem
解密的AES密钥位于0x4处,长度为0x40字节。解密的AES密钥:
0x5BC64C5DC7EC96750CCB466935ED2183FE90212CB1BF6305F0B79B4B9D9261A4AC8A3E06F3E07D4037A40F4E221BB12E05B4DE2682B31617F177712BD12B501A
解密的AES密钥:
0xE4DF3353FD6D213E7400EEDA8B164FC0
然后用解密的AES密钥来解密真实payload。Flash下载器使用的AES算法有一个定制的初始向量(initialization vector,IV)位于加密点的0x44处,长16字节:
0xCC6FC77B877584121AEBCBFD4C23B67C
最后的解密还需要用到OpenSSL:
openssl enc -nosalt -aes-128-cbc -d -in payload.bin -out decrypted_payload -K E4DF3353FD6D213E7400EEDA8B164FC0 -iv CC6FC77B877584121AEBCBFD4C23B67C
解密的shellcode payload会用zlib进行压缩,可以通过0x789c的前两个字节看出来。然后用offzip进行解压,然后就获得了解密的shellcode payload。解密Flash漏洞利用的过程除了部用zib压缩和解压外都是相同的。
在解密了Flash漏洞利用和shellcode payload后,研究然后开始对恶意软件进行静态分析和静态分析。这个过程相对复杂,因为漏洞利用使用了混淆技术,而shellcode payload含有两个PE payload。考虑到静态分析代码的难度,研究人员决定创建一个简版的服务端PHP脚本来对进行动态分析。创建过程如下:
所有的请求文件都是gzip编码的,否则攻击链无效。研究人员将PHP脚本上传到了Github有兴趣的可以了解不同阶段以及工作原理。
https://github.com/pan-unit42/iocs/tree/master/pb40
关于漏洞利用已经有文章描述过了,所以本文关注将执行过程转变为shellcode payload的这一过程。大部分反编译的ActionScript漏洞利用代码也是混淆过的,但也有一些方法名是明文的。
因为当转变成可执行文件时,解密的shellcode payload并不会运行,所以必须了解其执行原理和传递的参数。所以,最好的选择就是executeShellcodeWithCfg32
方法,可以帮助找出传递的数据。运行时会创建一个shellcode模板并填充一些占位符。模板如下:
图3. 含有占位符(红色)的Shellcode模板
最后形成的shellcode如下:
图4. 用占位符填充的shellcode模板运行时版本
下面看一下占位符中的值,图4中地址0xA543000
是解密的shellcode payload的入口点,payload在真实代码之前有一个小的NOP sled(空指令滑行区,是在shellcode之前的一段很长的指令序列):
图5. 内存中的shellcode模板入口点
图4中的地址0x771A1239
位于ntdll.dll的函数NtPrivilegedServiceAuditAlarm
的中间:
图6. Windows API函数NtPrivilegedServiceAuditAlarm
图中中在通过call edx
调用API函数前,0x4D就会被移入eax,eax是API函数NtProtectVirtualMemory的ID。这样,在不需要直接调用的情况下就可以执行NtProtectVirtualMemory函数。
图4中地址0x9DD200C
处的数据是NTSTATUS返回的复制的NtProtectVirtualMemory的值。结构的地址以ebx的形式传递给shellcode payload,最后通过call edi
来执行shellcode payload。
也就是说,在0x1000字节区块中,shellcode payload的内存访问权限通过NtProtectVirtualMemory被修改为RWE
。最后的NTSTATUS代码会保存到ebx指向的内存中,然后执行shellcode payload。
同时,在利用的每个阶段,当出错时利用代码还会发送状态消息。这些状态消息与初始的Flash下载器发送的非常相似,会通过假的PNG图片的形式发送回攻击者服务器。URL中含有/stab/
目录,真实的消息是通过定制的数字组合编码后发送到。但利用代码的状态消息含有其他阶段的简写信息。状态消息有:
表1. Flash exploit代码中使用的状态消息
漏洞利用成功得到RWE权限后,执行就会传递给shellcode payload。Shellcode会加载内部嵌入的FirstStageDropper.dll
到内存中,并调用输出函数__xjwz97
来运行。DLL含有2个资源,分别是x64 DLL SecondStageDropper.dll
和kernel模式的shellcode。
FirstStageDropper.dll
负责将SecondStageDropper.dll
注入到另一个进程中,并执行。而shellcode payload只含有搜索和绕过EMET的代码,FirstStageDropper.dll
含有绕过Kaspersky 和Bitdefender的代码。对EMET,搜索emet.dll和emet64.dll的加载模块,对Kaspersky搜索klsihk.dll,对Bitdefender搜索avcuf32.dll和avcuf64.dll。还会收集和发送加密的用户系统和进程信息数据以及唯一的硬编码ID到攻击者服务器。数据会发送给URL,URL中含/home/
和/log/
目录,使用的加密算法为Rijndael。在分析过程中,攻击者服务器并没有响应,研究人员猜测会有一个命令发回来执行SecondStageDropper.dll
。
研究人员获取的样本是在用户模式通过线程注入SecondStageDropper.dll
的,x64 shellcode好像有kernel模式注入的选项。
kernel模式的shellcode含有Blackbone windows内存入侵开源库的一部分,下面是代码中的部分函数:
FindOrMapModule
BBQueueUserApc
BBCallRoutine
BBExecuteInNewThread
还有TitanHide中的代码,攻击者用相同的代码来查询Windows 7和10系统中的SSDT。
SecondStageDropper.dll
是final payload的下载器,会收集受害者系统中的信息,并回给攻击者服务器。如果发现下面的进程,就跳过执行:
表2. lookup列表中的进程名
CHAINSHOT通过HTTPS与下面的域名进行通信并获取final payload:
contact.planturidea[.]net
dl.nmcyclingexperience[.]com
tools.conductorstech[.]com
研究人员发现所有样本中final payload中的域名都是相同的。Shellcode payload、FirstStageDropper.dll和kernel shellcode都是一样的,但SecondStageDropper.dll含有一些不同的字符串。受害者不同,这些字符串就不同的,final payload目录是项目名(project name)的MD5表示。
表3. SecondStageDropper.dll中不同的字符串
Shellcode payload和PE文件中的部分代码相同,说明使用了同一个框架。比如,shellcode和CHAINSHOT使用了相同的处理错误代码的例外情况。也用了相同的代码来扫描和绕过EMET。
FirstStageDropper.dll还会发送数字9开头的消息给攻击者。比如,下面的抓包数据就成功测试了攻击者发回命令来执行SecondStageDropper.dll:
图7. VM中实现的攻击重现网络抓包
IceBrg报告的一个域名使用了writeup中记录的SSL证书。通过搜索使用相同证书的IP地址,研究人员发现了大量类似攻击活动相关的域名。虽然这些域名都来自相同的托管服务商和注册商,但可以减小被怀疑的可能。
研究人员发现了利用Adobe Flash CVE-2018-5002漏洞攻击中东地区的新工具集,因为攻击者使用了不安全的512位RSA加密所以才能进行分析。恶意软件会发送加密的用户信息到攻击者服务器并尝试下载final stage的植入。因为攻击者在同类攻击中使用了相同的SSL证书,所以研究人员发现了攻击者更多的基础设施。
Flash 0-day漏洞攻击的细节参见:https://www.icebrg.io/blog/adobe-flash-zero-day-targeted-attack