恶意.NET安全攻防(一):使用ETW隐藏你的.NET

本文探讨了攻击者如何利用.NET进行恶意活动,尤其是如何通过ETW(Windows事件线程)隐藏.NET程序集的执行。文章介绍了execute-assembly的工作原理,蓝队如何通过ETW检测此类活动,以及红队如何通过禁用或篡改ETW来规避检测。作者还展示了如何在Cobalt Strike中执行SharpHound并利用ETW工具进行检测。
摘要由CSDN通过智能技术生成

恶意.NET安全攻防(一):使用ETW隐藏你的.NET

随着目前的防御机制不断加强对于PowerShell的检测功能,攻击者也不断改变他们所使用的战术,并逐渐改用到很少会被监测到的技术,.NET就是其中的一种。随着时间的推移,很多攻击者已经习惯了可以用于后漏洞利用的大量.NET Payload。诸如GhostPack和SharpHound这样的工具套件,已经成为攻击者武器库中的一部分,负责为其提供“动力”的框架,通常会是Cobalt Strike的execute-assembly。

这样的功能,有效减少了红队的工作量。在我看来,这也正是.NET工具持续流行的原因之一,它使得恶意活动运营人员可以在后漏洞利用的剧本(Playbook)中从非托管的进程中运行程序集。

如同PowerShell一样,随着时间的推移,Microsoft和终端安全厂商已经逐渐引入了防御功能,以帮助缓解在.NET Payload执行这方面的盲区(例如:在.NET 4.8中引入的AMSI)。对于攻击者来说,一大挑战就是如何继续保证在不产生告警的情况下继续利用这种技术。当然,目前AMSI对攻击者来说并不是一个太大的问题,奇热但是我们担心防御方所使用的其他技术没有得到足够的审查。

因此,在这几篇文章中,我们希望探讨蓝队能如何检测恶意的.NET,如何通过execute-assembly这样的方法来利用,以及红队的攻击者如何能绕过针对这类攻击的检测和限制。

在这一系列的第一篇文章中,我们将重点讨论Windows事件线程(ETW),以及如何使用它来表示正在从非托管进程执行的.NET程序集。

Execute-assembly的工作原理

为了了解防御方的侦查能力,我们首先需要研究execute-assembly技术的实际工作原理。

该方法的魔力在于,其背后隐藏着三个接口——ICLRMetaHostICLRRuntimeInfo和ICLRRuntimeHost。要开始将CLR加载到“非托管”进程中(也称为没有启动CLR的Windows进程),我们需要调用CLRCreateInstance方法。使用该函数,将会提供一个ICLRMetaHost接口,该接口在.NET Frameworks列表中公开了一些对我们有帮助的信息

ICLRMetaHost *metaHost = NULL;   
IEnumUnknown *runtime = NULL;
 
if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&metaHost) != S_OK) {
    printf("[x] Error: CLRCreateInstance(..)\n");
    return 2;
}
 
if (metaHost->EnumerateInstalledRuntimes(&runtime) != S_OK) {
    printf("[x] Error: EnumerateInstalledRuntimes(..)\n");
    return 2;
}

一旦选择了运行时,接下来就要实例化我们的ICLRRuntimeInfo接口,该接口又用于创建我们的ICLRRuntimeHost接口。

frameworkName = (LPWSTR)LocalAlloc(LPTR, 2048);
if (frameworkName == NULL) {
    printf("[x] Error: malloc could not allocate\n");
    return 2;
}
 
// Enumerate through runtimes and show supported frameworks
while (runtime->Next(1, &enumRuntime, 0) == S_OK) {
    if (enumRuntime->QueryInterface(&runtimeInfo) == S_OK) {
        if (runtimeInfo != NULL) {
            runtimeInfo->GetVersionString(frameworkName, &bytes);
            wprintf(L"[*] Supported Framework: %s\n", frameworkName);
        }
    }
}
 
// For demo, we just use the last supported runtime
if (runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&runtimeHost) != S_OK) {
    printf("[x] ..GetInterface(CLSID_CLRRuntimeHost...) failed\n");
    return 2;
}

在创建后,所有内容都会通过两个方法调用合并在一起。ICLRRuntimeHost::Start将CLR加载到我们的进程中,而ICLRRuntimeH

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值