AI摘要:本文分析了Process Mockingjay和Dirty-Vanity两种新型进程注入技术。Process Mockingjay利用合法DLL的RWX内存节执行恶意代码,绕过API钩子。Dirty-Vanity则滥用Windows Fork机制,将代码写入与执行分离,打破传统EDR的AWE检测链。防御策略需从API监控转向行为分析、内存完整性检查和跨进程关联,监控Fork原语,追踪进程血缘,检测异常行为,以应对这些隐蔽的注入技术。
I. 引言
进程注入作为规避安全检测、提升权限和维持持久性的核心技术,其复杂度和隐蔽性不断提升。在网络安全领域,攻击者与防御者之间的对抗从未停止。传统的注入技术,如早期APC注入、线程劫持、反射DLL注入和进程空洞等,虽然在过去行之有效,但随着终端检测与响应(EDR)解决方案的日益成熟,这些方法的检测能力也显著增强。EDR系统通过API钩子、行为分析、内存监控等多种手段,对常见的注入模式形成了有效的防御屏障。这种不断演进的防御态势迫使攻击者寻求更底层、更隐蔽的注入方法,以绕过现有的防护机制。
II. Process Mockingjay:利用 RWX 内存区域的隐蔽注入
核心原理与机制
Process Mockingjay 是一种新型的进程注入技术,其核心在于利用 Windows 系统中合法动态链接库(DLL)内预先存在的读-写-执行(RWX)内存节,以实现恶意代码的隐蔽执行。这种方法与传统的进程注入技术存在显著差异,使其在规避现代EDR检测方面展现出独特的优势。
与传统注入方法的对比
传统的进程注入技术通常依赖于一系列显式的内存操作,这些操作往往是EDR系统重点监控的指标。例如,攻击者常使用 VirtualAllocEx
在目标进程中分配新的内存区域,随后使用 WriteProcessMemory
将恶意代码写入该区域,最后通过 CreateRemoteThread
或 QueueUserAPC
等API创建或劫持线程来执行代码。EDR产品通常会在这些关键API调用处设置钩子,以检测和阻止可疑行为。
然而,Process Mockingjay 的独特之处在于,它在执行注入代码时,声称无需显式分配内存、设置新的权限或创建新线程。这种“无痕”特性使其与传统的注入方式显著不同,对EDR的检测能力构成了直接挑战。
滥用合法 DLL 中的 RWX 节
Process Mockingjay 攻击的核心在于识别并利用系统中合法且受信任的DLL文件中预先存在的RWX(读-写-执行)内存节。这些RWX节通常是为了支持某些合法功能(如即时编译、自修改代码)而存在的,但却成为了攻击者利用的“灰色地带”。攻击者将恶意代码直接复制到这些天然具备RWX权限的区域中。这意味着恶意代码能够以合法进程的身份在受信任的内存空间中运行,从而混淆EDR的判断。
例如,研究人员发现 Visual Studio 2022 Community 目录下的 msys-2.0.dll
包含一个默认的16KB RWX 节,可被用于此目的。这种利用现有合法内存区域的策略,使得恶意代码能够“回响”在用户态的RWX内存中,这也是该技术被称为“Mockingjay”(模仿鸟)的原因。
无显式内存分配、权限设置或线程创建的特点
通过利用已存在的RWX节,Process Mockingjay 绕过了 VirtualAllocEx
等内存分配API,也无需调用 VirtualProtectEx
等权限设置API。这意味着EDR无法通过监控这些常见的、通常被视为可疑的API调用来检测注入行为。此外,恶意代码的执行通常通过劫持现有线程的执行流,或在进程的正常执行流程中被触发,而非创建新的远程线程。这种“无痕”特性使得其与传统注入方式显著不同,对EDR的检测能力构成了直接挑战。
NTDLL 钩子绕过
Process Mockingjay 的隐蔽性不仅体现在内存操作上,还延伸到了用户态钩子(user-mode hooking)的规避,特别是针对 ntdll.dll
的钩子。
EDR 用户态钩子检测原理
大多数EDR通过在用户态关键系统DLL(如 ntdll.dll
)的导出函数入口点设置钩子(hook)来监控进程的API调用行为。当程序调用这些被钩子的API时,控制流会先跳转到EDR的代码,进行检测和判断,以识别潜在的恶意活动。
Mockingjay 如何通过干净 NTDLL 副本和直接系统调用绕过钩子
Process Mockingjay 进一步增强了隐蔽性,它通过获取一份干净的 ntdll.dll
副本。攻击者从这份干净的 ntdll.dll
中解析出所需系统调用的真实地址,并获取EDR钩子添加的 jmp
指令之后的“测试指令”地址。然后,恶意shellcode会直接准备系统调用号(如在EAX寄存器中),并使用远跳指令(jmp
)直接跳转到这些“测试指令”的地址,从而绕过EDR在 ntdll
函数入口处设置的钩子。这种技术与“Hell's Gate”或“SysWhispers”等直接系统调用方法类似,旨在规避用户态API监控。EDR通常重点关注 WriteProcessMemory
、NtWriteVirtualMemory
、CreateRemoteThread
或 NtCreateThreadEx
等API,而Mockingjay通过这种方式避免了这些常见监控点的触发。
实现细节与攻击流程
Process Mockingjay 的实现细节体现了其对现有Windows机制的巧妙利用,以达到隐蔽注入的目的。
详细攻击步骤与伪代码示例
Process Mockingjay 的攻击步骤通常分为两类:
- 自注入 (Self-injection): 攻击者自定义的应用程序(例如
nightmare.exe
)直接加载含有RWX节的DLL到自身内存空间,然后利用该RWX节执行恶意代码。 远程进程注入 (Remote Process Injection):
- 执行自定义应用程序: 攻击者运行一个自定义的注入器程序。
- 启动目标进程: 注入器程序通过
CreateProcessW
等API,以挂起(或正常)方式启动一个受信任的应用程序(例如ssh.exe
),并确保该程序加载了含有RWX节的DLL(例如msys-2.0.dll
)。 - 获取进程句柄: 注入器程序获取目标进程(
ssh.exe
)的句柄。 - 复制恶意代码: 注入器程序将恶意shellcode直接复制到目标进程中
msys-2.0.dll
的RWX节中。这一步避免了VirtualAllocEx
和WriteProcessMemory
的直接调用,而是利用了已存在的“天然”RWX区域。攻击者可能通过其他内存写入原语(如NtWriteVirtualMemory
)来进一步避免被监控。 - 触发执行: 恶意代码在目标进程的正常执行流中被触发。这可能通过修改现有线程上下文(如RIP寄存器),或利用其他机制使进程执行到RWX节中的恶意代码。
- 加载额外DLL/建立C2: 注入的shellcode随后加载额外的恶意DLL(例如
MyLibrary.dll
),并建立与攻击者C2服务器的反向shell连接。
伪代码示例 (远程注入核心逻辑):
// 1. 启动目标进程 (ssh.exe) 作为子进程,确保加载了 msys-2.0.dll
CreateProcessW(L"C:\\Path\\To\\ssh.exe", NULL,..., &pi);
// 2. 获取 msys-2.0.dll 在目标进程中的基地址
// (需要枚举目标进程模块或通过其他方式获取)
HMODULE hModMsys2 = GetRemoteModuleBase(pi.hProcess, L"msys-2.0.dll");
// 3. 解析 msys-2.0.dll 的PE结构,找到RWX节的偏移和大小
// (此步骤在注入器进程中完成,或通过读取目标进程内存)
DWORD rwxOffset = GetRWXSectionOffset(hModMsys2);
SIZE_T rwxSize = GetRWXSectionSize(hModMsys2);
// 4. 将 shellcode 写入目标进程的RWX节
// 注意:这里不是 VirtualAllocEx/WriteProcessMemory,而是直接写入已存在的RWX区域
// 实际实现可能需要 OpenProcess(PROCESS_VM_WRITE) 和 WriteProcessMemory,
// 但关键是写入的区域是“天然”的RWX,而非新分配的。
// 攻击者可能通过其他内存写入原语(如 NtWriteVirtualMemory)来避免被监控。
WriteProcessMemory(pi.hProcess, (LPVOID)((BYTE*)hModMsys2 + rwxOffset), shellcode, shellcodeSize, NULL);
// 5. 触发 shellcode 执行 (例如,通过修改线程上下文或APC)
// 这一步具体实现可能复杂,旨在让目标进程的正常执行流触及注入的代码
//... (例如,通过直接syscall方式修改RIP,或等待进程自身调用到该区域)
// 6. 绕过 NTDLL 钩子 (在 shellcode 内部实现)
// 伪代码表示:
// PVOID ntdllBase = GetCleanNtdllBase(); // 获取干净NTDLL副本
// PVOID syscallAddr = GetSyscallAddress(ntdllBase, "NtAllocateVirtualMemory"); // 从干净NTDLL获取真实地址
// ExecuteSyscall(syscallAddr,...); // 直接执行系统调用
攻击者对“正常”行为的伪装是Mockingjay成功的关键。该技术声称无需分配内存、设置权限或创建线程,这直接挑战了EDR对这些“可疑”API调用的监控。通过利用合法DLL中已存在的RWX节,恶意代码被植入到“看似正常”的内存区域。这种“正常”的伪装使得EDR难以区分合法操作和恶意注入。攻击者正在利用操作系统设计中的“灰色地带”,即为了某些合法目的(如JIT编译、自修改代码)而存在的RWX内存区。这表明攻击者对Windows内存管理模型有深入理解。EDR对显式内存操作的强监控,直接促使攻击者寻找无需这些操作的注入方式。这种攻击行为的演变,反过来要求EDR需要更复杂的内存完整性检查和行为模式分析。这意味着EDR不仅要监控API调用,还要对进程的内存布局、内存权限变化以及代码执行的来源进行持续性的、细粒度的检查。
表1:Mockingjay 与传统注入方法对比
特征/技术维度 | 传统注入技术 (e.g., CreateRemoteThread) | Process Mockingjay |
---|---|---|
API 使用 | 依赖 VirtualAllocEx , WriteProcessMemory , CreateRemoteThread 等常见API | 避免显式内存分配/权限设置API,利用直接系统调用绕过 ntdll 钩子 |
内存操作 | 显式分配新内存并写入恶意代码 | 利用合法DLL中已存在的RWX节,直接复制恶意代码 |
线程创建 | 通常创建新的远程线程或劫持现有线程 | 避免创建新线程,通过劫持现有执行流或在正常流程中触发,利用现有进程的线程上下文 |
EDR 检测焦点 | API 钩子,可疑API调用序列,新创建的线程 | 难以通过传统API钩子检测,需依赖行为分析、内存完整性检查、对RWX节的异常写入和直接系统调用的识别 |
磁盘痕迹 | 通常无磁盘痕迹(反射DLL除外) | 无需在磁盘上留下恶意DLL,代码直接注入到内存中 |
隐蔽性 | 相对较高,但易被API钩子检测 | 极高,通过滥用信任DLL的RWX节和直接系统调用,深度规避API监控和进程行为关联,混淆合法与恶意行为 |
III. Dirty-Vanity:滥用 Windows Fork 机制
Dirty-Vanity 是一种利用 Windows 操作系统中鲜为人知的 Fork(派生)机制来实现代码注入和EDR规避的新型技术。它通过打破传统的“分配-写入-执行”(Allocate-Write-Execute, AWE)检测链,对现有安全方案提出了挑战。
Windows Fork 机制背景
虽然 Windows 操作系统不像 Unix/Linux 那样原生且广泛地使用 fork
和 exec
系统调用来创建进程(其中 fork
复制父进程的地址空间,exec
加载新程序),但其内部确实存在类似的进程复制能力。
Unix fork 与 Windows 进程反射/快照的关联
Unix 的 fork
机制以“写时复制”(Copy-on-Write)的方式创建子进程,使其成为父进程的几乎精确副本。在 Windows 中,虽然没有直接对应的 fork
函数,但其内部机制中存在类似的功能。例如,Windows 诊断基础设施(WDI)利用“进程反射”(Process Reflection)机制来分析进程的克隆副本。此外,“进程快照”(Process Snapshotting)功能(通过 PssCaptureSnapshot
函数实现)也能够高效地捕获进程的虚拟地址内容,这部分能力利用了 Windows 内部的 POSIX fork
克隆能力。
Windows 内部 Fork 相关 API 概述
Dirty-Vanity 滥用的核心在于以下 Windows 内部 API:
RtlCreateProcessReflection
: 这是一个未公开的API,用于创建父进程的克隆副本,并允许在克隆进程中执行指定代码。该API在远程进程 Fork 和克隆分析中发挥作用。需要注意的是,其StartRoutine
参数(指向要执行的 shellcode)必须位于Ntdll.dll
中,这暗示了对 shellcode 编写的特定要求。NtCreateProcess[Ex]
: 这些是内核级别的 API,允许创建新进程并指定其父进程。虽然NtCreateProcessEx
可以用于 Fork,但它不负责创建线程,这意味着攻击者需要额外的执行原语来启动 shellcode。此API接受内存投影对象(即映像节)而非文件作为输入。RtlCloneUserProcess
: 这是用于自 Fork 的主要 API。它在内部调用RtlpCreateUserProcess
,而后者又封装了NtCreateUserProcess
。NtCreateUserProcess
: 这是一个低级别的进程创建API。值得注意的是,尝试使用此API通过将PS_ATTRIBUTE_PARENT_PROCESS
属性设置为远程进程句柄来执行远程克隆会失败,并返回STATUS_INVALID_PARAMETER
错误。这表明NtCreateUserProcess
主要设计用于自 Fork 或创建全新的进程,而非任意的远程克隆。
注入方法与运行时步骤
Dirty-Vanity 的注入方法巧妙地将代码写入和执行过程分离,利用 Windows 的 Fork 机制在新的进程上下文中执行恶意代码。
初始写入阶段:将 Shellcode 写入目标进程
在 Dirty-Vanity 攻击中,第一步是“初始写入阶段”(Initial Write Step)。在此阶段,攻击者将恶意 shellcode 分配并写入到目标进程的内存空间中。这一步可以使用任何常见的写入原语,例如 NtCreateSection
和 NtMapViewOfSection
、VirtualAllocEx
和 WriteProcessMemory
,甚至是通过 NtSetContextThread
实现的“幽灵写入”(Ghost Writing)等技术。重要的是,这一写入操作发生在原始的目标进程中。
Fork & 执行阶段:远程 Fork 目标进程并重定向执行流
第二步是“Fork & 执行阶段”(Fork & Execute Step),这是 Dirty-Vanity 的核心所在。在此阶段,攻击者对已写入 shellcode 的目标进程执行远程 Fork 操作,从而创建一个新的进程(克隆)。这个新创建的克隆进程继承了父进程的内存状态,包括之前写入的恶意 shellcode。随后,攻击者将这个新 Fork 进程的起始地址重定向到 shellcode 所在的位置。这意味着 shellcode 会在新的、克隆的进程中被执行,而该进程的内存布局与原始目标进程几乎一致。例如,攻击者可以 Fork explorer.exe
进程,并在其克隆实例中执行 shellcode,进而从该克隆的 explorer.exe
实例中启动 cmd.exe
。
表2:Dirty-Vanity 执行流程与规避点
阶段 | 动作 | 关键 API/机制 | EDR 检测挑战 |
---|---|---|---|
初始写入阶段 | 将恶意 Shellcode 分配并写入到目标进程内存 | VirtualAllocEx , WriteProcessMemory , NtCreateSection , NtMapViewOfSection , NtSetContextThread (Ghost Writing) | EDR 可能检测到内存分配和写入,但这些操作发生在父进程中,尚未触发执行 |
Fork & 执行阶段 | 对目标进程执行远程 Fork,创建新进程(克隆);设置克隆进程的起始地址指向 Shellcode | RtlCreateProcessReflection , NtCreateProcess[Ex] , RtlCloneUserProcess | 打破 AWE 链:写入发生在父进程,执行发生在子进程,EDR难以关联;进程创建回调可能不记录 Fork 进程的初始线程 |
Shellcode 执行 | 克隆进程执行继承的 Shellcode | Shellcode 内部的 ntdll API 调用 (e.g., NtCreateUserProcess ) | EDR 可能监控 ntdll API,但由于执行发生在新的进程上下文中,且可能采用直接系统调用绕过钩子,增加了检测难度 |
此表详细分解了Dirty-Vanity的复杂多阶段注入过程,并明确指出了每个阶段如何规避EDR检测,特别是其如何通过分离写入和执行来打破传统的AWE检测链。这有助于防御者理解其隐蔽性来源,并为构建更具针对性的检测策略提供依据。
EDR 规避策略
Dirty-Vanity 的主要规避策略在于其独特的进程 Fork 机制,这种机制能够有效打破 EDR 传统的检测逻辑。
如何通过分离写入与执行打破 EDR 检测链
传统的 EDR 解决方案在检测进程注入时,通常会监控并关联“分配-写入-执行”(AWE)这一序列操作,即在同一个目标进程中观察到内存分配、恶意代码写入以及随后的执行行为。如果这三个步骤在同一进程ID内发生,EDR便会将其标记为可疑行为。
Dirty-Vanity 的核心规避机制在于它将“写入”阶段(发生在父进程中)与“执行”阶段(发生在Fork 出来的子进程中)分离。当攻击者在父进程中写入 shellcode 后,通过 Fork 操作创建的子进程会继承父进程的内存状态,包括已写入的 shellcode。随后,shellcode 在这个新的、克隆的子进程中执行。从 EDR 的角度来看,初始的写入操作发生在父进程的 PID 上,而恶意代码的执行则发生在新的子进程的 PID 上。这种跨进程 ID 的行为分离在时间上和逻辑上都造成了断裂,使得 EDR 难以将写入和执行关联起来,从而绕过那些依赖于单一进程内 AWE 链的检测机制。
跨进程 ID 行为的隐蔽性
这种跨进程 ID 的行为分离,迫使 EDR 必须考虑更复杂的跨进程血缘关系和内存状态继承。这比传统的单一进程监控要复杂得多,并且意味着 EDR 需要跟踪内存区域及其在进程 Fork 过程中的内容变化。此外,传统的进程创建通知回调函数可能不会以传统方式记录 Fork 出来的进程的初始线程,因为其并非通过常规的线程创建API启动。
尽管 RtlCreateProcessReflection
等 API 在执行时可能会触发一些检测向量(例如,打开父进程句柄会触发 Ob-callback 并可能显示可疑的访问掩码;内存映射会触发 EtwTi 事件,尽管初始时可能不可执行;跨进程线程创建会触发 Ps-callback),但 Dirty-Vanity 的主要规避优势仍然在于其打破了 AWE 链。
Dirty Vanity 对 Windows 内部未公开 Fork 机制的利用,揭示了安全产品长期以来的一个盲点。EDR通常优先监控那些广为人知的、有文档记录的 Win32 API。然而,攻击者通过深入Windows内核的进程创建原语,得以在常规监控表面之下进行操作。这表明攻击者与防御者之间的对抗持续升级,攻击者不断发现并利用那些安全研究人员尚未完全理解或监控的操作系统内部功能。这要求EDR厂商投入大量资源进行逆向工程,以全面理解Windows内部API,特别是那些与进程和内存管理相关的API。同时也凸显了EDR在内核模式下获得可见性的重要性,因为这些API更接近内核层。
Dirty Vanity 的核心规避在于其将“写入”操作(在父进程中执行)与“执行”操作(在 Fork 出来的子进程中执行)分离,从而打破了传统的 AWE 检测链。许多 EDR 依赖于观察单个进程 ID 内完整的 AWE 序列来标记注入行为。通过在父进程中执行写入,并在新的克隆子进程中执行恶意代码,Dirty Vanity 在时间上和逻辑上都制造了断裂,从而绕过那些依赖于特定模式的 EDR。这迫使 EDR 必须考虑跨进程的血缘关系和内存状态继承,这比单一进程监控要复杂得多。这也意味着 EDR 需要跟踪内存区域及其在进程 Fork 过程中的内容。
技术细节与 DirtyVanity.cpp 分析
Dirty-Vanity 的技术实现细节进一步揭示了其复杂性和对 Windows 内部机制的深刻理解。
ntdll API-based Shellcode 的必要性与定制
在 Dirty-Vanity 的概念验证(PoC)中,DirtyVanity.cpp
文件是用于存放位置无关(position-independent)shellcode 的核心位置。该 shellcode 必须基于 ntdll
API 进行编写。
定制 shellcode 的过程通常包括:
- 修改
shellcode_template
函数(通常基于windows_x64_shellcode_template
等项目)以实现所需功能。 - 编译
shellcode_template
项目。 - 使用 PE 解析工具(如 IDA Pro)提取编译后的
shellcode_template
函数的字节码,这些字节码即为位置无关的 shellcode。 - 将这些提取出的 shellcode 字节码手动放置到
DirtyVanity.cpp
文件中。
USER32\!gpsi 问题及其解决方案
在 Dirty-Vanity 的早期尝试中,研究人员发现了一个关键问题:当尝试在克隆进程中执行依赖于 USER32.dll
的 shellcode(例如,调用 MessageBoxA
)时,会因为 USER32!gpsi
缺失而导致访问冲突。深入分析发现,USER32!gpsi
指向 win32k!tagSHAREDINFO
,这是一个位于内核对象中的共享只读节,在 user32.dll
初始化时被映射到每个进程。然而,这个共享节在映射时使用了 InheritDisposition
参数的 ViewUnmap (2)
标志。这意味着该视图被明确设置为不映射到子进程中。因此,Fork 过程不会复制这些带有 ViewUnmap
标志的共享节,导致依赖这些映射的 shellcode 无法正常工作。
为了解决这个问题,攻击者将方法转向了完全基于 ntdll
API 的 shellcode。ntdll.dll
始终正确地映射在任何进程中,并且其导出的函数可以直接用于执行低级系统调用,而无需依赖那些可能因为 Fork 机制而缺失的高级 DLL 依赖。
基于 ntdll
的 shellcode 通常会执行以下步骤:
- 设置进程环境块(PEB)中的
Ldr -> ShutdownInProgress = 0
。 - 通过加载器数据表(LDR)检测
ntdll
API 的地址。 - 使用
RtlInitUnicodeString
、RtlAllocateHeap
和RtlCreateProcessParametersEx
创建必要的参数。 - 调用
NtCreateUserProcess
来启动新的进程(例如,启动cmd.exe
并显示消息)。 - 通过
NtSuspendThread
暂停线程。
USER32!gpsi
问题揭示了 Windows Fork 机制的一个关键限制,以及高级注入技术面临的常见挑战。高层 API(如 user32.dll
中的函数)通常依赖于共享内存节,而这些节被设计为不由 Fork 进程继承。这迫使攻击者编写高度自包含、低级别的 shellcode,仅使用 ntdll
API,因为 ntdll.dll
始终存在并正确映射在任何进程中。这增加了有效载荷开发的复杂性,但也使其在不同进程内存布局下更具鲁棒性。它还强调了即使是“完美”的操作系统功能也存在攻击者必须考虑和规避的细微限制。
防御者可以利用这一点。如果 EDR 检测到进程 Fork,并且 Fork 出来的进程立即尝试使用高层 API(例如 user32.dll
函数)而没有进行适当的初始化或重新映射,这可能是一个强烈的恶意活动信号,因为合法的 Fork 进程可能会避免此类调用或以不同方式处理它们。这也强调了监控 ntdll
API 调用的重要性,即使使用了直接系统调用,因为其序列或上下文可能异常。
关键 API 调用及权限要求
为了成功执行 Dirty-Vanity 注入,攻击者需要目标进程句柄具备特定的访问权限:
RtlCreateProcessReflection
变体: 需要PROCESS_VM_OPERATION
|PROCESS_CREATE_THREAD
|PROCESS_DUP_HANDLE
权限。NtCreateProcess[Ex]
变体: 需要PROCESS_CREATE_PROCESS
权限。
此外,初始写入阶段也需要目标进程的内存分配和写入权限。
表3:Windows Forking 关键 API 及其在 Dirty-Vanity 中的作用
API 名称 | 描述 | 在 Dirty-Vanity 中的作用 | 关键限制/注意事项 |
---|---|---|---|
RtlCreateProcessReflection | 未公开的内部 API,用于创建进程的反射(克隆)副本以进行分析。 | 用于远程 Fork 目标进程,并将克隆进程的执行流重定向到注入的 Shellcode。 | StartRoutine 必须在 ntdll.dll 中;可能触发 Ob-callback, EtwTi, Ps-callback 等检测事件。 |
NtCreateProcess[Ex] | 内核级别 API,用于创建新进程,可指定父进程。 | 可用于 Fork 目标进程,但不负责创建线程;需要额外的执行原语来启动 Shellcode。接受内存映像节作为输入。 | |
RtlCloneUserProcess | 用于自 Fork 的主要内部 API,创建当前进程的克隆。 | 用于实现自注入场景,或作为 RtlCreateProcessReflection 内部调用的基础。 | 内部调用 NtCreateUserProcess 。 |
NtCreateUserProcess | 低级别进程创建 API,封装了创建用户模式进程的核心逻辑。 | RtlCloneUserProcess 内部调用;无法直接用于远程克隆(设置远程父进程句柄会失败)。主要用于自 Fork 或创建全新进程,而非任意远程克隆。 | 无法直接用于远程克隆。 |
此表提供了 Dirty-Vanity 所依赖的 Windows 内部 Forking API 的详细参考,解释了它们的功能、在注入链中的作用,以及攻击者必须应对的限制。这对于理解该技术的深层机制以及防御者如何针对这些低级原语进行监控至关重要。
IV. 检测与防御策略
Process Mockingjay 和 Dirty-Vanity 等新型注入技术对传统的EDR检测机制提出了严峻挑战。为了有效应对这些威胁,防御策略必须从API钩子和签名检测向更深层次的行为分析和内存完整性检查发展。
针对 Mockingjay 的行为分析与内存完整性检查
要检测 Process Mockingjay,EDR解决方案需要超越对特定DLL或系统调用的静态监控。核心防御策略应包括:
- 行为分析与异常检测: 部署基于行为分析、异常检测和机器学习的技术,以增强识别进程注入技术和检测受信任进程内存空间内恶意活动的能力。这包括建立正常进程的基线行为模式,并识别任何偏离基线的内存访问或代码执行模式。
- 扩大监控范围: 拓宽监控范围,将受信任进程的内部活动纳入考量。这意味着EDR不仅要关注可疑进程,还要对合法进程的内存布局、内存权限变化以及代码执行的来源进行持续性的、细粒度的检查。
- 内存完整性检查: 实施持续的内存完整性检查,以识别对RWX节的未经授权的写入或修改。即使没有显式的内存分配或权限设置API调用,对现有RWX区域的异常写入也应被视为强烈的恶意信号。
针对 Dirty-Vanity 的 Fork 机制监控与异常检测
Dirty-Vanity 利用 Windows 的 Fork 机制打破了传统的 AWE 检测链,因此防御需要聚焦于对 Fork 行为本身的监控:
- 监控所有 Fork 原语: EDR 必须监控所有相关的 Fork 原语,包括
RtlCloneUserProcess
、NtCreateProcess[Ex]
和RtlCreateProcessReflection
。这些 API 的调用本身就应引起关注,特别是当它们发生在非典型场景时。 - 跨进程关联与血缘追踪: 追踪 Fork 出来的子进程,并将其与父进程的内存状态和写入区域进行关联。这要求 EDR 具备复杂的关联引擎和上下文分析能力,能够识别写入操作(在父进程中)与执行操作(在子进程中)之间的逻辑联系。
- 异常 Fork 行为检测: 检测异常的进程创建行为(例如,通过 Ps-callback)和远程进程/线程句柄的复制(通过 Ob-callbacks)。
- Fork 后活动分析: 对 Fork 出来的进程进行行为分析,特别是关注其是否进行网络连接、加载异常 DLL 或派生子进程。在合法的 Fork 场景中,这些活动通常不常见,因此可以作为强烈的恶意信号。
1 条评论
orz