重写ring3 API函数
字数 1362 2025-08-29 08:30:05

重写Ring3 API函数实现免杀技术详解

一、系统调用基础概念

1.1 系统调用介绍

系统调用(System Call)是操作系统提供给应用程序与内核交互的核心接口,允许用户程序请求内核执行特权操作,是用户态和内核态之间的桥梁。

在Windows系统中:

  • Zw*Nt*类型API通过syscall指令进入内核态
  • 这些API本质上是Ring3级别的,但通过系统调用触发内核特权操作
  • 执行流程:用户态API → syscall指令 → 根据SSN(系统调用号)从SSDT查找 → 执行内核态对应函数

1.2 EDR的用户模式钩子机制

现代EDR通过在ntdll.dll中植入钩子来监控API调用:

  1. 使用jmp指令覆盖目标函数(如NtOpenProcess)前5字节
  2. 重定向执行流到EDR自身的DLL进行参数检查
  3. 执行原始指令后跳回ntdll继续执行

二、直接系统调用技术原理

2.1 技术优势

  • 绕过EDR在ntdll上的用户态钩子
  • 直接通过汇编指令实现系统调用,避免被监控

2.2 技术局限性

  1. 直接使用syscall可能被高级EDR标记为异常行为
  2. 函数调用栈异常,容易被检测
  3. 仅对具备用户态Hook的EDR有效(如BitDefender)

2.3 系统调用流程分析(x64架构)

  1. 参数传递:前4个参数通过rcx, rdx, r8, r9传递
  2. 寄存器准备:syscall执行会覆盖rcx返回地址,需先保存到r10
  3. 系统调用号设置:不同Windows版本需要不同SSN
  4. 系统调用指令:现代CPU使用syscall,旧系统使用int 2Eh

三、环境配置与实现

3.1 Visual Studio配置

  1. 项目属性 → 生成依赖性 → 勾选"masm"
  2. 添加.asm文件并设置属性:
    • 项类型:自定义生成工具
    • 命令行:ml64 /c %(fileName).asm
    • 输出:%(fileName).obj

3.2 汇编代码模板

; 示例:ZwAllocateVirtualMemory (SSN: 0x18)
_TEXT segment

ZwAllocateVirtualMemory proc
    mov r10, rcx
    mov eax, 18h    ; SSN
    syscall
    ret
ZwAllocateVirtualMemory endp

end

3.3 C++调用示例

// 函数声明
EXTERN_C NTSTATUS ZwAllocateVirtualMemory(
    HANDLE ProcessHandle,
    PVOID* BaseAddress,
    ULONG_PTR ZeroBits,
    PSIZE_T RegionSize,
    ULONG AllocationType,
    ULONG Protect);

int main() {
    PVOID baseAddr = nullptr;
    SIZE_T size = 0x1000;
    
    // 调用重写的API
    ZwAllocateVirtualMemory(
        GetCurrentProcess(),
        &baseAddr,
        0,
        &size,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);
    
    return 0;
}

四、关键技术与注意事项

4.1 系统调用号(SSN)获取方法

  1. 使用调试工具(IDA/Windbg/x64dbg)查看ntdll导出函数
  2. 在"符号"界面找到目标函数对应的汇编代码
  3. 定位mov eax, SSN指令获取调用号

4.2 版本兼容性问题

  • 不同Windows版本SSN可能不同
  • 示例代码仅适用于Windows 11,其他系统需调整
  • 建议实现动态SSN获取机制

4.3 高级规避技术

  1. 间接系统调用:使调用栈看起来更合法
  2. 动态SSN解析:避免硬编码
  3. 调用栈混淆:防止ETW分析检测

五、防御与检测

5.1 EDR检测手段

  1. Windows事件跟踪(ETW)分析线程调用栈
  2. 检测异常的syscall指令使用模式
  3. 监控非标准系统调用路径

5.2 应对措施

  1. 模拟合法程序的调用模式
  2. 使用间接系统调用技术
  3. 结合其他混淆技术增强隐蔽性

六、扩展阅读方向

  1. 动态解析SSN的实现方法
  2. 间接系统调用技术细节
  3. 系统调用与内核PatchGuard的交互
  4. ETW监控机制与反制手段

通过重写Ring3 API函数实现直接系统调用,可以有效绕过EDR的用户态钩子,但需要注意调用栈的合法性和SSN的动态获取,才能在实际对抗中发挥更好的效果。

重写Ring3 API函数实现免杀技术详解 一、系统调用基础概念 1.1 系统调用介绍 系统调用(System Call)是操作系统提供给应用程序与内核交互的核心接口,允许用户程序请求内核执行特权操作,是用户态和内核态之间的桥梁。 在Windows系统中: Zw* 或 Nt* 类型API通过 syscall 指令进入内核态 这些API本质上是Ring3级别的,但通过系统调用触发内核特权操作 执行流程:用户态API → syscall指令 → 根据SSN(系统调用号)从SSDT查找 → 执行内核态对应函数 1.2 EDR的用户模式钩子机制 现代EDR通过在ntdll.dll中植入钩子来监控API调用: 使用 jmp 指令覆盖目标函数(如 NtOpenProcess )前5字节 重定向执行流到EDR自身的DLL进行参数检查 执行原始指令后跳回ntdll继续执行 二、直接系统调用技术原理 2.1 技术优势 绕过EDR在ntdll上的用户态钩子 直接通过汇编指令实现系统调用,避免被监控 2.2 技术局限性 直接使用syscall可能被高级EDR标记为异常行为 函数调用栈异常,容易被检测 仅对具备用户态Hook的EDR有效(如BitDefender) 2.3 系统调用流程分析(x64架构) 参数传递 :前4个参数通过 rcx , rdx , r8 , r9 传递 寄存器准备 :syscall执行会覆盖 rcx 返回地址,需先保存到 r10 系统调用号设置 :不同Windows版本需要不同SSN 系统调用指令 :现代CPU使用 syscall ,旧系统使用 int 2Eh 三、环境配置与实现 3.1 Visual Studio配置 项目属性 → 生成依赖性 → 勾选"masm" 添加.asm文件并设置属性: 项类型:自定义生成工具 命令行: ml64 /c %(fileName).asm 输出: %(fileName).obj 3.2 汇编代码模板 3.3 C++调用示例 四、关键技术与注意事项 4.1 系统调用号(SSN)获取方法 使用调试工具(IDA/Windbg/x64dbg)查看ntdll导出函数 在"符号"界面找到目标函数对应的汇编代码 定位 mov eax, SSN 指令获取调用号 4.2 版本兼容性问题 不同Windows版本SSN可能不同 示例代码仅适用于Windows 11,其他系统需调整 建议实现动态SSN获取机制 4.3 高级规避技术 间接系统调用 :使调用栈看起来更合法 动态SSN解析 :避免硬编码 调用栈混淆 :防止ETW分析检测 五、防御与检测 5.1 EDR检测手段 Windows事件跟踪(ETW)分析线程调用栈 检测异常的syscall指令使用模式 监控非标准系统调用路径 5.2 应对措施 模拟合法程序的调用模式 使用间接系统调用技术 结合其他混淆技术增强隐蔽性 六、扩展阅读方向 动态解析SSN的实现方法 间接系统调用技术细节 系统调用与内核PatchGuard的交互 ETW监控机制与反制手段 通过重写Ring3 API函数实现直接系统调用,可以有效绕过EDR的用户态钩子,但需要注意调用栈的合法性和SSN的动态获取,才能在实际对抗中发挥更好的效果。