Windows系统调用免杀的过去和未来
字数 2635 2025-09-23 19:27:46

Windows系统调用免杀技术深度解析

一、系统调用基础概念

1.1 核心组件:ntoskrnl.exe

ntoskrnl.exe是Windows操作系统内核的核心组件,负责:

  • 维护系统服务描述符表(SSDT)
  • 响应系统调用指令(int 2Eh/sysenter/syscall)

1.2 系统调用存根(syscall stub)

系统调用存根是用户空间与内核交互的桥梁,主要功能:

  • 将系统调用号放入特定寄存器(EAX/RAX)
  • 执行触发系统调用的指令(int 0x2E/syscall)
  • 系统调用号(SSN)用于索引SSDT中的函数指针

1.3 _KUSER_SHARED_DATA结构

用户态和内核态共享的数据结构:

  • 用户态地址:0x7ffe0000(只读)
  • 内核态地址:0xffdf0000(可写)
  • 包含SystemCall字段(偏移0x300),存储KiFastSystemCall地址

1.4 MSR寄存器

x86/x64架构中的专用寄存器:

  • sysenter使用:
    • IA32_SYSENTER_CS:内核代码段选择
    • IA32_SYSENTER_EIP:内核入口点
    • IA32_SYSENTER_ESP:内核栈指针
  • syscall使用:
    • IA32_LSTAR:64位内核入口点
    • IA32_STAR:指定内核/用户态CS/SS

二、系统调用流程

2.1 传统中断调用(INT 2E)

  1. CPU执行INT 2E指令触发软中断
  2. 通过IDT找到KiSystemService
  3. 保存完整寄存器形成完整陷阱帧
  4. 定位SSDT表并索引服务函数

2.2 快速系统调用(SYSCALL/SYSENTER)

  1. CPU执行sysenter/syscall指令
  2. 直接跳转到MSR指定地址(KiFastCallEntry)
  3. 只保存关键寄存器形成精简陷阱帧
  4. 执行KiSystemService核心逻辑

2.3 Zw与Nt函数区别

  • 用户态下功能相同
  • 内核态下:
    • Zw*函数:设置Previous Mode为内核模式,绕过参数检查
    • Nt*函数:继承调用者模式,执行严格参数检查

三、系统调用免杀技术演进

3.1 早期技术:地狱之门(HellsGate)

核心思想:动态获取系统调用号

实现步骤

  1. 通过PEB获取ntdll基址
  2. 解析ntdll导出表
  3. 计算函数名哈希匹配目标函数
  4. 扫描函数代码查找系统调用号模式:
    • x64模式:0x4C 0x8B 0xD1 0xB8(MOV R10, RCX; MOV EAX, SSN)
  5. 直接使用syscall指令调用

局限性

  • 被Hook函数无法正确获取SSN
  • syscall指令硬编码易被检测

3.2 改进技术:HalosGate

核心思想:通过相邻函数推算SSN

实现方法

  1. 定位目标函数附近未被Hook的函数
  2. 获取其SSN并加减偏移量
  3. 得到目标函数的SSN

3.3 改进技术:TartarusGate

增强功能

  1. 更精确的Hook检测(检查0xE9跳转指令)
  2. 添加NOP指令混淆syscall特征

3.4 ntdll unhook技术

实现思路

  1. 从磁盘重新加载ntdll.dll
  2. 修复节表、重定位表
  3. 调整内存属性
  4. 获得干净的ntdll副本

局限性:无法绕过ring0的SSDT Hook监控

四、现代系统调用免杀技术

4.1 彩蛋猎人(egg hunters)

核心思想:运行时替换syscall指令

实现方法

  1. 使用DB伪指令定义特殊字节序列(如"r00vr00v")
  2. 程序加载后搜索并替换为syscall指令
  3. 绕过静态检测

优化方向

  • 替换部分DB指令为实际指令
  • 增加彩蛋长度提高精确度

4.2 随机跳转间接系统调用

