Canterlot's Gate
Canterlot's Gate
Origin: @MDSecLabs / @0x42en — 2022
Default method: random
Principle
Canterlot's Gate resolves SSNs by enumerating ntdll's Exception Directory (IMAGE_DIRECTORY_ENTRY_EXCEPTION) rather than relying on opcode bytes or address ordering alone.
The Exception Directory (IMAGE_RUNTIME_FUNCTION_ENTRY array) is the table used by the Windows x64 exception-handling mechanism. It lists every function that has an entry in the unwind data, ordered by function start address. Since Windows assigns SSNs in the same address order, Canterlot can determine SSNs by counting Zw* entries as they appear in this table.
Algorithm (from source)
- PEB walk — locate ntdll base, load both its Export Directory and Exception Directory:
ExportDirectory = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress RuntimeFunctions = DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress - Outer loop over RuntimeFunctions — iterate
IMAGE_RUNTIME_FUNCTION_ENTRYrecords in table order (index 0, 1, 2 …). - Inner loop over exports — for each runtime entry, search the Export Name/Ordinal tables for a function whose RVA matches
RuntimeFunctions[i].BeginAddress. - Filter for
Zw*— check the matched function name:if (*(USHORT*)FunctionName == 0x775a) // 'Zw' prefix - ssn counter — a local counter, incremented once per matched
Zw*entry, gives the SSN:Entries[ssn].Hash = SPT_HashSyscallName(FunctionName); Entries[ssn].Address = FunctionAddress; Entries[ssn].SyscallAddress = FunctionAddress + SPT_DetectPadding(FunctionAddress); ssn++;
The SSN is therefore determined by the position of the function in the Exception Directory (relative to other Zw* entries), not by reading opcode bytes.
Why the Exception Directory order matters
The x64 IMAGE_RUNTIME_FUNCTION_ENTRY table is required by the Windows exception-handling ABI to be sorted by BeginAddress (ascending). This is enforced at link time. The result is equivalent to sorting by function address — which, as with FreshyCalls and SysWhispers2, corresponds directly to SSN order for the Zw* family.
Canterlot therefore produces the same SSN mapping as address-sorted approaches, but through a structurally different mechanism: it reads the already-sorted exception table instead of sorting exports in memory.
Sensitivity to hooks
Since Canterlot never reads the opcode bytes of a stub to find the SSN (it only calls SPT_DetectPadding to find the syscall instruction offset for indirect/random methods), SSN resolution is hook-agnostic.
Recommendation
Canterlot is the most recently developed iterator in Sysplant and is recommended for modern environments. Its combination of exception-directory enumeration for SSN resolution, random default method, and robustness to hook bytes makes it the strongest general-purpose choice.