你可以把过去两年叫做勒索软件的年头。毫无疑问,勒索软件是最流行的恶意软件。但在去年年底,我们开始注意到,勒索软件的流行程度正逐渐被挖币者所取代。随着2018年的发展,这一趋势很有可能会进一步发展。

从受害者的角度来看,这是一个巨大的宽慰,因为矿工的威胁不像勒索软件那么大。是的,它们会使系统变慢,但一旦你摆脱了它们,你可以像以前一样继续使用你的电脑。没有数据被盗,或丢失的情况下,与勒索软件感染。

从恶意软件研究人员的角度来看,目前为止矿工的表现令人失望。它们没有提供足够深入分析的有趣材料,这主要是因为它们基于众所周知的开放源码组件,很少或没有混淆。

然而,我们偶尔会发现挖硬币的人有一些有趣的把戏。在最近的一个例子中,我们观察到一种叫做“天堂之门”的技术,它允许恶意软件从32位加载器注入64位进程。这个技巧并不新鲜——它的引入日期可以追溯到2009年——但在这张野外捕获的新样本中看到它是令人好奇的。

那些恶意软件分析的新手可以继续读下去,了解什么是天堂之门,以及如何分析它。

分析样品

这个样本是在继续Ngay运动(更多关于它在这里).对类似样本的背景调查让我找到了文章@_qaz_qaz他用类似的样本描述了早些时候的一场运动。然而,他的分析忽略了天门技术的细节。

行为分析

要观察上述注入,我们必须在64位系统上运行示例。我们可以看到,它运行一个记事本实例,带有挖掘加密货币的典型参数:

在ProcessExplorer中查看内存中的字符串,我们可以清楚地看到它不是一个真正运行的记事本,而是xmrigMonero矿业公司:

因此,现在我们确信记事本的图像已经在内存中被替换了,最有可能是被RunPE(进程空化)技术替换了。

主滴器是32位的,但它将一个有效载荷注入64位的记事本:

有趣的是,官方的Windows API并不支持这种类型的注入。我们可以从64位应用程序中读写32位进程的内存(使用Wow64 API),但不能反过来。

然而,也有一些非官方的解决方案,比如“天堂之门”技术。

天堂的大门概述

“天堂之门”技术最早是在2009年由一名绰号为罗伊·g·毕夫(Roy G. Biv)的黑客提出的。后来,又出现了许多改编版本,比如图书馆Wow64ext或者,基于它,W64oWoW64.在2015年的博文中,Alex Ionescu描述道对这种技术的缓解

但让我们来看看它是如何工作的。

在64位Windows上运行32位进程

在64位版本的Windows上运行的每个32位进程都运行在一个名为WoW64它模拟了32位环境。我们可以将其解释为在64位进程中创建的32位沙箱。因此,首先创建进程的64位环境。然后,在它内部创建32位环境。应用程序在这个32位环境中执行,它不能访问64位部分。

如果我们通过64位扫描器从外部扫描32位进程,我们可以看到它包含32和64位dll。最重要的是,它有两个版本的NTDLL: 32位(从目录SysWow64加载)和64位(从目录System32加载):

但是,32位进程本身不能看到64位部分,并且仅限于使用32位dll。要向64位进程进行注入,我们需要使用相应函数的64位版本。

代码段

为了进入环境中被禁止的部分,我们需要了解隔离是如何形成的。事实证明这很简单。可以通过代码段的不同地址访问32位和64位代码执行:32位是0x23, 64位是0x33。

如果我们以一种典型的方式调用一个地址,那么用来解释它的模式就是默认设置的模式。但是,我们可以使用汇编指令显式地请求更改它。

矿工内部:天堂之门实现

我将不做这个矿机的全面分析,因为它已经被描述在这里.让我们直接跳到乐趣开始的地方。恶意软件检查它的环境,如果它发现它在64位系统上运行,它会采取不同的路径注入64位进程:

在一些反分析检查之后,它会创建一个新的、挂起的64位进程(在本例中,它是一个记事本):

这是恶意负载将被注入的目标。

如前所述,为了将有效负载注入64位进程,我们需要使用适当的64位函数。

首先,加载器获取一个64位NTDLL句柄:

这个函数里面发生了什么get_ntdll需要一些更深层次的解释。作为参考,我们也可以看看相似的代码在狼的图书馆里

要访问进程环境的64位部分,我们需要操作段选择器。让我们看看我们的恶意软件如何进入64位模式:

这段代码似乎是从开源库直接复制的:https://github.com/rwfpl/rewolf-wow64ext/blob/master/src/internal.h#L26

段选择器0x33被推入堆栈。然后,恶意软件调用下一行:(通过这种方式,下一行的地址也被推到堆栈上)。

一个被推送的地址通过添加5个字节并设置在retf之后来固定:

最后,调用指令RETF。RETF是一个“远返回”,与非正式的RET不同,它不仅允许指定执行应该返回的地址,还允许指定段。它接受来自堆栈的两个dword作为参数。因此,当点击RETF时,实际的返回地址是:

0 x33:0x402a50

由于改变了段,从指定地址开始的代码被解释为64位。所以,在调试器下可见的代码是32位的…

实际上是64位的。

为了快速切换这些视图,我使用了PE-bear的一个特性:

这是这段代码的样子,如果它被解释为64位:

因此,这里执行的代码负责将R12寄存器的内容移动到堆栈上的一个变量中,然后切换回32位模式.这样做的目的是获得64位线程环境块(TEB),接下来我们从它获取64位过程环境块(PEB)—的相似的代码

64位PEB用作搜索64位NTDLL版本的起点。本部分是在休闲的方式(可以找到该技术的“普通”实现在这里),使用指向已加载库的指针,该库是PEB结构中的字段之一。PEB中有一个字段叫异地恋

Ldr是该类型的结构_PEB_LDR_DATA.它包含一个名为InMemoryOrderModuleList

这个列表包含所检查进程内存中所有已加载的dll。我们浏览这个列表,直到找到我们感兴趣的DLL,在本例中是NTDLL。这正是前面提到的函数get_ntdll所做的事。为了找到合适的名称,它调用下面的函数(记为)is_ntdll_lib-逐个字符检查库的名称,并将其与ntdll.dll进行比较。它相当于代码。

如果名称匹配,库的地址将在一对寄存器中返回:

一旦我们找到NTDLL,我们只需要获取适当函数的地址。我们通过浏览DLL的导出表来做到这一点:

下面的函数正在被获取:

  • NttUnmapViewOfSection
  • NtGetContextThread
  • NtAllocateVirtualMemory
  • NtReadVirtualMemory
  • NtWriteVirtualMemory
  • NtSetContextThread

我们知道,这些函数对于RunPE技术来说是典型的。首先,NtUnmapViewOfSection用于解除PE原始文件的映射。然后,在远程进程中分配内存,并写入新的PE。最后,流程的上下文被更改,以从注入的模块开始执行。

函数的地址被保存并在以后被调用(类似于代码)来操作远程进程。

结论

到目前为止,硬币挖掘者的作者并没有表现出很大的创造力。他们通过大量依赖开源组件来实现他们的目标。所描述的案例也显示了这种趋势——他们使用了一个现成的实现。

天门技术已经存在好几年了。一些恶意软件用它来秘密的目的.但是对于这个硬币挖掘者来说,作者的目标可能是通过使用最适合目标架构的有效负载版本来最大化性能。