Guides

Syscall Generation

How PayloadFactory generates and randomizes syscalls using SysPlant.

Syscall Generation

On Windows, calling APIs through the import table leaves a fingerprint that EDRs can flag. PayloadFactory replaces them with direct syscalls generated by the SysPlant library (a declared dependency in pyproject.toml), using one of several recovery strategies. This is Windows-only — Linux targets use native libc syscalls and skip this step entirely.

Control it with two flags:

python main.py thread_hijack -s sc.bin --syscall sysplant -r jumper_randomized

--syscall

Defines how syscalls are resolved at runtime:

ValueBehaviour
stubs(default) Use the bundled GetSyscallStub helpers in libs/.
sysplantGenerate syscall resolution code via SysPlant.
plainCall the syscalls directly (no indirection).

-r/--recovery

SysPlant recovery strategy — how the stub recovers the syscall number and ntdll base at runtime. Mapped to SysPlant iterators in ExecutableFactory:

Recovery flagSysPlant iteratorMeaning
embeddedhellNumber is embedded directly in the stub.
jumpertartarusA single indirect "jumper" resolves it.
jumper_randomizedcanterlot(default) Randomized jumper chain.
egg_hunterfreshyEgg-hunter scan to locate the stub.

Randomizing syscall names

By default, syscall names in the stub (e.g. NtAllocateVirtualMemory) are randomized to reduce string-based detection. Disable this with -nr/--no-random:

python main.py thread_hijack -s sc.bin --syscall sysplant -nr

When randomization is on and --syscall sysplant is used, the random names are applied consistently to both the C++ stub and the generated libs/syscalls.h header.

Copyright © 2026