实现步骤(以SysWhispers3为例):

  1. 枚举ntdll中所有Zw*函数
  2. 构建函数哈希-地址列表
  3. 随机选择干净的syscall指令地址
  4. 构造调用链:
    • 获取随机syscall地址→RAX→R11
    • 获取SSN→EAX
    • JMP R11实现间接调用

优势:回调RIP指向ntdll,绕过来源检测

4.3 VEH间接系统调用

核心技术(HWSyscalls项目):

  1. 硬件断点:在Dr0寄存器设置断点地址
  2. VEH处理:注册异常处理函数构造syscall
  3. 栈空间伪造:利用kernel32/kernelbase的ret gadget
  4. SSN获取:改进版HalosGate算法

调用流程

  1. 调用PrepareSyscall触发硬件断点
  2. VEH处理函数接管执行
  3. 构造mov r10, rcx + mov eax, SSN
  4. 跳转到干净的syscall指令地址

五、系统调用免杀关键问题与解决方案

问题 解决方案
系统调用号获取 HellsGate动态解析、HalosGate相邻函数推算
syscall指令检测 egg hunters运行时替换、间接跳转调用
调用来源验证 随机跳转使RIP指向ntdll、VEH异常处理
参数检查绕过 使用Zw*函数设置Previous Mode为内核模式
ETW检测 禁用ETW或混淆线程堆栈

六、实战建议

  1. 基础掌握:深入理解HellsGate实现原理
  2. 技术组合:结合多种技术(如egg hunters+随机跳转)
  3. 环境适配:根据目标EDR能力选择适当方案
  4. 持续进化:关注新技术如HWSyscalls的硬件断点应用
  5. 隐蔽性优化:添加反调试、堆栈混淆等辅助技术

七、参考资源

  1. HellsGate项目:https://github.com/am0nsec/HellsGate
  2. HalosGate技术解析:https://blog.sektor7.net/
  3. SysWhispers3:https://github.com/klezVirus/SysWhispers3
  4. HWSyscalls项目:https://github.com/Sh0ckFR/HWSyscalls
  5. Windows异常处理机制:https://blog.csdn.net/qq_41988448/article/details/112467210

通过系统性地理解和应用这些技术,可以有效绕过现代AV/EDR对系统调用的监控,实现更高隐蔽性的恶意代码执行。

