Random
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:
- Does not correspond to the requested function (different hash).
- Has a
.SyscallAddressthat is not equal to.Address— i.e.,Entries[index].SyscallAddress != Entries[index].Address. This condition filters out entries where no usablesyscall;retgadget 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
| Property | Value |
|---|---|
Inline syscall in binary | No |
| EAX set explicitly in stub | Yes |
| Return address during syscall | Inside a random ntdll stub |
| Predictable syscall location | No — varies per call |
| Requires usable gadgets in syscall list | Yes |
Default iterators
random is the default method for the syswhispers3 and canterlot iterators.