Syscall原理及其地狱之门家族代码详解
字数 1359 2025-08-29 22:41:02
Syscall原理及其地狱之门家族代码详解
1. Syscall基础原理
1.1 什么是Syscall
系统调用(Syscall)是用户空间程序与内核空间交互的标准接口,允许用户态程序请求内核服务,如文件操作、进程控制、网络通信等。
1.2 Syscall工作流程
- 用户态准备参数:将系统调用号和参数放入特定寄存器
- 触发中断/特殊指令:通过
int 0x80(传统)、sysenter/syscall(现代)等方式进入内核 - 内核处理:内核根据调用号查找系统调用表,执行对应函数
- 返回用户态:将结果通过寄存器返回给用户程序
1.3 不同架构下的Syscall调用方式
| 架构 | 调用指令 | 调用号寄存器 | 参数寄存器 | 返回寄存器 |
|---|---|---|---|---|
| x86 | int 0x80 | eax | ebx, ecx, edx... | eax |
| x86_64 | syscall | rax | rdi, rsi, rdx... | rax |
| ARM | svc 0 | r7 | r0-r6 | r0 |
| ARM64 | svc 0 | x8 | x0-x6 | x0 |
2. 地狱之门(Hell's Gate)技术原理
2.1 技术背景
地狱之门是一种绕过EDR(终端检测与响应)监控的技术,通过直接调用系统服务表(SSDT)中的函数指针来规避用户态hook。
2.2 关键技术点
- 动态获取SSDT地址:通过PEB(进程环境块)和PE头解析获取ntdll.dll基址
- 解析导出表:定位Nt*/Zw*函数
- 读取前32字节:获取系统调用号和可能的SSDT索引
- 直接调用:绕过用户态hook直接进入内核
2.3 技术优势
- 绕过用户态API监控
- 避免触发EDR的用户态hook检测
- 可动态适应不同Windows版本
3. 地狱之门家族代码实现
3.1 基本实现步骤
// 1. 获取ntdll.dll基址
HMODULE GetNtdllBase() {
PPEB peb = (PPEB)__readgsqword(0x60); // x64 PEB位置
PPEB_LDR_DATA ldr = peb->Ldr;
PLIST_ENTRY list = ldr->InMemoryOrderModuleList.Flink;
while (list != &ldr->InMemoryOrderModuleList) {
PLDR_DATA_TABLE_ENTRY entry = CONTAINING_RECORD(list, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
if (wcsstr(entry->FullDllName.Buffer, L"ntdll.dll")) {
return (HMODULE)entry->DllBase;
}
list = list->Flink;
}
return NULL;
}
// 2. 解析导出表获取函数地址
PVOID GetSyscallAddress(HMODULE ntdllBase, LPCSTR funcName) {
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + dosHeader->e_lfanew);
PIMAGE_EXPORT_DIRECTORY exportDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)ntdllBase +
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD functions = (PDWORD)((DWORD_PTR)ntdllBase + exportDir->AddressOfFunctions);
PDWORD names = (PDWORD)((DWORD_PTR)ntdllBase + exportDir->AddressOfNames);
PWORD ordinals = (PWORD)((DWORD_PTR)ntdllBase + exportDir->AddressOfNameOrdinals);
for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
LPCSTR name = (LPCSTR)((DWORD_PTR)ntdllBase + names[i]);
if (strcmp(name, funcName) == 0) {
return (PVOID)((DWORD_PTR)ntdllBase + functions[ordinals[i]]);
}
}
return NULL;
}
// 3. 提取系统调用号
DWORD ExtractSyscallNumber(PVOID funcAddr) {
BYTE* code = (BYTE*)funcAddr;
// x64典型模式: mov eax, SSN
if (code[0] == 0xB8 && code[3] == 0x00 && code[4] == 0x00) {
return *(DWORD*)(code + 1);
}
return 0;
}
3.2 地狱之门家族变种
- Halo's Gate:针对Windows 10 1809及更高版本的改进
- Tartarus' Gate:添加了间接调用和混淆技术
- FreshyCalls:动态生成syscall存根
4. 防御与检测
4.1 EDR检测方法
- 用户态hook验证:检查关键API是否被hook
- 异常调用链检测:监控非标准syscall调用路径
- 行为分析:检测直接syscall调用行为模式
4.2 对抗技术
- 动态SSN获取:避免硬编码系统调用号
- 调用栈欺骗:伪造合法的调用栈
- 间接syscall:通过合法模块跳转
5. 实际应用示例
5.1 直接syscall调用NtAllocateVirtualMemory
typedef NTSTATUS(NTAPI* NtAllocateVirtualMemory_t)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect);
void DirectSyscallExample() {
HMODULE ntdll = GetNtdllBase();
PVOID funcAddr = GetSyscallAddress(ntdll, "NtAllocateVirtualMemory");
DWORD ssn = ExtractSyscallNumber(funcAddr);
PVOID baseAddr = NULL;
SIZE_T size = 0x1000;
__asm {
mov r10, rcx // x64 syscall参数约定
mov eax, ssn // 系统调用号
syscall
mov [baseAddr], rax // 结果
}
}
6. 总结
地狱之门技术代表了现代恶意软件对抗EDR检测的一种高级技术,通过深入理解Windows系统调用机制和PE结构,实现了对安全产品的有效规避。防御方需要从多维度构建检测能力,包括用户态hook验证、调用链分析和行为监控等。