免杀基础-SysCall
字数 2313 2025-08-22 12:23:35

Windows系统调用(SysCall)免杀技术详解

1. 系统调用基础概念

1.1 什么是系统调用

系统调用(SysCall)是Windows提供的从用户模式(3环)进入内核模式(0环)进行特权操作的方法。通过sysentersyscall指令进入内核模式,将执行流程交给内核。

1.2 系统调用流程

  1. 用户模式API(如VirtualAlloc)最终调用NTDLL中的对应函数(如ntdll!NtAllocateVirtualMemory)
  2. NTDLL中的函数准备参数并设置系统调用号(SSN)
  3. 通过syscallint 2e指令进入内核模式
  4. 内核根据SSN查找系统服务描述符表(SSDT)并执行对应内核函数

1.3 关键数据结构

  • _KUSER_SHARED_DATA结构:
    • 内核地址:0xffdf0000
    • 用户地址:0x7ffe0000
    • 偏移0x308处的SystemCall成员决定使用int 2e还是syscall

2. 直接与间接系统调用

2.1 直接系统调用

在当前模块中使用syscall指令,示例:

mov r10, rcx
mov eax, SSN ; 系统调用号
syscall
ret

特点:

  • 直接在代码中使用syscall指令
  • 需要硬编码或动态获取SSN
  • 容易被检测

2.2 间接系统调用

通过跳转指令(如jmp)跳转到NTDLL中的syscall指令位置:

jmp [ntdll_syscall_addr]

特点:

  • 从NTDLL发起系统调用,行为更"合法"
  • 需要动态获取NTDLL中的syscall指令地址
  • 更难被检测

3. 系统调用免杀技术实现

3.1 SysWhispers系列

3.1.1 SysWhispers1

  • 硬编码系统调用号
  • 根据Windows版本选择正确的SSN
  • 直接系统调用

3.1.2 SysWhispers2

  • 使用哈希查找系统调用号
  • 解析NTDLL导出表,按地址排序系统调用
  • 随机选择NTDLL中的syscall指令地址(间接调用)

3.1.3 SysWhispers3

提供四种技术:

  1. Embedded: 基于哈希的直接系统调用
  2. Egg Hunter: 动态替换shellcode中的"egg"部分
  3. Jumper: 通过哈希获取调用号和地址后跳转到NTDLL
  4. Jumper Randomized: 随机选择NTDLL中的函数执行系统调用

3.2 Hell's Gate技术

  1. 手动解析NTDLL导出表
  2. 获取关键Windows API
  3. 分配RW内存写入shellcode后改为RX执行
  4. 直接系统调用

关键函数:

  • HellsGate: 获取并保存SSN
  • HellDescent: 触发系统调用

3.3 Tartarus' Gate (Halo's Gate改进)

  • Hell's Gate的升级版
  • 处理被hook的情况:
    • 如果第一条指令是jmp(0xe9),表示被hook
    • 向上或向下查找未被hook的函数
  • 仍然是直接系统调用

3.4 RecycledGate

  • Tartarus' Gate的升级
  • 改为间接系统调用
  • 搜索syscall;ret特征码确保通过NTDLL发起调用

3.5 ParallelSyscalls

利用Windows 10并行DLL加载机制:

  1. 检查关键函数(NtOpenFile等)是否被hook
  2. LdrpThunkSignature比较前16字节检测hook
  3. 使用NtMapViewOfSection映射干净的NTDLL
  4. 从干净的NTDLL提取SSN和地址

3.6 HWSyscalls

使用硬件断点和VEH(向量化异常处理):

  1. 在Kernel32/KernelBase中搜索返回指令特征码
  2. 注册VEH异常处理程序
  3. 在目标函数地址设置硬件断点
  4. 触发断点后检查hook情况
  5. 如果被hook,查找干净函数获取SSN

3.7 FreshyCalls

  1. 定义Syscall类提供调用接口
  2. 解析NTDLL导出表构建stub_mapsyscall_map
  3. 查找syscallsysenter指令地址
  4. 根据情况选择直接或间接系统调用

3.8 PigSyscall

类似FreshyCalls但改进:

  • 使用哈希而非函数名查找
  • 调用时使用加密的masked_syscall_stub
  • 调用CryptPermute进行解密

4. 关键技术与技巧

4.1 SSN获取方法

  1. 硬编码(不推荐,不同Windows版本不同)
  2. 从NTDLL导出表解析
  3. LdrpThunkSignature获取
  4. 特征码匹配(如b8d18b4c)

4.2 反Hook技术

  1. 检查前几条指令是否为jmp
  2. 查找邻近的干净函数
  3. 映射干净的NTDLL副本
  4. 使用硬件断点检测hook

4.3 隐蔽调用技术

  1. 间接系统调用(跳转到NTDLL)
  2. 随机选择NTDLL中的syscall位置
  3. 使用异常处理机制
  4. 加密系统调用stub

5. 参考资源

6. 总结

系统调用免杀技术核心在于:

  1. 正确获取系统调用号
  2. 绕过或检测用户模式hook
  3. 选择隐蔽的系统调用方式(直接/间接)
  4. 保持与合法程序相似的行为特征

