Trickbot是攻击银行客户并窃取凭证的金融机构木马,是一款多模块恶意软件,不同的模块负责不同的恶意活动。该恶意软件从2016年开始活动,这么多年更新更新都会出现新的技巧和模块。Trickbot包含的模块有从浏览器窃取数据、从Outlook从窃取数据、锁定用户计算机、收集系统信息、收集网络信息和窃取域凭证。
Cyberbit恶意软件研究团队研究了最新的Trickbot变种,并与之前的变种进行了比较。最新的Trickbot变种使用了stealthy code injection(隐身代码注入)技术,该技术用直接系统调用、反分析技术、关闭安全工具来执行process hollowing(现代恶意软件常用的一种进程创建技术)。新变种的行为模式与Flokibot银行木马非常相像。
本报告分析了新变种和其感染向量——一个恶意word文档。
Trickbot变种是从含有宏代码的word文档(SHA256: aef2020534f81bbebec6c9b842b3de6fd4f5b55fe5aeb3d9e79e16c0a3ff37ab)中下载的。当用户开启宏并放大或缩小文档时宏文件才会执行,这可能是为了绕过沙箱。
图1 – 放大/缩小栏是红色高亮显示
图2 – 只有窗口大小变化后宏才会执行,InkPicture1_Resize
方法会触发用户放大/缩小
与大多数恶意宏文件一样,Trickbot的宏文件也经过了混淆,最终会执行一个下载和执行Trickbot的PowerShell脚本。在解混淆和重命名后,PowerShell脚本如下图所示:
图3 – 下载和执行Trickbot的PowerShell脚本
SHA256: 1c81272ffc28b29a82d8313bd74d1c6030c2af1ba4b165c44dc8ea6376679d9f
在对恶意软件初步分析后,可以看出调试路径为:c:\users\exploitdb\desktop\esetfuck\release\esetfuck.pdb
恶意软件执行后会先调用Sleep(30000)
完成休眠30秒,以绕过沙箱监测。然后用RSA软件解密资源:
图4 –休眠30秒用红色标注,调用资源解密函数用紫色标注
0x405680
处的函数会接收到key (private_key)和key size (16),分别是指向解密缓存的指针和大小;解密的资源是一个DLL文件(SHA256: 31A4065460CEF51C8B4495EFC9827926A789F602F5AD5C735EA1D88CAFAC135A)和一个名为shellcode_main
的输出函数。
图5 –资源解密函数内部
然后,有一些调用过程:
对CreateWindowEx
的调用是不执行的,代码的逻辑会导致对SendMessageW
的27次调用,对InSendMessage
的调用也是不执行的。
图6 – 这只是调用的一部分
在从一个调用跳转到另一个调用时,恶意软件会继续恶意意图:将解密的DLL与开始地址位于0x10000000
的缓存进行映射。
然后调用Sleep(3) 3890次,结果是执行过程中会有11秒的延迟。这种短时间休眠加多次调用的方式可能可以很好地绕过沙箱监测,因为短暂的休眠看着是一种比较正常的行为。最后,执行位于0x10001900
输出的shellcode_main
函数。
图7 –每隔三秒钟休眠和唤醒一次
新变种使用了Trickbot 原来就使用的process hollowing技术,process hollowing技术被用来解压。
process hollowing技术是通过直接系统调用完成的,这与Flokibot恶意软件使用的方法系统。研究人员认为这两个恶意软件逐渐有代码共享。
在Flokibot恶意软件中,并非所有用于process hollowing的函数都直接使用系统调用,其中一些函数从之前保存在栈中的函数地址进行调用。
正常情况下,暂停进程是用CreateProcessW
创建的,选择的进程就是恶意软件的进程。该进程的主线程的线程上下文结构是用GetThreadContext
保存的。
图8 – 创建暂停进程
然后,恶意软件用CreateFileW
来获取ntdll.dll
的句柄,ntdll.dll
可以用ReadFile
将自己复制到VirtualAlloc
分配的缓存中,然后分配另一个缓存来将内存与原始副本(raw copy)进行映射:
图9 – 从硬盘上读取 Reading ntdll.dll
图10 – 手动映射ntdll.dll
上图中最后一个调用指令是调用一个可以接收对映射的ntdll.dll缓存和函数名的CRC32值的指针。该函数会对映射的ntdll.dll的所有函数名进行CRC32运算,然后与输入的CRC32值进行比较。如果匹配,就返回目标函数开始的缓存偏移量。下图是UnmapViewOfSection解析出的地址:
图11 – 指向含有映射的ntdll.dll(0x1cd0000)和0x90483ff6=CRC32(NtUnmapViewOfSection)的缓存的指针
代码中使用CRC32算法的证据是使用的常量0xedb88320
,这是逆向CRC32多项式的十六进制表示。
图12 –计算字符串NtAllocateVirtualMemory的CRC32值,0xedb88320
是CRC32多项式的二进制表示
然后,提取出系统调用数,这些参数会进入栈中,然后通过将系统调用树放在EAX上和用sysenter指令传递给内核来完成适当的函数调用。
图13 – 系统调用数提取
图14 – sysenter命令,EAX含有系统调用次数,栈中有适当的参数
执行上面的步骤是为了完成下面的功能:
如上所述,并不是所有的函数都是为了hollowing。一些函数是从之前保存在栈中的地址调用的。完整的hollowing顺序如下:
直接系统调用的函数用蓝色表示,从之前栈中保存的地址调用的函数用红色表示:
与之前的变种类似,运行恶意软件之后,会复制自己和加密的模块到C:\Users\%USERNAME%\AppData\Roaming\msnet
。
图15 – Trickbot (1c9_patched.exe) 和其模块
该变种还通过下面的命令关闭和删除了Windows defender服务:
最后一行是关闭Windows Defender实时监控的PowerShell命令。
从中可以看出Trickbot通过之间系统调用调用了两个其他的函数。但并不实现直接系统调用到上面的三个函数,奇怪的是有一些函数也没有在Flokibot中实现过。
另一个相同点是使用CRC32算法对函数名进行哈希。在Flokibot中,CRC32与2字节值的XOR一起使用,而Trickbot中CRC32是单独使用的。
Trickbot还在不断地发展,并逐渐使用一些新的技巧,也变得更加静默。但它并不是通过直接系统调用来实现所有的process hollowing函数调用的。为了避免被分析,Trickbot中加入了sleep、无用的函数调用这样一些简单的技术。为了避免被检测到,Trickbot还关闭和删除了Windows defender服务。