Skip to content

Instantly share code, notes, and snippets.

@gremlinbeet
Created May 12, 2025 20:07
Show Gist options
  • Save gremlinbeet/4960774f8a08bff6b1667eb69da24f7b to your computer and use it in GitHub Desktop.
Save gremlinbeet/4960774f8a08bff6b1667eb69da24f7b to your computer and use it in GitHub Desktop.
nt!PsSyscallProviderDispatch
// Pseudocode and structs for nt!PsSyscallProviderDispatch.
// For ntosknrl win11 24H2 10.0.26100.1742.
// Restored by Cyra, adjusted by @sixtyvividtails.
//
// See actual research:
// by @gal_kristal: https://gist.github.com/Kristal-g/eec050b3fcea2a77715ef0cff4acf841
// by @0xfluxsec: https://fluxsec.red/alt-syscalls-for-windows-11
// name's mine // @gal_kristal: _PS_SYSCALL_PROVIDER_SERVICE_DESCRIPTOR_GROUP
struct $SVC_DESCRIPTOR
{
/*00*/ void* HandlersBase; // all syscall handlers are at HandlersBase + offset
/*08*/ $SVC_TABLE* LowTable; // for syscall numbers < 0x1000
/*10*/ $SVC_TABLE* HighTable; // for syscall numbers >= 0x1000
/*18*/ // size
};
// name's mine // @gal_kristal: _PS_SYSCALL_PROVIDER_SERVICE_DESCRIPTOR
struct $SVC_TABLE
{
/*00*/ uint SyscallEntriesCount; // number of entries in table, up to 0x1000
/*04*/ $SYSCALL_ENTRY SyscallEntry[]; // indexed from 0 to SyscallEntriesCount-1
/*4004*/ // maximum size
};
// name's mine // @gal_kristal: _PS_SYSCALL_PROVIDER_SERVICE_ENTRY
struct $SYSCALL_ENTRY
{
uint StackArgsCount: 4; // number of non-register arguments
uint NeedsGenericDispatch: 1; // PspSyscallProviderServiceDispatch[Generic]
uint Reserved: 3;
uint PackedOffset: 24; // real offset = PackedOffset << 4
operator uint&() { return *(uint*)this; }
};
// Up to 0x20 distinct descriptors allowed system-wide.
// Each process bound to one via EPROCESS.SyscallProviderDispatchContext.Slot.
$SVC_DESCRIPTOR PspServiceDescriptorGroupTable[0x20];
// Invoked from nt!KiSystemCall64 when
// (ETHREAD.Tcb.Header.Minimal or ETHREAD.Tcb.Header.AltSyscall)
//
// Return values:
// <1: handled, trapFrame->Rax contains return status
// =1: needs regular syscall dispatch in KiSystemCall64
// >1: raise STATUS_INVALID_SYSTEM_SERVICE
schar PsSyscallProviderDispatch(_Inout_ _KTRAP_FRAME *trapFrame):
ETHREAD* currentThread = PsGetCurrentThread()
if currentThread->Tcb.Header.Minimal:
PsPicoSystemCallDispatch(trapFrame) // invokes PspPicoProviderRoutines[1]
return 0
// notice potential TOCTOU? Hint: NtSetContextThread (most likely unusable)
uint syscallNumber = trapFrame->Rax & ~0x6000
uint syscallIndex = syscallNumber & 0xFFF
bool isHighSyscall = (syscallNumber & 0x1000) != 0
EPROCESS* currentProcess = IoThreadToProcess(currentThread)
uint slot = currentProcess->SyscallProviderDispatchContext.Slot
if slot >= 0x20:
KeBugCheckEx(0x1E0, 5, slot, currentProcess->SyscallProvider, 0)
$SVC_DESCRIPTOR& svcDescriptor = PspServiceDescriptorGroupTable[slot]
$SVC_TABLE* svcTable = isHighSyscall? svcDescriptor.HighTable: svcDescriptor.LowTable
if not svcTable:
return 1 // needs regular dispatch
if syscallIndex >= svcTable->SyscallEntriesCount:
trapFrame->Rax = STATUS_INVALID_SYSTEM_SERVICE // 0xC000001C
return 0
$SYSCALL_ENTRY syscallEntry = svcTable->SyscallEntry[syscallIndex]
if syscallEntry == 0:
return 1 // needs regular dispatch
if syscallEntry == 1:
return 2 // raise STATUS_INVALID_SYSTEM_SERVICE
if isHighSyscall:
NTSTATUS st = PspEnsureGuiThreadAndBatchFlush(currentThread)
if st == STATUS_UNSUCCESSFUL:
// transform status if needed using extra table of bytes beyond packed shadow table
schar* shadowSyscallInfo = (schar*)KeServiceDescriptorTableShadow[1].Base
+ sizeof(uint) * KeServiceDescriptorTableShadow[1].Limit
if shadowSyscallInfo[syscallIndex] == 1:
st = STATUS_INVALID_SYSTEM_SERVICE // was not intended to be called
if FAILED(st):
trapFrame->Rax = st
return 0
// unlike regular syscall packed tables, offset here is unsigned; so one can specify
// driver image base as svcDescriptor.HandlersBase, then use RVAs for handlers
uint offset = syscallEntry.PackedOffset << 4
void* syscallHandler = (char*)svcDescriptor.HandlersBase + offset // function to invoke
NTSTATUS st = STATUS_SUCCESS
if syscallEntry.NeedsGenericDispatch:
int rez = PspSyscallProviderServiceDispatchGeneric(trapFrame, syscallHandler,
syscallEntry.StackArgsCount, syscallNumber, &st)
if rez:
return (schar)rez
else:
st = PspSyscallProviderServiceDispatch(trapFrame, syscallHandler,
syscallEntry.StackArgsCount)
trapFrame->Rax = st
return 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment