文章总结: 本文深入解析间接系统调用技术,用于绕过EDR对ntdll的inlinehook,通过定位ntdll内syscallgadget执行系统调用,使返回地址合法化,规避调用栈检测。同时探讨C2定制、SleepMask及完整用户态免杀链,提供实战级规避方案,对红队与安全研究有较高参考价值。 综合评分: 88 文章分类: 免杀,红队,安全开发,安全工具
间接系统调用与C2定制
原创
pandazhengzheng pandazhengzheng
安全分析与研究
2026年8月30日 22:00 广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
目录
- 问题背景:ntdll 的 inline hook
- 系统调用的底层机制
- Direct Syscalls(直接系统调用)
- Indirect Syscalls(间接系统调用)
- SSN 解析技术族
- Indirect Syscalls 的实现详解
- Indirect Syscalls 的检测与规避
- C2 通信的检测面
- Havoc 框架架构
- C2 定制关键技术
- Sleep Mask 与内存规避
- 完整用户态免杀链
- 小结
1. 问题背景:ntdll 的 inline hook
1.1 hook 的位置
EDR 在 ntdll.dll 的每个关键 Nt*/Zw* 函数序言安装 inline hook,将控制权转到 EDR 的处理例程。典型 hook 形式(x64):
原始 NtXxx 序言:
mov r10, rcx
mov eax, <SSN>
syscall
ret
被 hook 后:
jmp <edr_handler> ; 或 mov rax, addr; jmp rax
<原始字节备份在 trampoline>
1.2 为什么前几节未解决
- 第二节(APC/Fiber)解决”执行载体”,但 shellcode 内部仍调用
ntdll; - 第三节(Module Stomping/Call Stack Spoofing)解决”内存与栈特征”,但 shellcode 调用
ntdll时控制权仍经过被 hook 的序言。
只要 shellcode 调用 ntdll!NtXxx,inline hook 就触发。绕过 hook 的唯一方式是不经过 ntdll 的 stub 发起系统调用——这就是 syscall 类技术的核心。
1.3 系统调用的本质
ntdll!NtXxx 只是系统调用的用户态包装:设置 SSN 到 EAX、设置 r10、执行 syscall 指令进入内核。**syscall 指令本身才是系统调用的入口**,ntdll 的 stub 只是方便调用。若攻击者自己 emit mov r10, rcx; mov eax, SSN; syscall; ret,即可不经过 ntdll 发起系统调用。
2. 系统调用的底层机制
2.1 syscall 指令的语义
x64 syscall 指令完成:
- 保存用户态 RIP 到 RCX(
RCX = next instruction after syscall); - 保存用户态 RFLAGS 到 R11;
- 清除 RFLAGS 中的 IF(关中断);
- 加载内核态 CS/SS(
MSR.LSTAR→ RIP,进入内核 syscall 入口); - 内核根据 EAX(SSN)查
SSDT/SSDTShadow派发到对应内核例程。
2.2 SSN(System Service Number)
每个系统服务在 SSDT 中有一个序号(SSN)。ntdll!NtXxx 的 stub 中 mov eax, <SSN> 即设置该序号。SSN 因 Windows 版本与补丁而异,不能硬编码。
2.3 ntdll stub 的标准形式
x64 下,几乎所有 NtXxx stub 形式统一:
mov r10, rcx ; Windows 内核 syscall 约定:参数1通过 r10 传递(因为 syscall 会破坏 rcx)
mov eax, <SSN> ; 系统服务号
syscall ; 进入内核
ret ; 返回(部分函数后有 ret 0/ret 4,但 Nt* 通常是 ret)
少数函数(如 NtCreate* 等需保存更多寄存器)可能有额外 prologue,但 syscall 前必有 mov r10, rcx; mov eax, SSN。
3. Direct Syscalls(直接系统调用)
3.1 原理
Direct Syscalls 在 shellcode 内部直接 emit mov r10, rcx; mov eax, SSN; syscall; ret 序列,不经过 ntdll 的 stub,从而不触发其上的 inline hook。
3.2 实现
shellcode 内嵌汇编(或 C 内联汇编):
NTSTATUS MyNtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ...) {
// 设置参数(x64 调用约定:rcx=ProcessHandle, rdx=BaseAddress, ...)
// 然后执行 syscall
__asm__ volatile (
"mov r10, rcx\n"
"mov eax, %0\n" // SSN
"syscall\n"
:
: "i" (SSN_NtAllocateVirtualMemory)
: "rax", "r10", "rcx", "r11", "memory"
);
}
或用动态构造的 shellcode stub:
direct_syscall:
mov r10, rcx
mov eax, [ssn] ; 动态填入 SSN
syscall
ret
3.3 致命缺陷:调用栈暴露
当 syscall 指令执行进入内核后,**syscall 的返回地址(即 syscall 指令的下一条指令地址)落在 shellcode 所在的私有内存**。EDR 在内核态(ETW-TI、回调)或 hook 处理时回溯调用栈,会发现:
syscall返回地址在MEM_PRIVATE(shellcode 内部);- 合法系统调用的返回地址应在
ntdll的 stub 内(syscall指令的下一条是ret,地址在ntdll)。
这是极强的异常信号:合法进程的系统调用返回地址几乎必然在 ntdll,而 Direct Syscalls 的返回地址在私有内存,一目了然。
3.4 Direct Syscalls 的适用与局限
- 绕过用户态 hook:✓ 完全绕过(不经过 stub);
- 调用栈暴露:✗ 返回地址在私有内存;
- ETW-TI 仍感知:✗ 内核埋点仍记录系统调用(但 ETW-TI 不直接检查返回地址,主要靠后续栈回溯);
- 适用场景:仅当 EDR 不做调用栈检查时有效;现代 EDR 普遍检查,故 Direct Syscalls 已不够。
4. Indirect Syscalls(间接系统调用)
4.1 核心思路
Indirect Syscalls 在 Direct Syscalls 基础上修复”返回地址暴露”问题:让 syscall 指令本身从一个合法的、未被 hook 的 ntdll 区域执行,使得 syscall 的返回地址落在 ntdll 内。
4.2 关键观察
ntdll 中每个 NtXxx stub 末尾都是 syscall; ret。即便其序言被 hook 覆写,stub 末尾的 syscall; ret 通常未被覆写(hook 一般只覆写序言前几字节,跳转到 handler,handler 内部调用 trampoline 执行原始序言 + 原始 syscall)。
因此,ntdll 中存在大量 syscall; ret gadget——可以是任意 NtXxx 的末尾,不限于目标函数。
4.3 实现思路
- 解析 ntdll:找到目标
NtXxx的 SSN; - 寻找一个
syscall; retgadget:在ntdll中扫描任意一个未被 hook 覆盖的syscall指令; - 设置寄存器:
r10 = rcx,eax = 目标 SSN; - 跳转到该 gadget:
jmp <ntdll 中的 syscall; ret>。
此时:
syscall指令在ntdll内执行,返回地址落在ntdll内(gadget 的ret后一条指令地址);- 未经过被 hook 的 stub 入口,inline hook 不触发;
- 系统调用号通过
eax传入,内核正确派发到目标服务。
4.4 与 Direct Syscalls 的对比
| 维度 | Direct Syscalls | Indirect Syscalls |
| — | — | — |
| 绕过用户态 hook | ✓ | ✓ |
| syscall 返回地址 | 私有内存(暴露) | ntdll 内(合法) |
| 调用栈最近一层 | 异常 | 合法 |
| 实现复杂度 | 低 | 中 |
| 依赖 ntdll 完整性 | 否(自己 emit) | 是(需读 ntdll 找 gadget) |
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全分析与研究 pandazhengzheng pandazhengzheng《间接系统调用与C2定制》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论