Methods

Random

How the random syscall method works in Sysplant — SSN explicitly set, execution via a randomly chosen syscall;ret gadget in ntdll.

Random Method


Principle

The random method combines the explicit SSN control of direct with the ntdll return-address advantage of indirect. It resolves the SSN normally, then jumps to a randomly selected syscall;ret gadget from a different ntdll stub — not the one that corresponds to the target function.

The result: EAX holds the correct SSN, the syscall instruction executes from an unpredictable location inside ntdll, and the call-stack frame appears to originate from a ntdll stub that is not necessarily the one for the called function.


Generated stub (x64, from source)

SPT_Syscall:
    pop  rax              ; discard return address
    pop  r15              ; load function hash
    mov  [rsp+ 8], rcx    ; save arg1
    mov  [rsp+16], rdx    ; save arg2
    mov  [rsp+24], r8     ; save arg3
    mov  [rsp+32], r9     ; save arg4
    sub  rsp, 0x28        ; shadow space

    mov  rcx, r15
    call SPT_GetSyscallNumber      ; rax = SSN for this function
    mov  rcx, r15
    mov  r15, rax                  ; r15 = SSN (saved before next call)
    call SPT_GetRandomSyscallAddress ; rax = random Entries[index].SyscallAddress

    xchg r15, rax                  ; r15 = random syscall gadget, rax = SSN

    add  rsp, 0x28        ; restore stack
    mov  rcx, [rsp+ 8]
    mov  rdx, [rsp+16]
    mov  r8,  [rsp+24]
    mov  r9,  [rsp+32]
    mov  r10, rcx         ; Windows x64 syscall ABI
    jmp  r15              ; jump to random syscall;ret gadget — eax = SSN

After the xchg: RAX contains the correct SSN, R15 contains the random gadget address. The syscall instruction is reached by the jump into the gadget.


What SPT_GetRandomSyscallAddress returns

SPT_GetRandomSyscallAddress (from resolvers/random.c) picks a random index from the syscall list that:

  1. Does not correspond to the requested function (different hash).
  2. Has a .SyscallAddress that is not equal to .Address — i.e., Entries[index].SyscallAddress != Entries[index].Address. This condition filters out entries where no usable syscall;ret gadget was found during list population.

It returns Entries[index].SyscallAddress, the address of the syscall opcode found inside that unrelated ntdll stub.


What .SyscallAddress is

During list population (SPT_PopulateSyscallList), the helper SPT_DetectPadding scans forward from each ntdll function start until it finds the byte sequence {0x0F, 0x05, 0xC3} (syscall; ret) within 0x22 bytes. The byte offset returned by SPT_DetectPadding is added to .Address to yield .SyscallAddress.

If no syscall; ret pattern is found within 0x22 bytes, .SyscallAddress remains equal to .Address. The random resolver skips such entries.


Characteristics

PropertyValue
Inline syscall in binaryNo
EAX set explicitly in stubYes
Return address during syscallInside a random ntdll stub
Predictable syscall locationNo — varies per call
Requires usable gadgets in syscall listYes

Default iterators

random is the default method for the syswhispers3 and canterlot iterators.

Copyright © 2026