通过ETW补丁绕过EDR监控:原理、实现与实战 1. 项目概述当EDR成为“天眼”我们如何在其眼皮底下“隐身”在当前的网络安全攻防对抗中终端检测与响应EDR系统已经成为了企业防御体系中至关重要的“天眼”。无论是像CrowdStrike、SentinelOne这样的商业产品还是像微软Defender for Endpoint这样的原生方案它们都深度集成在操作系统中监控着进程、网络、文件、注册表等几乎一切行为。对于渗透测试人员或红队队员而言如何在执行攻击模拟时绕过这些“天眼”的监控实现无痕或低痕的横向移动、权限提升和数据窃取是衡量技术深度的关键指标。传统的绕过方法如直接进程注入、内存操作或利用未签名驱动随着EDR内核回调Kernel Callbacks和受保护进程Protected Process Light, PPL等机制的普及其生存空间被急剧压缩。EDR厂商的响应速度极快一个公开的绕过技术可能在几天甚至几小时内就被加入特征库。因此我们需要将目光投向操作系统更底层、更核心的机制——事件追踪Event Tracing for Windows, ETW。ETW是Windows内置的高性能内核级追踪框架绝大多数安全产品包括EDR和杀毒软件都严重依赖ETW来收集系统活动日志。试想一下如果我们能“修补”ETW让它对我们指定的进程“视而不见”或者篡改它上报的事件数据那么依赖它的EDR就相当于被蒙上了眼睛。这就是“通过ETW补丁实现无痕渗透测试”的核心思路不是正面硬刚EDR的检测引擎而是釜底抽薪干扰其最关键的数据源。这篇文章我将从一个实战红队的角度深入剖析ETW的工作原理并手把手带你实现一种相对新颖的ETW补丁技术。这种方法不依赖于公开的、容易被检测的第三方工具而是通过直接操作内存中的ETW函数实现动态、临时的绕过。整个过程将在Windows 10/11及Server 2016环境中进行适合有一定C/C和Windows内部机制基础的渗透测试人员、安全研究人员参考。我们的目标不仅是实现“绕过”更要理解其背后的“为什么”从而在面对未来更复杂的防御体系时能够举一反三。2. ETW机制深度解析EDR的“数据管道”是如何工作的要成功绕过一个系统首先必须彻底理解它。ETW绝不仅仅是一个简单的日志系统它是一个由内核模式驱动程序ntoskrnl.exe和用户模式组件共同构成的复杂事件发布-订阅架构。整个体系可以分为四个核心部分控制器Controller、提供者Provider、消费者Consumer和会话Session。控制器通常是像logman.exe这样的工具或EDR自身负责创建和管理ETW会话。一个会话就像一个专用的数据通道。提供者是事件的源头它可以是内核组件如进程管理器、网络栈也可以是用户模式的应用程序如.NET CLR、你的自定义程序。提供者通过一个唯一的GUID进行注册。消费者则是事件的接收端EDR代理就是一个典型的消费者它订阅感兴趣的会话实时接收事件数据进行分析。最关键的部分在于会话。当EDR启动时它会创建一个或多个高权限的ETW会话。例如一个常见的会话是Microsoft-Windows-Threat-Intelligence它提供了大量关于进程创建、模块加载、注册表访问等敏感操作的事件。EDR通过EtwNotificationRegister这类API向系统注册回调当特定事件发生时内核会直接将事件数据通过这个会话传递给EDR的消费者进程。那么事件数据是如何从提供者流向消费者的呢这依赖于一组核心的函数我们称之为ETW的“发送”函数。对于用户模式的提供者最常用的是EventWrite和EventWriteTransfer这两个API。当一个应用程序比如一个恶意进程执行了某个操作相关的ETW提供者就会调用这些函数将包含操作细节的事件结构体发送出去。内核中的ETW组件nt!EtwWrite、nt!EtwWriteEx等最终处理这些事件并将其分发给所有订阅了该提供者的会话。注意这里存在一个常见的误解认为ETW事件都是“被动”收集的。实际上很多关键安全事件是“主动”上报的。例如ntdll.dll中的EtwEventWrite函数会在进程创建NtCreateUserProcess、线程创建、映像加载等关键动作发生时被自动调用。这意味着即使你的恶意程序本身不触发任何日志操作系统内核和系统库也会替你“报告”行踪。理解了这条数据流我们的攻击面就清晰了如果我们能拦截或篡改EventWrite、EtwWrite或EDR用于接收事件的回调函数就能控制哪些信息被上报甚至伪造信息。直接挂钩Hook这些函数是经典思路但现代EDR会扫描关键函数的内存完整性检测内联钩子Inline Hook。因此“补丁”的思路更具隐蔽性我们不永久性地修改函数代码而是在运行时动态地修改ETW相关数据结构或函数指针使其指向我们控制的、什么也不做No-Op或过滤事件的“桩函数”Stub Function。3. 核心思路与方案选型为什么选择“函数指针补丁”基于对ETW架构的理解我们可以设计几种不同的补丁方案。每种方案都有其优缺点选择哪一种取决于目标环境、所需隐蔽级别和操作的复杂度。方案一用户模式EventWrite函数挂钩。这是最直接的方法。通过注入DLL或使用APC异步过程调用等方式在目标进程内挂钩advapi32!EventWrite或ntdll!EtwEventWrite。当这些函数被调用时我们的钩子函数可以先检查事件GUID或描述符如果是来自我们想要隐藏的提供者例如与我们恶意活动相关的就直接返回成功而不真正发送事件。优点是实现相对简单对单个进程有效。缺点是过于常见容易被用户模式钩子扫描UMH检测到且只影响当前进程如果系统其他组件如内核通过其他路径发送事件则无法拦截。方案二内核模式EtwWriteEx函数挂钩。这是在系统层面生效的方法。通过加载一个未签名的内核驱动或利用有漏洞的已签名驱动在内核空间挂钩nt!EtwWriteEx。这样可以拦截所有通过ETW发送的事件无论来自用户模式还是内核模式。优点是效果彻底。缺点是技术门槛高风险极大。在启用了驱动签名强制DSE和内核模式代码完整性KMCI的系统上加载未签名驱动几乎不可能而利用漏洞则不稳定且可能引发系统崩溃。此外内核钩子同样是EDR和反病毒软件的重点监控对象。方案三修补ETW提供者注册表或上下文结构。ETW提供者在注册时会得到一个REGHANDLE注册句柄其背后关联着一个包含函数指针等信息的内部结构。通过内存扫描和解析我们可以定位到特定提供者的这个结构并将其EnableCallback或类似的回调函数指针修改为空函数。这样当控制器EDR尝试启用该提供者时回调不会执行提供者实际上处于“静默”状态。优点是非常隐蔽直接操作数据结构没有明显的代码修改痕迹。缺点是逆向工程成本高结构体因Windows版本不同而异稳定性差。方案四动态修补ETW会话的“启用提供者”列表函数指针。这是我们本次重点探讨的折中且相对新颖的方案。其核心在于ETW会话在启用某个提供者时需要调用一个内部函数来建立连接。这个函数指针通常保存在一个全局或会话相关的数据结构中。我们的目标是找到这个函数指针例如与nt!EtwpEnableTrace相关的回调并在内存中将其临时替换为指向我们自定义函数的指针。我们的自定义函数会检查要启用的提供者GUID如果它是我们想要绕过的安全提供者如{D02A9C27-79B8-40D6-B05C-3CA6A6DE3B7C}就简单地返回一个错误状态码让启用操作失败。对于其他无害的提供者则调用原始函数保持系统正常功能。为什么选择方案四系统级效果在会话层面操作可以影响所有尝试向该会话发送事件的进程包括系统进程。隐蔽性较高我们修补的是一个不常被安全软件检查的内部函数指针而非广为人知的公开API。动态性与可恢复性补丁可以在运行时应用和移除无需重启或持久化修改磁盘适合短期渗透测试任务。兼容性考量相比内核驱动此方案主要在用户态的高权限进程如注入到拥有SeDebugPrivilege的进程中实现避免了驱动签名的难题。当然它也有挑战需要深入逆向ETW内部结构并且由于Windows版本更新偏移量和结构定义可能会变需要一套动态定位的方法。4. 实战环境准备与关键数据结构逆向在开始编写补丁代码之前我们需要一个实验环境。建议使用Windows 10 21H2或Windows 11的虚拟机并安装一个EDR产品如微软Defender for Endpoint的评估版或开源的Elastic Endpoint用于验证效果。你需要安装Visual Studio 2019/2022和WDKWindows Driver Kit但请注意我们主要开发用户模式程序WDK主要用于其头文件和符号。首先我们需要理解关键的数据结构。由于微软未公开ETW内部结构的完整定义我们必须依赖逆向工程和公开的研究成果。一个至关重要的结构是_ETW_REG_ENTRY它代表一个在系统中注册的ETW提供者。通过WinDbg预览版并加载微软的公有符号srv*我们可以进行探索。以nt!EtwpProvRegEntry为线索可以找到注册表项链表。_ETW_REG_ENTRY大致包含以下对我们有用的字段不同版本有差异typedef struct _ETW_REG_ENTRY { LIST_ENTRY RegList; // 链表项 GUID ProviderId; // 提供者的GUID PVOID Callback; // 启用/禁用回调函数指针 PVOID CallbackContext; ULONG Flags; // ... 其他字段 } ETW_REG_ENTRY, *PETW_REG_ENTRY;我们的目标之一是找到并遍历所有的_ETW_REG_ENTRY从而定位特定安全提供者的回调函数地址。另一个关键目标是找到控制ETW会话启用提供者的函数指针。研究显示nt!EtwpEnableTrace函数内部会调用一个通过参数传递或全局变量访问的回调。这个回调指针可能存储在_ETW_SESSION或相关的全局变量如EtwpHostSiloState中。动态定位策略我们不能在代码里写死偏移量。一个可靠的方法是使用特征码扫描Pattern Scanning。例如我们可以搜索ntoskrnl.exe在内存中的镜像寻找EtwpEnableTrace函数中调用特定回调指令的字节序列如call rax或call qword ptr [rcxxx]然后通过计算指令的操作数来提取出回调函数的指针地址。实操心得逆向的“捷径”。完全从零开始逆向耗时巨大。强烈建议参考安全社区已有的开源项目和研究博客例如F-Secure、MDSec等团队发布的关于ETW绕过和SilkETW项目的文章。它们提供了许多关键的结构定义和搜索模式。我们的工作不是重复造轮子而是在理解的基础上整合并实现一个更稳定、更隐蔽的变种。同时要准备好应对不同Windows版本可以设计一个简单的版本检测逻辑为不同版本应用不同的特征码。除了逆向我们还需要提升我们工具的权限。为了读取和修改内核内存ntoskrnl.exe的镜像我们的进程需要SeDebugPrivilege特权。这可以通过以下步骤实现BOOL EnableDebugPrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, hToken)) { return FALSE; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, tp.Privileges[0].Luid)) { CloseHandle(hToken); return FALSE; } tp.PrivilegeCount 1; tp.Privileges[0].Attributes SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, tp, sizeof(tp), NULL, NULL)) { CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return GetLastError() ERROR_SUCCESS; }5. 实现ETW函数指针补丁的详细步骤现在我们进入核心的实现环节。整个过程可以分为五个主要步骤定位内核镜像、搜索特征码找到目标函数指针、备份原始指针、安装自定义回调函数、以及最后的清理与恢复。5.1 第一步获取ntoskrnl.exe基址并解析PE我们需要在用户态读取内核模块的信息。这可以通过EnumDeviceDrivers函数或查询NtQuerySystemInformation的SystemModuleInformation类来实现。后者能提供更详细的信息。#include windows.h #include psapi.h #include vector PVOID GetKernelModuleBase(const wchar_t* moduleName) { DWORD cbNeeded; std::vectorHMODULE modules(1024); if (!EnumDeviceDrivers(reinterpret_castLPVOID*(modules.data()), modules.size() * sizeof(HMODULE), cbNeeded)) { return nullptr; } for (auto base : modules) { wchar_t szModName[MAX_PATH]; if (GetDeviceDriverBaseNameW(base, szModName, sizeof(szModName)/sizeof(wchar_t))) { if (_wcsicmp(szModName, moduleName) 0) { return base; } } } return nullptr; } // 使用示例 PVOID ntBase GetKernelModuleBase(Lntoskrnl.exe); if (!ntBase) { // 尝试使用 NtQuerySystemInformation // ... }获取基址后我们需要将其当作一个PE文件来解析以便计算相对虚拟地址RVA到实际内存地址的转换。我们需要实现或借用简单的PE解析代码来读取ntoskrnl.exe的.text节区因为我们的特征码大概率在这个代码节中。5.2 第二步特征码扫描定位回调指针假设通过逆向我们得知在EtwpEnableTrace函数中存在这样一段指令模式以x64为例这是概念性示例实际模式需逆向确定... 前序指令 ... 48 8B 05 XX XX XX FF mov rax, qword ptr [rip - 0xXXXXXX] ; 从相对地址加载一个指针到RAX FF D0 call rax ; 调用该指针 ... 后续指令 ...我们的目标是找到这个call rax指令并计算出rax中值的来源地址即[rip - 0xXXXXXX]对应的内存位置这个位置存储的就是我们要补丁的函数指针。我们需要在ntoskrnl.exe的.text节区内进行字节扫描。为了提高准确性最好使用更长的、更独特的特征码例如包含EtwpEnableTrace函数开头部分字节。// 简化的特征码扫描函数 PVOID FindPattern(PVOID base, size_t size, const char* pattern, const char* mask) { auto* data static_castconst char*(base); size_t patternLen strlen(mask); for (size_t i 0; i size - patternLen; i) { bool found true; for (size_t j 0; j patternLen; j) { if (mask[j] x pattern[j] ! data[i j]) { found false; break; } } if (found) { return const_castchar*(data[i]); } } return nullptr; } // 使用示例假设我们已经获取了.text节的地址和大小textBase, textSize // char pattern[] { 0x48, 0x8B, 0x05, 0x??, 0x??, 0x??, 0xFF, 0xFF, 0xD0 }; // char mask[] xxx????xx; // PVOID foundAddr FindPattern(textBase, textSize, pattern, mask);找到指令地址后需要解析指令计算相对偏移得到存储目标函数指针的地址我们称之为pTargetFunctionPointer。5.3 第三步备份与内存属性修改在修改这个指针之前我们必须先备份它的原始值以便后续恢复。同时该指针所在的内存页很可能是只读的我们需要使用NtProtectVirtualMemory或VirtualProtectEx但目标地址在内核空间需通过特殊方式来修改其保护属性。在用户态我们无法直接调用这些API修改内核内存。这里就需要利用一个关键技巧通过一个合法的、有权限的渠道——\Device\PhysicalMemory对象在旧版本中或利用有漏洞的驱动。然而在现代系统中直接映射物理内存已被严格限制。更可行的方案是将我们的代码运行在内核模式。这意味着我们需要一个内核驱动。但为了避免签名问题我们可以尝试利用一个已知的、已签名的、但存在漏洞的驱动如gdrv.sys、RTCore64.sys等来提供读写内核内存的原语。这属于漏洞利用Exploit范畴风险高且不稳定。另一种折中的用户态方案我们不去修改内核中的函数指针而是修改用户态中EDR消费者进程内用于接收ETW事件的回调函数指针。这要求我们能够向EDR进程注入代码或操作其内存。这同样需要高权限SeDebugPrivilege和适当的进程注入技术并且针对性强只对特定的EDR进程有效。鉴于内核补丁的复杂性和风险下文将重点描述一个用户态方案的实现思路挂钩目标EDR进程中的ntdll!EtwEventWrite函数。这虽然不如内核补丁彻底但更易于实现和演示且原理相通。5.4 第四步实现并安装自定义桩函数我们的自定义桩函数Stub Function需要与原函数具有相同的调用约定对于x64 Windows是快速调用约定__fastcall。它的逻辑很简单检查事件是否来自我们希望隐藏的提供者。如何检查EtwEventWrite的函数签名是ULONG EtwEventWrite( _In_ REGHANDLE RegHandle, _In_ PCEVENT_DESCRIPTOR EventDescriptor, _In_ ULONG UserDataCount, _In_reads_opt_(UserDataCount) PEVENT_DATA_DESCRIPTOR UserData );RegHandle是提供者注册句柄。我们需要建立一张“黑名单”将我们恶意进程的注册句柄或者已知的安全事件提供者GUID通过RegHandle可以反向查询到加入其中。如果事件在黑名单中我们的桩函数直接返回STATUS_SUCCESS0让调用者认为事件已成功写入但实际上我们什么都没做。如果不在黑名单则调用原始的EtwEventWrite函数。我们需要用汇编或编译器特性来编写这个桩函数。以下是一个概念性的C内联汇编示例x64// 假设我们通过Trampoline Hook替换了函数开头 // 原始函数的前N个字节被替换为跳转到我们的MyEtwEventWrite // 我们保存了这N个字节和被覆盖地址后的指令地址OriginalFunction。 extern C ULONG_PTR OriginalEtwEventWrite; __declspec(naked) ULONG MyEtwEventWrite(REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData) { __asm { push rbp mov rbp, rsp sub rsp, 20h // 影子空间 // 检查RegHandle是否在黑名单中 mov rcx, [rbp30h] // 假设RegHandle是第一个参数实际需根据调用约定调整 call IsHandleInBlacklist test al, al jnz DoNotLog // 不在黑名单跳回原函数 jmp [OriginalEtwEventWrite] DoNotLog: // 直接返回成功 xor eax, eax // STATUS_SUCCESS leave ret } } bool IsHandleInBlacklist(REGHANDLE RegHandle) { // 这里实现你的黑名单逻辑 // 可以通过RegHandle查询其对应的GUID与已知的安全提供者GUID列表对比 // 例如{D02A9C27-79B8-40D6-B05C-3CA6A6DE3B7C} (Microsoft-Windows-Threat-Intelligence) // 或者记录下我们恶意进程自己注册ETW时返回的RegHandle return false; // 示例 }安装钩子的过程就是经典的“蹦床”Trampoline钩子技术计算跳转偏移将目标函数开头的指令替换为jmp MyEtwEventWrite并保存被覆盖的原始指令。5.5 第五步进程注入与钩子安装为了将我们的钩子安装到EDR进程我们需要将包含钩子代码的DLL注入到目标进程。可以使用远程线程注入CreateRemoteThreadLoadLibrary、APC注入、或者父进程欺骗等技术。注入成功后在DLL的DllMain或一个初始化函数中执行上述的钩子安装流程。关键点我们需要在目标进程内定位ntdll!EtwEventWrite的地址。这可以通过GetModuleHandle和GetProcAddress实现但要注意注入的DLL与目标进程在同一个地址空间所以直接调用这两个API获取的就是目标进程内的地址。// 在注入的DLL中 HMODULE hNtdll GetModuleHandleW(Lntdll.dll); FARPROC pEtwEventWrite GetProcAddress(hNtdll, EtwEventWrite); if (pEtwEventWrite) { InstallHook(pEtwEventWrite, MyEtwEventWrite); }6. 效果验证与隐蔽性增强技巧完成补丁或钩子安装后如何验证其效果最直接的方法是观察EDR控制台。执行一些通常会触发告警的操作例如使用Mimikatz尝试抓取密码、使用PsExec进行横向移动、或者加载一个已知的恶意反射DLL。如果EDR没有产生相应的进程创建、网络连接或恶意行为告警说明我们的绕过可能成功了。更技术性的验证方法是直接监控ETW事件流。可以使用Windows自带的logman和tracerpt工具或者更强大的PerfView、SilkETW等工具。在绕过前开启一个ETW会话收集相关提供者如Microsoft-Windows-Threat-Intelligence的事件执行操作你会看到大量事件。安装我们的补丁后重复操作对应的事件应该消失或显著减少。隐蔽性增强技巧间接系统调用Syscall在安装钩子或进行内存操作时避免直接调用VirtualProtect、WriteProcessMemory等高级API因为这些调用本身会被EDR通过用户模式API钩子监控。转而使用直接系统调用如NtProtectVirtualMemory、NtWriteVirtualMemory可以绕过一部分用户态钩子。动态解析与偏移计算不要硬编码函数地址或偏移量。通过PEB进程环境块遍历LDR_MODULE链表来获取模块基址通过导出表解析函数地址。对于内部函数指针坚持使用特征码扫描并设计版本适配逻辑。内存操作伪装如果必须修改内存尽量使用NtMapViewOfSection等相对低调的API或者利用合法的内存操作如动态代码生成作为掩护。避免连续、大量的可疑内存修改。钩子检测规避我们的钩子本身也可能被检测。可以采用更隐蔽的钩子技术如“热补丁”Hotpatch利用函数前缀的mov edi, edi指令或者使用硬件断点DRx寄存器来实现执行流转向但这需要内核权限。清理痕迹任务完成后务必恢复所有修改过的函数指针或代码字节。卸载注入的DLL清理远程线程。理想情况下整个操作不应在磁盘留下任何持久化文件所有代码应在内存中反射加载。7. 常见问题、检测与对抗实录在实际操作中你肯定会遇到各种问题。下面记录了一些典型场景和排查思路。问题1特征码扫描失败返回空指针。原因分析ntoskrnl.exe的版本与你的特征码不匹配。Windows 10不同版本如1909、20H2、21H2以及Windows 11之间函数内部实现可能有细微差别。解决方案准备多套特征码或者实现更智能的扫描。例如先定位函数EtwpEnableTrace的起始地址可以通过解析ntoskrnl的PDB调试符号如果可用或者搜索该函数常见的序言字节然后在函数体范围内搜索更具体的指令模式。也可以考虑使用社区维护的签名数据库。问题2注入成功但钩子安装后导致目标EDR进程崩溃。原因分析可能的原因有1钩子函数MyEtwEventWrite的调用约定或栈处理不正确破坏了栈平衡。2覆盖的指令不完整破坏了原函数的逻辑。例如如果覆盖的指令是某条多字节指令的中间部分。3黑名单检查函数IsHandleInBlacklist访问了无效内存。解决方案使用反汇编引擎如Capstone、Zydis来精确计算需要覆盖的指令长度确保复制完整的指令到“蹦床”中。仔细检查钩子函数的汇编代码确保其符合x64调用约定影子空间、栈对齐等。在黑名单检查函数中加入严格的空指针和边界检查。问题3绕过效果不理想部分事件仍被记录。原因分析ETW提供者众多你的补丁或钩子可能只拦截了部分路径。例如你挂钩了ntdll!EtwEventWrite但某些事件可能通过advapi32!EventWrite、kernel32!TraceEvent或直接内核调用EtwWriteEx发送。此外一些EDR可能使用多个ETW会话订阅了不同的提供者集合。解决方案扩大拦截范围。尝试同时挂钩EventWrite和EtwEventWrite。更激进的方法是尝试定位并修补ETW会话控制器用于接收事件的核心回调这又回到了内核补丁的思路。使用PerfView等工具详细分析在你执行操作时具体是哪些提供者的哪些事件被触发然后有针对性地将其GUID加入黑名单。对抗与检测视角作为一名蓝队成员如何检测这种ETW补丁攻击呢内存完整性检查定期扫描关键ETW函数EtwEventWrite、EventWrite、EtwWriteEx的内存查找内联钩子jmp、call指令或代码补丁。可以使用GetProcAddress获取函数地址然后读取其开头几个字节与磁盘上文件中的原始字节进行比较。行为异常检测监控ETW事件流的突然中断或特定重要提供者如威胁情报提供者的事件率降至零。这可能是ETW被禁用的信号。内核回调监控使用ObRegisterCallbacks监控进程/线程句柄操作检测对EDR进程的远程线程注入尝试。使用PsSetLoadImageNotifyRoutine监控非法的DLL加载。函数指针验证在EDR驱动中可以校验其依赖的关键ETW内部函数指针的完整性例如通过校验和或与一个安全备份对比。多源数据关联不要完全依赖ETW。结合进程树分析、网络流量分析、文件系统监控等其他数据源。如果网络连接存在但对应的进程创建事件缺失这就是一个强烈的异常信号。8. 总结与个人体会通过ETW补丁实现绕过是一场在操作系统观测框架深水区的博弈。它考验的不仅仅是漏洞利用或代码编写能力更是对Windows内部机制、编译器行为、反调试和反逆向技术的综合理解。我个人的体会是这种技术的生命周期正在变得越来越短。随着微软不断强化安全特性如Kernel Data Protection (KDP)、Hypervisor-Protected Code Integrity (HVCI)直接修改内核代码或关键数据结构的难度呈指数级上升。因此红队技术必须向更底层如虚拟化层、固件或更“合法”的方向发展。例如利用Windows原生且未受监控的组件如Windows COM、WMI事件订阅来达到持久化和执行的目的或者深入研究如何滥用合法的、已签名的驱动程序LOLDrivers来获得内核读写能力这比从零开发一个绕过DSE的驱动要现实得多。最后必须强调授权。所有上述技术只应在你拥有完全所有权或已获得明确书面授权的系统上进行测试。未经授权的测试是违法的。真正的安全价值在于理解这些攻击技术从而设计出更有效的防御策略让整个数字环境变得更加安全。技术本身没有善恶但使用技术的人必须心存敬畏恪守边界。