OceanLotus隐写术分析报告

ang010ela 技术 2019年4月19日发布
Favorite收藏

导语:BlackBerry Cylance研究人员对OceanLotus APT组织使用的payload加载器中使用的隐写术进行了分析。

简介

OceanLotus APT,也称为APT32和APT-C-00,是从2012年开始活跃的间谍组织。BlackBerry Cylance研究人员近期发现该组指的一个新的payload加载器,其中使用隐写术来读取隐藏在.png图像文件中的加密payload。隐写算法使用了最低有效位(least significant bit)算法来减少与原始图片的差别,以预防给分析人员和工具发现。解码、解密并执行后,可以看到一个混淆后的加载器来加载APT 32的后门。Cylance研究人员共发现2个与隐写加载器共同使用的后门,分别是Denes 后门和Remy后门的变种。

隐写加载器#1

image.png

该OceanLotus恶意软件加载器尝试模拟McAfee的McVsoCfg DLL并尝试通过合法On Demand Scanner可执行文件进行顺带加载。与该加载器一起出现的是保存在.png图像文件中的加密payload。该.png文件本身是非恶意的,其中的payload是用隐写术编码在图像文件中的,具体是使用了颜色代码的最低有效位来保存隐藏信息,这样就不会改变原来的图片。编码的payload是用AES128加密的,并用XOR算法进行混淆试图欺骗隐写检测工具。

特征

· 顺带加载DLL

· 用定制的.PNG隐写术来加载下一阶段payload

· 用AES128实现payload解密

· 加载Denes后门

加载器分析

恶意DLL会导出相同的函数名作为原始的mcvsocfg.dll库。所有的导出都含有解密payload的相同的代码,然后注入到内存并执行。

image.png

图1. 常见的导出入口

Payload是用隐写术编码在一个单独的.png文件中的。解码的payload是用AES 128加密的,最后使用XOR 0X3B进行混淆。XOR KEY并不是硬编码的,而是从C:\Windows\system.ini文件的第1个字节读取的:

image.png

图2. Payload解码和解密路径

研究人员发现其中一个payload是编码在怪盗基德(日文:怪盗キッド;英文:Kid the Phantom Thief,是日本动漫《魔术快斗》中的主人公以及《名侦探柯南》中的客串角色)的图片中的。

image.png

图3. “Kaito Kid” 怪盗基德

为了提取payload,恶意软件会初始化GDI+ API,并获取图片的宽度和长度值:

image.png

图4. 使用GDI+ APIs

Payload的大小是编码在图片的前4个像素值中的。在获取了payload的大小后,恶意软件会分配适当的内存缓冲区并一个字节一个字节地解码剩下的payload:

image.png

图5. 获取payload的大小

Payload的编码方式与大小类似,payload的每个字节都是通过图片中之后的像素的ARGB色值计算得来的:

image.png

图6. 隐写解码路径

如果payload的大小比用来保存payload的图片大的话,剩下的payload就会负载图片的IEND marker之后,可以从文件中直接读取:

image.png

图7. 读取剩余的payload的字节

像素编码算法也非常直接,目的就是减少修改带来的视觉差异,而且只修改红绿蓝色字节值的最低有效位。阿尔法通道(α Channel或Alpha Channel)字节值并没有修改。为了编码payload的字节,前3位(0-2)会保存在红色中,接下来3位(3-5)会保存在绿色中,最后的2位(6-7)会保存在蓝色中。解码是非常简单的逆向操作:

image.png

图8. RGBA像素解码

Windows会把.png像素的RGBA值通过GdpiBitmapGetPixel API转化为ARGB编码,如下图所示:

image.png

图9. 像素颜色解码

比如,ARGB像素值0xFF4086DB会解码为0xF0:

image.png

图10. ARGB像素值解码

为了帮助加密payload的恢复,下面的python脚本用来从.png图像中解码出像素值:

image.png

图11. 从.png图像中解码像素值的python脚本

在从.png图像中加密后,加载器会初始化密钥和IV(初始向量)来执行加密payload的AES解密。这些值都硬编码在二进制文件的.rdata区域的一个256伪随机字节数组中。数组的前2个字节指明了key和IV的相对偏移值:

image.png

图12. 提取key和IV值

image.png

图13. 256伪随机字节数组中的AES key和IV