随着防御技术发展,更先进的方案如硬件断点、异常处理、内存映射等被引入,使得检测和防御更加困难。理解这些技术的原理和实现对于攻防双方都至关重要。

Windows系统调用(SysCall)免杀技术详解 1. 系统调用基础概念 1.1 什么是系统调用 系统调用(SysCall)是Windows提供的从用户模式(3环)进入内核模式(0环)进行特权操作的方法。通过 sysenter 或 syscall 指令进入内核模式,将执行流程交给内核。 1.2 系统调用流程 用户模式API(如 VirtualAlloc )最终调用NTDLL中的对应函数(如 ntdll!NtAllocateVirtualMemory ) NTDLL中的函数准备参数并设置系统调用号(SSN) 通过 syscall 或 int 2e 指令进入内核模式 内核根据SSN查找系统服务描述符表(SSDT)并执行对应内核函数 1.3 关键数据结构 _KUSER_SHARED_DATA 结构: 内核地址: 0xffdf0000 用户地址: 0x7ffe0000 偏移 0x308 处的 SystemCall 成员决定使用 int 2e 还是 syscall 2. 直接与间接系统调用 2.1 直接系统调用 在当前模块中使用 syscall 指令,示例: 特点: 直接在代码中使用 syscall 指令 需要硬编码或动态获取SSN 容易被检测 2.2 间接系统调用 通过跳转指令(如 jmp )跳转到NTDLL中的 syscall 指令位置: 特点: 从NTDLL发起系统调用,行为更"合法" 需要动态获取NTDLL中的 syscall 指令地址 更难被检测 3. 系统调用免杀技术实现 3.1 SysWhispers系列 3.1.1 SysWhispers1 硬编码系统调用号 根据Windows版本选择正确的SSN 直接系统调用 3.1.2 SysWhispers2 使用哈希查找系统调用号 解析NTDLL导出表,按地址排序系统调用 随机选择NTDLL中的 syscall 指令地址(间接调用) 3.1.3 SysWhispers3 提供四种技术: Embedded : 基于哈希的直接系统调用 Egg Hunter : 动态替换shellcode中的"egg"部分 Jumper : 通过哈希获取调用号和地址后跳转到NTDLL Jumper Randomized : 随机选择NTDLL中的函数执行系统调用 3.2 Hell's Gate技术 手动解析NTDLL导出表 获取关键Windows API 分配RW内存写入shellcode后改为RX执行 直接系统调用 关键函数: HellsGate : 获取并保存SSN HellDescent : 触发系统调用 3.3 Tartarus' Gate (Halo's Gate改进) Hell's Gate的升级版 处理被hook的情况: 如果第一条指令是 jmp(0xe9) ,表示被hook 向上或向下查找未被hook的函数 仍然是直接系统调用 3.4 RecycledGate Tartarus' Gate的升级 改为间接系统调用 搜索 syscall;ret 特征码确保通过NTDLL发起调用 3.5 ParallelSyscalls 利用Windows 10并行DLL加载机制: 检查关键函数( NtOpenFile 等)是否被hook 与 LdrpThunkSignature 比较前16字节检测hook 使用 NtMapViewOfSection 映射干净的NTDLL 从干净的NTDLL提取SSN和地址 3.6 HWSyscalls 使用硬件断点和VEH(向量化异常处理): 在Kernel32/KernelBase中搜索返回指令特征码 注册VEH异常处理程序 在目标函数地址设置硬件断点 触发断点后检查hook情况 如果被hook,查找干净函数获取SSN 3.7 FreshyCalls 定义 Syscall 类提供调用接口 解析NTDLL导出表构建 stub_map 和 syscall_map 查找 syscall 或 sysenter 指令地址 根据情况选择直接或间接系统调用 3.8 PigSyscall 类似FreshyCalls但改进: 使用哈希而非函数名查找 调用时使用加密的masked_ syscall_ stub 调用 CryptPermute 进行解密 4. 关键技术与技巧 4.1 SSN获取方法 硬编码(不推荐,不同Windows版本不同) 从NTDLL导出表解析 从 LdrpThunkSignature 获取 特征码匹配(如 b8d18b4c ) 4.2 反Hook技术 检查前几条指令是否为 jmp 查找邻近的干净函数 映射干净的NTDLL副本 使用硬件断点检测hook 4.3 隐蔽调用技术 间接系统调用(跳转到NTDLL) 随机选择NTDLL中的 syscall 位置 使用异常处理机制 加密系统调用stub 5. 参考资源 系统调用号查询: https://j00ru.vexillium.org/syscalls/nt/64/ 关键数据结构: _KUSER_SHARED_DATA , PEB , TEB 相关项目: SysWhispers, Hell's Gate, HWSyscalls等 6. 总结 系统调用免杀技术核心在于: 正确获取系统调用号 绕过或检测用户模式hook 选择隐蔽的系统调用方式(直接/间接) 保持与合法程序相似的行为特征 随着防御技术发展,更先进的方案如硬件断点、异常处理、内存映射等被引入,使得检测和防御更加困难。理解这些技术的原理和实现对于攻防双方都至关重要。