恶意软件作者的圣杯之一是模仿合法进程的完美方法。这将允许他们在不被防病毒产品注意的情况下运行恶意模块。多年来,出现了各种各样的技术来帮助他们更接近这个目标。对于研究人员和反向工程师来说,这个主题也很有趣,因为它展示了使用Windows api的创造性方法。

处理Doppelgänging.这是一种模拟过程的新技术黑帽大会.过了一段时间,一个勒索软件被命名为发现同步采用这种技术出于恶意目的。尽管在野外的过程中仍然仍然罕见,但我们最近在Osiris银行木马的滴管中发现了一些特征(一个新版本的臭名昭着的kronos).经过仔细检查,我们发现原来的技术是经过进一步定制的。

实际上,恶意软件作者从过程中融合了元素,从而挖空,采摘两种技术的最佳部分,以创造一个更强大的组合。在这篇文章中,由于这种有趣的装载机,我们仔细看看Osiris如何在受害者机器上部署Osiris。

概述

Osiris以下图的图表中的三个步骤加载:

第一级装载机是由过程中的流程启发,但具有意想不到的扭曲。最后,由于第二阶段装载机,奥斯西尔可以提供。

加载额外的ntdll.

当ran时,初始滴滴器会创建一个新的暂停过程Wermgr.exe。

调查在注射器流程空间内加载的模块,我们可以看到NTDLL的额外副本:

这是一些恶意软件作者使用的众所周知的技术,以便逃避监控应用程序并隐藏他们使用的API调用。当我们密切检查从该额外的NTDLL调用哪些函数时,我们会发现更有趣的细节。它调用与NTFS事务相关的几个API。很容易猜到这里依赖于这种机制的过程Doppelgänging技术。

NTDLL是一个特殊的低级DLL。基本上,它只是一个包装纸SYSCALLS..它没有系统中其他DLL的任何依赖项。因此,它可以方便地加载,无需填充其导入表。

其他系统dll,如Kernel32,严重依赖从NTDLL导出的函数。这就是为什么许多用户监控工具钩子和拦截由NTDLL导出的函数:观察哪些函数被调用,并检查进程是否显示任何可疑的活动。

当然,恶意软件的作者知道这一点,所以有时候,为了欺骗这种机制,他们从磁盘加载自己的、新鲜的、未连接的NTDLL副本。有几种方法可以实现这一点。让我们看看奥西里斯滴管的作者是如何做到的。

查看内存映射,我们看到额外的NTDLL作为图像加载,就像其他DLL一样。这种类型的映射是装载的DLL的典型LoadLibrary函数或其低级版本,ldrloaddll..但是,每个可执行文件默认加载NTDLL,官方API不可能加载相同的DLL两次。

通常,恶意软件作者决定手动映射第二个副本,但这给出了不同的映射类型,并从正常加载的DLL中脱颖而出。在这里,作者制作了一个解决方法:他们将文件加载为部分,使用以下功能:

  • ntdll.ntcreatefile.- 打开ntdll.dll文件
  • ntdll。NtCreateSection- 要从此文件中创建一个部分
  • ntdll.zwmapviewofsection.- 将此部分映射到进程地址空间

这是一个智能移动,因为DLL被映射为图像,因此它看起来像它以典型方式加载。

该DLL进一步用于使有效载入注入更隐秘。拥有他们的NTDLL的新鲜副本,他们确信从安全产品没有挂钩的功能。

比较流程Doppelgänging和工艺镂空

加载器将有效载荷注入新进程的方式显示与过程Dopplegänging的一些重要相似之处。但是,如果我们非常仔细地分析它,我们也可以看到与去年在黑帽子上提出的经典实施的差异。不同的元素更靠近过程挖空。

经典Doppelganging过程:

过程挖空:

Osiris Loader:

创建一个新流程

osiris加载程序通过创建要注入的过程来启动。该过程由来自kernel32的函数创建:createprocessinternalw:

新进程(Wermgr.exe)以原始文件的暂停状态创建。到目前为止,它提醒我们的流程挖空,一个更旧的过程冒充技术。

在流程Dopplegänging算法中,创建新进程的步骤稍后拍摄,并使用不同的未记录的API:NTCreateProcessex:

这个差异非常显著,因为在Process Doppelgänging中,新进程不是从原始文件创建的,而是从一个特殊的缓冲区(section)创建的。本节应该在前面创建,使用NTFS事务中创建的“不可见”文件。在奥西里斯装载机中,这部分也会发生,但顺序颠倒了,让我们怀疑是否可以称之为相同的算法。

在创建过程之后,将相同的图像(Wermgr.exe)映射到加载器的上下文中,就像以前使用NTDLL完成的那样。

如下所示,装载机将修补远程过程。Wermgr.exe的本地副本将用于收集有关应应用修补程序的位置的信息。

使用NTFS交易

让我们从简要看看NTFS事务是什么。在数据库上运行时,通常使用此机制 - 以类似的方式,它们存在于NTFS文件系统中。NTFS事务将一系列操作封装到单个单元中。在事务中创建文件时,在事务承诺之前,外部无法访问它。ProcessDoppelgänging使用它们来创建丢弃有效载荷的隐形文件。

在分析的情况下,NTFS事务的使用完全相同。我们可以发现所使用的API中的小差异。加载器创建一个新事务,在其中创建一个新文件。使用的原始实现createTransaction.CreateFileTransacted从Kernel32。在这里,它们被低水平的等价物所取代。

首先,一个函数ZwcreateTransaction.从一个ntdll调用。然后,而不是CreateFileTransacted,作者打开交易文件通过RTLSetCurrentTransaction.随着zwcreatefile.(创建的文件是%temp%\\ liebert.bmp)。然后,Dropper将缓冲区写入文件。类似地,RTLSetCurrentTransaction.zwwritefile.用来。

我们可以看到正在写入的缓冲区包含新的PE文件:第二阶段有效负载。对于这种技术,文件通常只在事务中可见,不能被其他进程(如反病毒扫描程序)打开。

然后使用此交易文件来创建一个部分。可以执行它的功能仅通过低级API:ZwcreateSection / NtcreateSection可用。

创建部分后,不再需要该文件。交易回滚(通过zwollbacktransaction.),对文件的更改永远不会保存在磁盘上。

因此,上述部分与过程Doppelgänging的类比部分相同。使用从NTDLL的自定义副本调用,滴管的作者使其更加隐秘。

从一个部分到一个过程

此时,Osiris Dropper创建两个完全不相关的元素:

  • 一个过程(此时包含映射的合法可执行的Wermgr.exe)
  • 包含恶意负载的部分(从事务文件创建)

如果这是典型的进程Doppelgänging,那么这种情况永远不会发生,我们将基于映射有效载荷的部分直接创建的进程。所以,问题出现了,滴管的作者如何决定在这一点上将元素合并?

如果我们追踪执行,我们可以看到正在调用以下功能后,就在交易回来之后(格式:RVA;功能):

4b1e6; ntdll_1.ZwQuerySection 4b22b; ntdll.NtClose 4b239; ntdll.NtClose 4aab8; ntdll_1.ZwMapViewOfSection 4af27; ntdll_1.ZwProtectVirtualMemory 4af5b; ntdll_1.ZwWriteVirtualMemory 4af8a; ntdll_1.ZwProtectVirtualMemory 4b01c; ntdll_1.ZwWriteVirtualMemory 4b03a; ntdll_1.ZwResumeThread

因此,看起来新创建的部分刚刚映射到新过程中作为另一个模块。将有效载荷写入内存并设置必要的修补程序之后,如入口点重定向,恢复过程:

重定向的方式的方式看起来类似于过程中空的变体。修补远程过程的PEB,新的模块基础设置为添加的部分。(由于此,在进程恢复时,导入将自动加载。)

但是,目录重定向是在原始模块的入口点地址处的补丁完成的。单跳重定向到注入模块的入口点:

如果修补入口点失败,则加载程序包含一个入口点重定向的第二个变体,通过在主题上下文(zwgetthreadcontext - > zwsetthreadContext)中设置新地址中空工艺中使用的经典技术

两全其美

正如我们所看到的,提交人合并了一些过程Doppelgäng的元素,其中一些过程挖空了。这种选择并不偶然。这两种技术都有强大而弱点,而是通过将它们合并在一起,我们得到一个权力组合。