加载器从开源的Crypto++2库来完成AES 128实现:

image.png

图14. Crypto++接口

研究人员与Crypto++ github上的源码进行了对比,恶意软件作者应该并没有对代码进行修改。SimpleKeyringInterface class用于初始化key,而IV会传递给SetCipherWithIV函数:

image.png

图15. 算法和密钥初始化

解密是用treamTransformationFilter类进行的,其中StreamTransformation cipher设置为AES CBC解密模式:

image.png

图16. 使用CryptoPP StreamTransformationFilter类进行Payload解密

库代码会对CPU特征进行无数次检查,基于检查的结果会选择与特定处理器对应的加密函数实现:

image.png

图17. CPU特征检查和调用AES解密路径

其中一种AES实现使用Intel AES-NI加密指令集,许多Intel和AMD CPU都支持该指令集:

image.png

图18. 使用Intel AES-NI加密指令集

解密的payload会进行最后的转变,与从C:\Windows\system. Ini文件中读取的第1个字节进行异或计算,ini文件应该是‘;’ (0x3B)开头的:

image.png

图19. 移除 payload混淆的最后一层

研究人员执行了CyberChef相同的步骤并解码出加密的payload,是一个x86 shellcode,是调用立刻opcode序列开始的:

image.png

图20. 用CyberChef 解密payload的第一个区块

隐写加载器#2

image.png

概览

第二个隐写加载器在实现上有隐写区别,但是payload提取与前面的是一样的。主要的区别在于:

· 解密路径调用的方式,是从DLLMain函数调用的,而不是导出函数;

· Payload调用的方式,是从覆盖栈中的返回地址而不是直接调用;

· 其他反分析检查的实现

研究人员对多个该DLL的变种进行了分析,发现其可能与受害者的环境有关。其中一些名字含有与安全软件相关的进程:

· wsc_proxy.exe

· plugins-setup.exe

· SoftManager.exe

· GetEFA.exe

特征

· 顺带加载的DLL

· 父进程名的反调试/反沙箱检查

· 用定制的.png隐写术来加载下一阶段payload

· 用AES128实现payload解密

· 通过覆写栈中的返回地址来执行payload

· 加载Remy后门的变种

加载器分析

DLL并不含有导出表,其完整功能位于DllMain路径:

image.png

图21.变种2

DllMain函数执行后,恶意软件首先会从其resources解密一个字符串,并与父进程的名字进行比较。如果名字不同,恶意软件就会直接退出。含有期望进程名(ICON/1)的resource会与合法C:\Windows\system.ini file – 0x3B (“;”)进行异或计算:

image.png

 图22. ICON/1 resource中混淆的文件名

image.png

图23. 父进程名比较

如果父进程名匹配,恶意软件就会遍历栈来找出进入父进程的text section的内存的返回地址:

image.png

图24.找到栈中的返回地址

Payload会从.png文件中读取。在该实例中,payload完全包含在图片的像素色值中,IEND marker中没有其他剩余信息。

image.png

图25. 含有编码的payload的图像

最后加载器会解密payload到内存缓冲区中,并用到该缓冲区的指针来覆写之前发现的返回地址,确保恶意shellcode会在DLL尝试返回该调用时执行:

image.png

图26. 用到解密payload的指针来覆盖返回地址

嵌入在payload中的加载器看似是Veil “shellcode_inject” payload的一个变种,之前OceanLotus用它来加载过Remy后门。在该例子中,shellcode被配置为从payload中加载编码的后门:

image.png

图27. 解码进程

后门启动器

Final payload是以启动器DLL的形式出现的,DLL中的.rdata区域含有加密的后门,在resource中含有明文的配置数据。Resources中还保存了至少1个C2通信模块。后门DLL和C2通信dll都用了大量垃圾代码来混淆,因此很难使用静态分析技术和调试工具进行分析。除了Denes和Remy后门外,研究人员还发现至少两个不同的通信模块,分别是DNSProvider和HTTPProv。

初始shellcode

含有final后门的启动器二进制文件是RC4加密的,封装在混淆的shellcode中。研究人员还发现了熟悉的明文DOS stub,但是header和二进制文件body的其他部分都是加密的:

image.png

图28. Payload中的DOS stub