Windows系统调用免杀技术深度解析 一、系统调用基础概念 1.1 核心组件:ntoskrnl.exe ntoskrnl.exe是Windows操作系统内核的核心组件,负责: 维护系统服务描述符表(SSDT) 响应系统调用指令(int 2Eh/sysenter/syscall) 1.2 系统调用存根(syscall stub) 系统调用存根是用户空间与内核交互的桥梁,主要功能: 将系统调用号放入特定寄存器(EAX/RAX) 执行触发系统调用的指令(int 0x2E/syscall) 系统调用号(SSN)用于索引SSDT中的函数指针 1.3 _ KUSER_ SHARED_ DATA结构 用户态和内核态共享的数据结构: 用户态地址:0x7ffe0000(只读) 内核态地址:0xffdf0000(可写) 包含SystemCall字段(偏移0x300),存储KiFastSystemCall地址 1.4 MSR寄存器 x86/x64架构中的专用寄存器: sysenter使用: IA32_ SYSENTER_ CS:内核代码段选择 IA32_ SYSENTER_ EIP:内核入口点 IA32_ SYSENTER_ ESP:内核栈指针 syscall使用: IA32_ LSTAR:64位内核入口点 IA32_ STAR:指定内核/用户态CS/SS 二、系统调用流程 2.1 传统中断调用(INT 2E) CPU执行INT 2E指令触发软中断 通过IDT找到KiSystemService 保存完整寄存器形成完整陷阱帧 定位SSDT表并索引服务函数 2.2 快速系统调用(SYSCALL/SYSENTER) CPU执行sysenter/syscall指令 直接跳转到MSR指定地址(KiFastCallEntry) 只保存关键寄存器形成精简陷阱帧 执行KiSystemService核心逻辑 2.3 Zw 与Nt 函数区别 用户态下功能相同 内核态下: Zw* 函数:设置Previous Mode为内核模式,绕过参数检查 Nt* 函数:继承调用者模式,执行严格参数检查 三、系统调用免杀技术演进 3.1 早期技术:地狱之门(HellsGate) 核心思想 :动态获取系统调用号 实现步骤 : 通过PEB获取ntdll基址 解析ntdll导出表 计算函数名哈希匹配目标函数 扫描函数代码查找系统调用号模式: x64模式:0x4C 0x8B 0xD1 0xB8(MOV R10, RCX; MOV EAX, SSN) 直接使用syscall指令调用 局限性 : 被Hook函数无法正确获取SSN syscall指令硬编码易被检测 3.2 改进技术:HalosGate 核心思想 :通过相邻函数推算SSN 实现方法 : 定位目标函数附近未被Hook的函数 获取其SSN并加减偏移量 得到目标函数的SSN 3.3 改进技术:TartarusGate 增强功能 : 更精确的Hook检测(检查0xE9跳转指令) 添加NOP指令混淆syscall特征 3.4 ntdll unhook技术 实现思路 : 从磁盘重新加载ntdll.dll 修复节表、重定位表 调整内存属性 获得干净的ntdll副本 局限性 :无法绕过ring0的SSDT Hook监控 四、现代系统调用免杀技术 4.1 彩蛋猎人(egg hunters) 核心思想 :运行时替换syscall指令 实现方法 : 使用DB伪指令定义特殊字节序列(如"r00vr00v") 程序加载后搜索并替换为syscall指令 绕过静态检测 优化方向 : 替换部分DB指令为实际指令 增加彩蛋长度提高精确度 4.2 随机跳转间接系统调用 实现步骤 (以SysWhispers3为例): 枚举ntdll中所有Zw* 函数 构建函数哈希-地址列表 随机选择干净的syscall指令地址 构造调用链: 获取随机syscall地址→RAX→R11 获取SSN→EAX JMP R11实现间接调用 优势 :回调RIP指向ntdll,绕过来源检测 4.3 VEH间接系统调用 核心技术 (HWSyscalls项目): 硬件断点 :在Dr0寄存器设置断点地址 VEH处理 :注册异常处理函数构造syscall 栈空间伪造 :利用kernel32/kernelbase的ret gadget SSN获取 :改进版HalosGate算法 调用流程 : 调用PrepareSyscall触发硬件断点 VEH处理函数接管执行 构造mov r10, rcx + mov eax, SSN 跳转到干净的syscall指令地址 五、系统调用免杀关键问题与解决方案 | 问题 | 解决方案 | |------|----------| | 系统调用号获取 | HellsGate动态解析、HalosGate相邻函数推算 | | syscall指令检测 | egg hunters运行时替换、间接跳转调用 | | 调用来源验证 | 随机跳转使RIP指向ntdll、VEH异常处理 | | 参数检查绕过 | 使用Zw* 函数设置Previous Mode为内核模式 | | ETW检测 | 禁用ETW或混淆线程堆栈 | 六、实战建议 基础掌握 :深入理解HellsGate实现原理 技术组合 :结合多种技术(如egg hunters+随机跳转) 环境适配 :根据目标EDR能力选择适当方案 持续进化 :关注新技术如HWSyscalls的硬件断点应用 隐蔽性优化 :添加反调试、堆栈混淆等辅助技术 七、参考资源 HellsGate项目:https://github.com/am0nsec/HellsGate HalosGate技术解析:https://blog.sektor7.net/ SysWhispers3:https://github.com/klezVirus/SysWhispers3 HWSyscalls项目:https://github.com/Sh0ckFR/HWSyscalls Windows异常处理机制:https://blog.csdn.net/qq_ 41988448/article/details/112467210 通过系统性地理解和应用这些技术,可以有效绕过现代AV/EDR对系统调用的监控,实现更高隐蔽性的恶意代码执行。