0%
毅种循环

模块 66 - Syscalls - 地狱之门 (Hell's Gate)

恶意软件开发课程 - Syscalls - 地狱之门 (Hell's Gate)


模块 66 - Syscalls - 地狱之门 (Hell’s Gate)#

Syscalls - 地狱之门 (Hell’s Gate)#

简介#

在之前的模块中,我们学习了使用直接系统调用(Direct Syscalls)来绕过用户态挂钩(Userland Hooks)。地狱之门 (Hell’s Gate) 是实现直接系统调用的另一种经典技术。与 SysWhispers(依赖预生成表或地址排序)不同,地狱之门通过直接解析运行中的 ntdll.dll 内存,动态地挖掘出每个系统调用的 SSN (系统服务号)

地狱之门的原始论文可以参考 这里

地狱之门的工作原理#

在 SysWhispers 中,SSN 要么是硬编码的,要么是通过对所有系统调用的地址进行排序后计算出的索引。而地狱之门采用了一种更具“侵略性”的方法:它直接定位到内存中某个函数的代码位置,寻找该函数正常汇编指令中的 SSN 字节。

技术详解#

为了便于理解,我们将地狱之门的实现拆解为以下几个部分。

1. 定义数据结构#

地狱之门使用 VX_TABLE_ENTRY 结构来代表一个系统调用。

typedef struct _VX_TABLE_ENTRY {
	PVOID   pAddress;             // 系统调用函数的内存地址
	DWORD64 dwHash;               // 函数名的 Djb2 哈希值
	WORD    wSystemCall;          // 动态解析出的 SSN (系统服务号)
} VX_TABLE_ENTRY, * PVX_TABLE_ENTRY;
c

2. 地狱之门的精髓:动态搜寻 SSN#

这是该技术的核心。代码会扫描 ntdll.dll 的导出表,找到目标函数后,进入 GetVxTableEntry 函数进行“深度挖掘”。

挖掘逻辑 (Part 2): 一旦找到了函数地址 pFunctionAddress,地狱之门会进入一个 while 循环,逐字节检查该函数的机器码。它在寻找以下特定字节序列: 0x4c, 0x8b, 0xd1, 0xb8

对应的汇编指令是:

mov r10, rcx
mov eax, <SSN>
asm

💡 知识扩展:绕过 Hook

如果一个函数被 EDR 挂钩了,它的前几个字节通常会被改成 jmp 指令。此时,地狱之门会聪明地向下侦察(通过增加 cw 变量的值),跳过被污染的字节,直到它在由于 EDR 实现不全而留下的“尾巴”中,或者在正常的指令流中找到那些代表 SSN 的特征码。

地狱之门跳过 Hook 示意图
地狱之门跳过 Hook 示意图

3. 边界检查#

为了防止找得太深误入歧途,地狱之门设置了保护:如果在还没找到特征码之前就遇到了 syscall (0x0F, 0x05) 或 ret (0xC3) 指令,说明这个函数的 SSN 无法被正常解析。

4. 计算并保存 SSN#

一旦匹配成功,地狱之门会提取出特征码之后的两个字节,通过位运算合成最终的 SSN。

// 提取第 4 和 第 5 个偏移位置的字节(即 SSN 的高低位)
BYTE high = *((PBYTE)pFunctionAddress + 5 + cw); 
BYTE low = *((PBYTE)pFunctionAddress + 4 + cw);
// 合成 16 位的 SSN
pVxTableEntry->wSystemCall = (high << 8) | low;
c

执行系统调用#

解析出 SSN 后,地狱之门通过两个 ASM 汇编函数来完成调用:

  1. HellsGate:接收 SSN 并存入一个全局变量。
  2. HellDescent:执行真正的内核切换,即 mov r10, rcx; mov eax, SSN; syscall
; hellsgate.asm 示例
HellsGate PROC
    mov wSystemCall, ecx ; 将传入的 SSN 存入全局变量
    ret
HellsGate ENDP

HellDescent PROC
    mov r10, rcx
    mov eax, wSystemCall ; 从全局变量读取 SSN
    syscall              ; 突进执行!
    ret
HellDescent ENDP
asm

🎯 总结#

在本模块中,我们学习了:

  1. 动态内存挖掘:理解了如何通过扫描汇编机器码特征来动态获取 SSN。
  2. 鲁棒性设计:地狱之门通过循环扫描,具备了跳过简单 EDR 挂钩并寻找原始指令的能力。
  3. 地狱之门汇编:掌握了如何配合 C 语言将解析出的 SSN 传递给底层汇编进行执行。

📚 下一步学习

地狱之门虽然强大,但如果 EDR 彻底覆盖了函数头,它也会失效。下一个模块我们将探讨 Syscalls - Reimplementing Classic Injection,看看如何把这些理论应用到实际的注入实战中!