安全技术

恶意文档使用 Windows API 进行 Process hollowing

zeronohacker · 8月31日 · 2020年 · 165次已读

本文翻译自: https://0xevilc0de.com/maldoc-uses-windows-api-to-perform-process-hollowing/

 原文作者: Josh Stroschein

1 前述

恶意软件作者通常喜欢在 Office 文档中使用宏技术来替换系统中正常可执文件中的代码,这种技术称之为 Process hollowing。这篇文章的主要目的是识别这种技术并了解其使用方法,我还在 YouTube 上发布了一段 视频,这段视频介绍了如何使用 Ghidra 进行 shellcode 分析。

SVCHOST.exe 被用来 process hollowing

2 让我们从宏开始

首先,需检查宏以查看代码是从何处开始执行,在这个文档中,是以 Document_Open 函数开始,这个可以在 ThisDocument 流中找到。

恶意宏从 Document_Open() 处开始执行

此 Office 文档中存在大量混淆,使用 shellcode 进行 process hollowing,让我们来看下此 shellcode 在内存中的位置。

此文档中有两个流,一个是 ThisDocument,另一个是 Cowkeeper。在 Cowkeeper 流开始的部分,你会发现一些别名,这些别名最终用于进行 Windows API 调用。在这些函数中,VirtualAllocExRtlMoveMemory 可能用于内存分配,将 shellcode 复制到此处,如果你不熟悉这些 API 中的其中一个,则值得在 MSDN 上花上一些时间来研究它们。

Windows API 函数的声明

让我们跟踪这些文件使用的位置,请记住,在 VBA 中是使用别名。让我们从 betterment 开始,因为恶意文档需要内存才能将 shellcode 转入其中,betterment 是在 foam 里调用。

在 foam 函数里调用 betterment

betterment 或 VirtualAllowEx 将返回一个指向新分配内存的指针,值赋给了 diener,除此之外,还使用了 RtlMoveMemory 或 antecedency,下一步是找到该函数的调用位置,这个在 ThisDocument 流中 foam 调用里找到。

调用 foam

当你通过 bayberry 变量跟踪返回值时,你会看到在一个简单的加法中使用了它,bayberry + anklet,相加后的值,赋值给了 aprum,并用作名为 cabriolet 函数的参数。如果回顾我们前面分析过的所有别名,你会发现这个针对函数 EnumDateFormatsW,如何使用它来执行 shellcode 呢?

在 MSDN 上查询这个函数,第一个参数 ( 新分配的内存 ) 需要一个指向应用程序定义的回调函数的指针!

EnumDateFormats 在 MSDN 上的定义

最后要弄清的是在它被调用之前添加到地址基址的内容,这可能是 shellcode 的偏移量,这对于正确理解反汇编代码非常重要 ( 这实际上定义了入口点 )。 你可以继续跟踪宏以查看该值是什么,或者可以使用 Office IDE 设置断点并动态检查这些值,两者都是可行的选择。在这里我将使用动态分析。 如果在对 Cabriolet 的调用上设置断点,则将阻止其执行,并允许你查看参数的值。

调用 EnumDateFormats

aprum 的十六进制值为 ( 在这种情况下,这个地址值会发生变化 ):

shellcode 的入口点,基址为 0x70D0000

使用 Process Hacker 2 来查看进程的内存,RWX 的基址位于 0x70D0000 处,那也就意味着偏移为 0xE5D。

内存分配的位置

下面就为这段 shellcode:

在内存中的 shellcode

3 分析 shellcode

提取 shellcode 代码后,对此进行反汇编,这样才能对它进行分析。你可以先将此 shellcode 加载到反汇编程序中,本文使用的是 Ghidra,一旦加载分析了 shellcode 代码,请转到偏移为 0xE5D 定义的函数处。

在开始偏移 0xE5D 处定位的函数

由于这是 shellcode,因此需要它自身的导入表结构。通常在程序加载过程中,操作系统会为该程序处理该操作,因为 shellcode 不会自行完成正常的加载过程。在检查代码时,你会注意到十六进制值序列被移到堆栈中:

stack strings 的凭据

你还会注意到在此一串值后面调用了 sub_cf1。第一个用到称为 stack-strings 的技术,程序正在构建需要解析的 API 的 ASCII 字符串。如果右键单击每个十六进制值,则可以将显示更改为字符常量。

有意义的是,每当使用这些字符串时,都必须具有解决这些函数的能力。在大多数的 shellcode 中,stack strings 之后都会调用 sub_cf1。你可以通过执行动态分析来确认这一点,在对 sub_cf1 的调用上 ( 或之后 ) 设置断点,并检查 EAX 寄存器的内容,它应为字符串中函数的指针。

当然,遍历二进制文件并更改所有这些类型可能是乏味的,由于 Ghidra 具有插件框架,因此你可以通过此类插件来使这项工作自动化。值得花一些时间搜索现有的插件,也许已经存在!提示,你可以在 这里 找到一个。

如果你想了解如何解析函数地址,可以花一些时间来分析 sub_cf1。但是,我们的重点是找到 process hollowing 技术,包括以下API:

  • CreateProcess
  • ZwUnmapViewOfSection
  • VirtualAlloc
  • WriteProcessMemory
  • GetThreadContext
  • SetThreadContext
  • ResumeThread

一旦能够识别这些字符串,就可以在 shellcode 中跟踪如何以及何时使用它们。其中大多数在偏移 0x11d5 处。

运行 stack strings 脚本后的结果

CreateProcess 将所需的 EXE 加载到内存中,其中一个参数将是 EXE 的路径,另一个将是在挂起状态下创建进程。以挂起状态启动会阻止进程开始执行。 ZwUnmapViewOfSection 将用于删除所选二进制文件的原始 TEXT 部分,这使 shellcode 可以调用 VirtualAlloc 分配新的内存,并与 WriteProcessMemory 一起将新的代码复制到进程中。从那里,它将调用 GetThreadContext 并使用返回的值更新新代码的入口点。最后的步骤是调用 SetThreadContext 和 ResumeThread。现在看来,SVCHOST 的一个实例正在 System32 目录中运行,但是实际的代码已被替换!

4 样本信息

Tria.ge:https://tria.ge/reports/200317-pt9rcrh1l2/behavioral1

shellcode:https://github.com/jstrosch/malware-samples/tree/master/maldocs/hancitor/2016/October

(本文完)

0 条回应

必须 注册 为本站用户, 登录 后才可以发表评论!