最近描述的Floki机器人SC杂志的Peter Stephenson博士,又是一个基于泄露的宙斯代码的机器人。然而,作者提出了各种定制修改,使其更有趣。

根据黑市上公布的广告,这种机器人能够进行非常隐蔽的注射,避开许多检测机制。我们决定看看它背后有什么把戏。事实证明,虽然滴管使用的注入方法本身并不新颖,但它也有一些有趣的曲折之处,这在恶意软件中并不常见。

分析示例

注:核心模块取决于滴管准备的数据,它们在独立运行时崩溃。

的Floki滴管

Flopi Dropper看起来很简单,并且在野外发现没有任何外部保护层。它有3个资源,具有描述性的名称 -BOT32.,bot64,钥匙:
物件

当我们试图观察它的活动时,我们可以看到它正在向explorer中注入。

滴管至探测器
实际上,当我们将调试器附加到新创建的资源管理器进程时,我们可以看到植入的一些外籍代码 - 它是在具有完整权限(RWE)的三个附加内存区域上写字:

enc_explorer_injected

但是,当我们跟踪API调用时,我们无法找到对将代码写入资源管理器进程的函数的任何引用。痕迹的片段:

[...]28a8;被调用的模块:C:\Windows\system32\kernel32.dll:CreateProcessW\ windows \系统\系统32\内核32.dll:IsWow64Process 1d94;C:\Windows\system32\kernel32.dll:IsWow64Process 1d94\ windows \system32\kernel32.dll:GetThreadContext210f;被调用的模块:C:\Windows\system32\kernel32.dll:iswow64process2aa1;被调用的模块:C:\Windows\system32\kernel32.dll:WaitForSingleObject 1818;被调用的模块:C:\Windows\system32\kernel32.dll:isbadreadptr182a;被调用的模块:C:\Windows\SYSTEM32\ntdll.dll:RtlFreeHeap 2aad;被调用的模块:C:\Windows\system32\kernel32.dll:ExitProcess

我们可以看到一个新的过程被创建了,它的上下文也在被改变——这意味着操纵——但写在哪里呢?为了找到这个问题的答案,我们将深入研究代码。

内部

开始时,滴管动态加载一些所需的导入:

入口点

所使用的方法描述了,作者试图不留下任何工件,以方便检测将要使用的模块和函数。它不是通过名称来加载dll,而是通过枚举system32目录中的所有dll来选择它们:

load_lib

为了混淆,它不会使用字符串比较。相反,它计算每个找到名称的校验和。校验和由CRC32从xored的名称创建,其中一个硬编码值,对于特定样本是常数(在所描述的样本中,它为0x58e5):

循环冗余异或

将得到的校验和与期望值进行比较,直到找到并加载适当的模块。以类似的方式枚举特定模块的导出表,并解析所需的函数。

初始导入加载后,将使用完全相同的方法搜索NTDLL.DLL。

如我们所知,NTDLL.dll提供了执行本机系统调用的接口。每个版本的Windows都可以使用不同数量的Syscall才能做同样的事情。这就是为什么建议通过包装器使用它们,我们可以在NTDLL导出的函数中找到。例如,这是如何实现的ntallocatevirtualmemory.可以在Windows 7上查看:

nt_allocate

Windows 8的另一个变体看起来有点不同:

nt_allocate_win8.

常见的部分是,将要执行的系统调用的编号移动到EAX寄存器中。
滴管将NTDLL加载到内存中,并从所选函数中提取系统调用:

0: NtCreateSection1:ntmapviewofsection.3: ZwWriteVirtualMemory 4: NtProtectVirtualMemory5:ntresumethread.6:ZwopenProcess 7:ntduplatebject 8:ntunmapviewofsection

它通过比较每个函数代码的开头来检查0xB8,这是一个字节码,用于将值移动到EAX中:

比较操作码

如果检查通过,则将被移到EAX中的系统调用值提取并存储在缓冲区中:

存储系统调用

然后,当droper想要调用一些函数时,它使用这些提取的值。从保存系统调用的数组中获取系统调用的数目,并将其复制到EAX。函数的参数被压入堆栈。指向参数的指针被加载到EDX中——系统调用在中断的帮助下被触发——INT 0x2E:

进行系统调用

这就是函数NtCreateSection,NtMapViewOfSectionNtResumeThread有人打电话给你。这些都是API调用跟踪中缺失的元素,所以它解释了很多!

例1 -滴漏器进行的调用相当于调用函数NtCreateSection:

ntcreatesection

示例2 - Dropper通过使用Syscall映射了一节 - 它是等效调用该功能NtMapViewOfSection:

map_view_of_section.

一旦准备好内存,外壳代码就会复制到那里:

钩形物

在准备之后,这些部分被映射到资源管理器流程的上下文中,资源管理器流程被创建为挂起状态。使用SetThreadContext,它的入口点被重定向到注入内存页。恢复explorer进程时,新代码将执行并继续解包恶意内核。

在注射的这一点上,它的恶意核心尚未揭示 - 它的解密过程发生在植入的shellcode内资源管理器. 这也是该滴管针对检测工具采取的额外对策。

此机器人使用的另一个技巧是针对内联挂钩的防御 - 一种由各种监控工具使用的方法。将所有映射的DLL与其原始版本进行比较,从磁盘读取丢弃器。如果检测到任何异常,则丢弃器通过从其原始版本复制的代码覆盖映射的DLL。结果,该功能正在“未悬on”,并且监控程序正在失去执行的呼叫上的跟踪。来自杜鹃的示例 - 呼叫后未搞乱的程序NtGetThreadContext-结果沙箱失去了对执行调用的控制:

布谷鸟

结论

所示的概念不是新颖的,然而它以一种有趣的方式使用。许多程序通过监视API调用来检测恶意活动,这通常是恶意软件滥用的。此外,用于自动分析挂钩API函数的应用程序,以监视它们正在使用的位置和方式。呈现的方法允许绕过它们 - 同时相对容易实现。

在本例中,作者没有充分利用该技术的潜力,因为他可以通过直接系统调用实现所有与注入相关的函数——相反,他选择只使用一些子集,与写入远程内存区域有关。其他一些系统调用已加载但未使用–这可能表明该产品仍在开发中。新流程的创建和上下文的更改仍然可以通过API监控检测到——这足以引起警报,并使滴管比预期的更隐蔽。

附录

https://www.evilsocket.net/2014/02/11/on-windows-syscall-mechanism-and-syscall-numbers-extraction-methods/–关于Windows系统调用机制和系统调用号码提取方法


这是一篇由Hasherezade撰写的客座文章,Hasherezade是一位对InfoSec非常感兴趣的独立研究员和程序员。她喜欢详细介绍恶意软件,并与社区分享威胁信息。看看她的推特@哈舍雷扎德以及她的个人博客:https://hshrzd.wordpress.com.