Call-stack spoofing for Dyncvoke.
Public API is [spoof!] (direct call) and [spoof_syscall!] (indirect
syscall). Mode is a compile-time choice:
- Synthetic (default,
dyncvokefeaturespoof). BuildsRtlUserThreadStart -> BaseThreadInitThunk -> gadget frames -> target. Works from any thread, including pool threads. - Desync (
dyncvokefeaturespoof-desync, crate featuredesync). Splices spoofed frames onto a liveBaseThreadInitThunkreturn on the current thread. Looks closer to a normal user thread. Fails on pool threads that never went through that path.
use spoof::{spoof_syscall, AsPointer};
use core::ffi::c_void;
use core::ptr::null_mut;
let mut addr: *mut c_void = null_mut();
let mut size: usize = 0x1000;
let status = spoof_syscall!(
"NtAllocateVirtualMemory",
-1isize,
addr.as_ptr_mut(),
0usize,
size.as_ptr_mut(),
0x3000u32,
0x04u32,
).unwrap() as i32;
The trampoline lives in src/asm/{msvc,gnu}/*.asm and reads
[types::Config] by field order. Do not reorder those fields.
Syscall SSNs come from [dyncvoke_core::resolve_syscall].