本文为 Maldev Academy 中的 Module 65 ~ Module 69 小节的笔记,主要讲解实现 Syscall 的两大工具 SysWhispers 与 Hell’s Gate。以及使用这两个工具将之前的 Classic Injection、Mapping Injection、APC Injection 项目替换为 Syscall 版本。(完整学习内容请自行前往跳转链接查看)
作者原文章中已经对工具的使用进行了很详细的讲解,只需要参考着学习完成即可。本文主要总结记录下这几个不同版本工具的工作原理和区别。
1、SysWhispers(第一代)
项目地址:https://github.com/jthuraisamy/SysWhispers
(1)核心原理
静态查表法。它使用预先搜集好的不同 Windows 版本的系统调用表,生成包含大量 switch-case 或 if-else 的汇编代码文件。
(2)优点
即使 ntdll.dll 被 Hook,也能通过硬编码的表获取正确的 SSN。
(3)缺点
- 生成的二进制文件体积庞大。
- 必须在编译前确定支持的 Windows 版本。
- 包含明显的系统版本判断特征,容易被 EDR 的静态扫描识别。
2、SysWhispers2(第二代)
项目地址:https://github.com/jthuraisamy/SysWhispers2
(1)核心原理
地址排序推导法。在运行时,它获取 ntdll.dll 中所有以 Zw 开头的函数地址并进行升序排列。由于 SSN 的顺序与地址顺序一致,排序后的索引即为 SSN。
(2)优点
- 全版本通用:不再需要硬编码 SSN 表,支持所有 Windows 版本。
- 更隐蔽:避开了硬编码数据库带来的体积问题。
(3)缺点
仍属于 直接系统调用 (Direct Syscalls)。syscall 指令直接在恶意程序的内存空间执行,会导致非法的调用堆栈(Call Stack),易被高级 EDR 发现。
3、SysWhispers3(第三代)
项目地址:https://github.com/klezVirus/SysWhispers3
(1)核心原理
引入了 Indirect Syscalls(间接调用)和多种混淆技术。。它不再在自己的代码中执行 syscall 指令,而是在 ntdll.dll 中寻找一个合法的 syscall; ret 指令序列,然后通过跳转(JMP)到该地址执行。
(2)关键改进
- 堆栈合法化:不再在自己的代码里写
syscall指令,而是在ntdll.dll内部找一个现成的syscall; ret指令位置,然后通过跳转(JMP)过去执行。这样 EDR 看到的调用来源就是合法的ntdll.dll。系统调用看起来像是从ntdll.dll内部发出的,拥有合法的调用堆栈,从而规避 EDR 的堆栈回溯检查。 - EGG Hunting(特征混淆):允许用户在代码中加入伪装特征,防止静态签名检测。
- 支持多种跳转模式:可以配置为直接调用、间接调用或特定版本的规避。
4、Hell’s Gate
项目地址:https://github.com/am0nsec/HellsGate
(1)核心原理
动态字节遍历。它通过在运行内存中解析 ntdll.dll 的导出表,定位到目标函数的代码段,并直接搜索系统调用的特征码(如字节码形式的mov eax, SSN),从而直接从内存中提取出系统调用号(SSN)。
主要流程:
- 特征码匹配:首先在目标函数(如
NtWriteVirtualMemory)的内存起始位置搜索特定的操作码(Opcode),通常是字节码形式的汇编指令mov r10, rcx和mov eax, SSN。 - 越过 Hook 遍历:如果发现函数开头已被 EDR 修改(即 Opcode 不匹配),则进行动态偏移计算。
- 动态偏移计算:它会以当前函数地址为基准,向上或向下按字节遍历(
cw变量自增),尝试在邻近的函数空间内寻找未被 Hook 的干净指令序列;一旦在邻近位置找到 SSN,它会根据函数之间的固定索引偏移量,回推导出目标函数的真实 SSN。
(2)优点
完全不依赖静态硬编码的数据库,具有极强的环境自适应性。
(3)缺点
- 采用直接系统调用(Direct Syscall):
syscall指令仍在恶意模块中执行,易被 EDR 通过检查返回地址发现调用栈异常。 - 搜索逻辑仍可被干扰:如果 EDR 对整个
ntdll导出表区域进行了大面积修改或指令混淆,逐字节遍历(cw递增)可能找不到任何干净的特征码,导致失效。 - 内存扫描特征:在运行时频繁扫描
ntdll的行为本身具有一定的行为特征,可能触发敏感内存访问监控。
5、技术对比
| 技术名称 | SSN 获取机制 | 应对 Hook 的策略 | 调用执行方式 | 优缺点 |
|---|---|---|---|---|
| SysWhispers | 静态硬编码 | 无(依赖预存的各版本数据库) | Direct Syscall (直接) | 简单但体积大,易被静态查杀 |
| SysWhispers2 | 运行时地址排序 | 忽略 Hook:仅提取导出表地址排序,不读取函数体指令 | Direct Syscall (直接) | 容易被堆栈回溯检测(Call Stack) |
| SysWhispers3 | 运行时地址排序 | 忽略 Hook + 伪装执行:排序获取 SSN,并寻找合法的syscall退出点 |
Indirect Syscall (间接) | 绕过堆栈回溯,支持混淆 |
| Hell’s Gate | 动态字节遍历 | 越过 Hook:通过cw偏移遍历邻近内存寻找干净 Opcode |
Direct Syscall (直接) | 纯动态,不依赖数据库,能处理部分 Hook;容易被堆栈回溯检测(Call Stack) |