进程空心化最薄弱的一点是在注入有效负载的内存空间上设置的保护权限(更多信息)这里).流程挖空通过VirtualAllocex分配了远程过程中的内存页面,然后在那里写入有效载荷。它给出了一个不受欢迎的效果:访问权限(mem_private)与正常加载的可执行文件不同(mem_image)不同。

使用过程空心化负载的例子:

将有效载荷作为图像加载有效载荷的主要障碍是这样做,必须首先丢弃磁盘。当然,我们不能这样做,因为一旦下降,它很容易被杀毒剂挑选。

另一方面,进程Doppelgänging提供了一个解决方案:不可见的事务文件,有效负载可以在不被注意的情况下安全地丢弃。这种技术假设事务处理的文件将用于创建一个section (MEM_IMAGE),然后这个section将成为新进程的基础(使用NtCreateProcessEx).

使用ProcessDoppelgänging加载的有效载荷示例:

此解决方案运行良好,但要求所有进程参数都必须手动加载:首先创建它们RTLCreateProcessParametersex.然后将它们设置为远程PEB.它使得在64位系统上运行32位过程,因为在WOW64过程的情况下,有2个PEBS填充。

如果我们创建流程,那些流程Doppelgänging的问题可以很容易地解决,就像镂空的过程一样。作者而不是使用低级API,而不是使用低级API,这是创建新流程的唯一方法,而是使用来自Kernel32的文档API创建了一个完全的文件的过程。然而,可以在稍后添加携带有效载荷(MEM_IMAGE)的有效载荷的部分,并且执行可以重定向到它。

第二级装载机

下一层(8D58C731F61AFE74E9F450CC1C7987BE.)还不是核心,而是加载器的下一阶段。它只导入一个DLL, Kernel32。

它唯一的作用是加载最终有效载荷。在这个阶段,我们几乎无法找到创新的东西。Osiris核心通过片断打开包装并手动加载,以及其依赖关系进入加载程序过程中的新分配的内存区域。

自注后,装载机跳入有效载荷的入口点:

有趣的是,应用程序的入口点与头文件中保存的入口点不同。因此,如果我们转储有效负载并尝试相互依赖地运行它,我们将不会执行相同的代码。这是一种用来误导研究人员的有趣技术。

这是标题中设置的入口点在RVA 0x26840:

呼叫导致一个使应用程序进入无限睡眠循环的函数:

实际的入口点,从中执行恶意软件的开始,在0x25386处,它只已知到加载器。

第二阶段对Kronos加载器

原始Kronos使用了一个使用隐藏入口点的类似技巧(2A550956263A22991C34F076F3160B49).在Kronos的情况下,最终有效载荷注入SVCHOST。通过修补SVChost中的入口点,执行执行将重定向到核心:

在这种情况下,有效载荷内的入口点位于RVA 0x13b90,而在有效载荷的标头中保存的入口点(d8425578fc2d84513f1f22d3d518e3c3)在0x15002。

真正的kronos入口点处的代码与Osiris中的模拟点显示相似之处。然而,我们可以看到他们不相同:

一种精确的实现

第一阶段装载机受到Dopplegänging流程的强烈启发,以一种干净和专业的方式实现。作者采用了一种相对较新的技术元素,并将其与其他已知的技巧结合起来。这里使用的精度让我们想起了原始Kronos中使用的代码。然而,我们不能确定第一层是否由与核心机器人相同的作者编写。恶意软件分销商经常使用第三方加密器打包恶意软件。第二阶段与有效载荷更紧密地耦合,在这里我们可以说,这种层与核心一起准备这层。

必威平台APP通过打破其分销链,可以避免包括在垃圾邮件活动中发送的恶意文件和驾车下载,感谢我们的防爆模块,可以避免这种威胁。此外,我们的反恶意软件引擎可检测滴管和Osiris核心。

妥协指标(IOCs)

第1阶段(原始样本)

e7d3181ef643d77bb33fe328d1ea58f512b4f27c8e6ed71935a2e7548f2facc0

二级装载机

40288538 ec1b749734cb58f95649bd37509281270225a87597925f606c013f3a

奥西里斯(核心机器人)

d98a9c5b4b655c6d888ab4cf82db276d9132b09934a58491c642edf1662e831e