Indirect Syscalls — Preserving a Legitimate Stack Trace
Why Direct Syscalls Are Not Enough
┌─────────────────────────────────────────────────────────────────┐
│ Call Stack — Legitimate Execution │
│ │
│ [0] ntdll!NtAllocateVirtualMemory ← expected frame │
│ [1] KERNELBASE!VirtualAllocEx │
│ [2] kernel32!VirtualAlloc │
│ [3] MyApplication!main+0x42 │
│ [4] KERNEL32!BaseThreadInitThunk │
│ │
│ Call Stack — Direct Syscall (suspicious) │
│ │
│ [0] MyApplication!syscall_stub+0x09 ← anomaly! │
│ [1] MyApplication!inject+0x1A │
│ [2] MyApplication!main+0x42 │
│ │
│ The ntdll frame is absent → EDR flags as suspicious. │
└─────────────────────────────────────────────────────────────────┘The Concept of Indirect Syscall
Finding the syscall; ret Offset in ntdll
syscall; ret Offset in ntdllHell's Gate Strategy
Halo's Gate Strategy
Tartarus' Gate Strategy
Complete Indirect Syscall Implementation
SysWhispers3 with Indirect Syscalls
Technique Comparison
Advanced Detection
References
Last updated