Shellcode使用OceanLotus的标准方法扁平化控制流和插入垃圾跳转代码的形式来混淆:

image.png

图29.垃圾opcodes

Shellcode以非常变种的方式开始,在加载的模块中寻找kernel32.dll库的基:

image.png

图30. Walk模块

image.png

图31. Find模块

image.png

图32. 检查kernel32.dl

找到kernel32 base之后,shellcode会计算LoadLibraryA和GetProcAddress函数的地址,并用来解析其他必要的API,包括VirtualAlloc, RtlMoveMemory和RtlZeroMemory:

image.png

图33. 解析kernel32.dll imports

image.png

图34. VirtualAlloc字符串

image.png

图35. Shellcode imports

在解析完API之后,shellcode会解密启动器库并加载到内存中。MZ header, PE header和其他section都用RC4算法和硬编码的key进行解密:

image.png

图36. PE头部进行RC4解密的代码

一旦所有的section都加载了,MZ/PE header就会在内存中0化:

image.png

图37. 在加载的模块中找出.reloc section

Shellcode会继续执行payload DLL的入口点:

image.png

图38. 执行payload DLL的入口点

启动器DLL

DLL的内部吗是随机寻找的CLSID,它只导出一个名为DllEntry的函数

image.png

图39. DLL name和export

执行后,启动器会通过用恶意路径的地址来覆盖内存中的入口点来尝试hook合法的wininet.dll库。如果成功的话,每当系统加载wininet.dll时,随后释放的后门DLL的入口点会在原始wininet入口点之前被执行:

image.png

image.png

图40. Hook wininet.dll的路径

image.png

图41. 后门解密路径

因为payload只是解压缩到内存中,还没有DLL注入路径,所以恶意软件需要固定解压缩的代码中的所有指针,这是用硬编码的值和偏移量来完成的。这部分利用了全部启动器代码的90%,包括超过11000次修订:

image.png

图42. 用来固定指针的代码

启动器会调用后门DLL的入口点:

image.png

图43. 调用后门DLL的入口点

从resource中读取配置和解压缩C2通信库的路径会被临时替换到函数CComCriticalSection的指针来调用。这样混淆的方法就很难在代码中看出来:

image.png

图44. 到资源解密路径的混淆调用

启动器会从resource加载配置,并用来自后门DLL的导出来初始化内存中的配置值。Resource P1/1含有配置值,包括端口号和注册表路径:

image.png

图45. 嵌入的配置

Resource P1/2含有的C2 url:

image.png

图46. 硬编码的C2 URL

Resource P1/ 0xC8含有用于C2通信的其他压缩的DLL:

image.png

图47. 压缩的C2通信库

来自resource的配置值会以参数的形式传递给后门函数:

image.png

图48. 初始化配置值

Resource 0XC8的内容在被解压缩后,来自后门DLL的另一个函数会用来加载C2模块到内存中,并调用CreateInstance:

image.png

图49. 解压缩第二个DLL

最后,启动器将控制权传递给主后门路径:

image.png

图50. 调用主后门路径

配置

image.png

后门DLL

后门DLL保存在启动器的.rdata section,并用LZMA压缩用RC4加密。二进制文件用大量的垃圾代码进行了混淆。DLLMAIN函数用到hook路径的指针替换了到GetModuleHandleA API的指针,当以NULL作为参数调用时,该指针会返回后门DLL base:

image.png

图51. 覆盖GetModuleHandleA指针

image.png

图52. GetModuleHandleA hook

后门还含有从resource中加载C2通信模块到内存中的导出函数,然后调用“CreateInstance” export。研究人员在分析后门的全部功能时发现与之前发现的Remy后门比较类似。

C2通信模块

DLL保存在启动器的resources中,并用LZMA压缩。也是严重混淆的,但是与后门混淆的方式有所不同。虽然不含有内部名,但研究人员相信它是HttpProv库的一个变种。后门使用该模块与C2服务器进行HTTP/HTTPS通信,并有代理绕过的功能。

更多参见:https://s7d2.scene7.com/is/content/cylance/prod/cylance-web/en-us/resources/knowledge-center/resource-library/white-papers/OceanLotus-Steganography-Malware-Analysis-White-Paper.pdf

如若转载,请注明原文地址: https://www.4hou.com/technology/17215.html
点赞 3
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论