Overview
SysWhispers4 provides multiple strategies for resolving syscall numbers (SSNs) and invoking syscalls, plus comprehensive evasion features to bypass AV/EDR detection. This guide covers all advanced options.SSN Resolution Methods
SysWhispers4 supports 8 different strategies for obtaining syscall numbers at runtime.FreshyCalls (Default)
Recommended for most scenarios. Sorts allNt* exports from ntdll by virtual address — the sorted index equals the SSN.
- Works even if every stub is hooked
- Reads only VAs, never function bytes
- Very fast (one-time VA sort)
- Hook-resistant
- Enumerate all
Nt*exports from ntdll - Sort by virtual address (ascending)
- Sorted index = syscall number
Static Embedding
Embeds SSNs from the bundled j00ru syscall table at generation time.- Fastest (no runtime parsing)
- No ntdll interaction needed
- SSN table in binary is a detection signal
- Must match target Windows version exactly
- Less flexible than dynamic methods
Hell’s Gate
Reads themov eax, <SSN> opcode directly from each ntdll stub.
- Reads actual ntdll code
- Fast
- Fails when stub is hooked (first bytes overwritten)
Halo’s Gate
Extends Hell’s Gate with neighbor scanning. When a stub is hooked, scans ±8 neighboring stubs and infers SSN via offset arithmetic.- Try to read SSN from target stub (Hell’s Gate)
- If hooked, scan neighbors:
Nt[Function-8]throughNt[Function+8] - Find first clean neighbor, calculate offset
- Infer target SSN:
neighbor_SSN + offset
- Handles sparse hooks (not every function hooked)
- Good balance of speed and resilience
Tartarus’ Gate
Extends Halo’s Gate to detect all common EDR hook patterns.E9 xx xx xx xx— near relative JMP (most common)FF 25 xx xx xx xx— far absolute JMP via memoryEB xx— short JMPCC— int3 breakpointE8 xx xx xx xx— call (rare)
- Handles complex EDR hooks
- Scans up to ±16 neighbors
- High hook resistance
SyscallsFromDisk
Bypasses ALL hooks. Maps a clean copy of ntdll from\KnownDlls\ntdll.dll and reads SSNs from the pristine .text section.
NtOpenSection(\KnownDlls\ntdll.dll)NtMapViewOfSection()— map clean ntdll to memory- Read SSNs from clean
.textsection NtUnmapViewOfSection()— cleanup
- Maximum hook resistance — EDR hooks irrelevant
- Reads from on-disk image, guaranteed clean
- Slower (disk mapping overhead)
- Requires system privileges for
\KnownDllsaccess
RecycledGate
Most resilient method. Combines FreshyCalls (sort-by-VA) with Hell’s Gate opcode validation.- Get candidate SSN from sorted VA position (FreshyCalls)
- If stub is clean, verify SSN matches opcode (double-check)
- If stub is hooked, trust the sorted-index SSN (hook-resistant)
- Works even if hooks and export table are modified
- Cross-validation increases confidence
- Best reliability
HW Breakpoint
Uses CPU debug registers (DR0–DR3) + Vectored Exception Handler (VEH) to extract SSNs.- Set DR0 = address of
syscallinstruction in ntdll stub - Register VEH handler
- Call into stub — VEH catches
EXCEPTION_SINGLE_STEP - At breakpoint,
EAXcontains the SSN — capture it - Clear DR0, skip syscall, continue
- No reading of potentially-tampered bytes
- Works even with complex hooks
- Slower (exception handling overhead)
- Advanced technique
Comparison Table
| Method | Hook Resistance | Speed | Notes |
|---|---|---|---|
| Static | None | ⚡ Fastest | Embedded table, version-specific |
| Hell’s Gate | ❌ Low | ⚡ Fast | Fails if hooked |
| Halo’s Gate | ⚠️ Medium | ⚡ Fast | Neighbor scan (±8) |
| Tartarus’ Gate | ✅ High | ⚡ Fast | Detects E9/FF25/EB/CC/E8 hooks, ±16 |
| FreshyCalls | ✅ Very High | 🔥 Medium | DEFAULT — sort by VA |
| SyscallsFromDisk | ✅✅ Maximum | 🐌 Slow | Maps clean ntdll from disk |
| RecycledGate | ✅✅ Maximum | 🔥 Medium | MOST RESILIENT — FreshyCalls + validation |
| HW Breakpoint | ✅✅ Maximum | 🐌 Slow | DR registers + VEH |
Invocation Methods
How thesyscall instruction is executed affects EDR detection.
Embedded (Direct Syscall)
Default. Thesyscall instruction lives in your stub.
RIP points into your PE (not ntdll) — detectable by EDRs.
Indirect
Jumps to asyscall;ret gadget inside ntdll.dll.
- At kernel entry,
RIPappears to be inside ntdll - Looks identical to a legitimate API call
- No
syscallopcode in your PE on disk
Randomized Indirect
Selects a random gadget from a pool of up to 64 on every call.- Defeats EDR heuristics that whitelist specific gadget addresses
- Per-call entropy (no API call needed)
- Maximum stealth
rdtsc corrupted edx (arg2). SW4 correctly saves/restores rdx.
Egg Hunt
Stubs contain an 8-byte random egg marker instead ofsyscall. SW4_HatchEggs() replaces eggs at runtime.
- No
syscallopcode in binary on disk - Defeats static analysis
- Must call
SW4_HatchEggs()before any syscalls
Evasion Features
Obfuscation
Randomizes stub ordering and injects junk instructions.SSN Encryption
XOR-encrypts SSN values at rest.Call Stack Spoofing
Replaces the visible return address with a pointer into ntdll.ETW Bypass
Patchesntdll!EtwEventWrite to return STATUS_ACCESS_DENIED.
AMSI Bypass
Patchesamsi.dll!AmsiScanBuffer to return E_INVALIDARG.
- Locate
amsi.dll!AmsiScanBuffer - Patch first bytes to
return E_INVALIDARG - AMSI thinks scan arguments are invalid, allows execution
ntdll Unhooking
Maps a clean ntdll from\KnownDlls\ and overwrites the hooked .text section.
NtOpenSection(\KnownDlls\ntdll.dll)NtMapViewOfSection()— map clean ntdll- Find
.textsection in clean copy VirtualProtect(RWX)on hooked ntdllmemcpy(clean → hooked)VirtualProtect(RX)— restore protection- Cleanup
Anti-Debugging
Performs 6 checks to detect debugger/analysis presence.| Check | Technique | Detects |
|---|---|---|
| 1 | PEB.BeingDebugged | Standard debugger attachment |
| 2 | NtGlobalFlag (offset 0x70) | Heap debug flags |
| 3 | RDTSC timing delta | Single-stepping / tracing |
| 4 | NtQueryInformationProcess(ProcessDebugPort) | Kernel debug port |
| 5 | Heap flags analysis | Debug heap indicators |
| 6 | Instrumentation callback detection | EDR hooks |
Sleep Encryption
Ekko-style memory encryption during sleep.- Generate random XOR key via
RDTSC - XOR-encrypt own
.textsection - Set waitable timer + queue APC to decrypt
- Sleep in alertable state
- Timer fires → APC decrypts
.text→ execution resumes
- Memory scanners during sleep (code is gibberish)
- Periodic module scans
- YARA/signature scans on in-memory PE
Recommended Configurations
Maximum Evasion (Red Team)
- Randomized indirect syscalls (64 gadgets)
- RecycledGate (most resilient SSN resolution)
- All evasion features enabled
Bypass Heavily Hooked EDR
- Read clean SSNs from disk (bypasses all hooks)
- Unhook ntdll
.textsection - Indirect syscalls (RIP in ntdll)
Fast & Stealthy
No Syscall on Disk
0F 05 on disk) + junk instructions.
EDR Detection Landscape
| Detection Vector | Embedded | Indirect | Randomized | Egg |
|---|---|---|---|---|
| User-mode hook bypass | ✅ | ✅ | ✅ | ✅ |
| RIP inside ntdll at syscall | ❌ | ✅ | ✅ | ❌ |
No 0F 05 in binary on disk | ✅¹ | ✅ | ✅ | ✅ |
| Random gadget per call | ❌ | ❌ | ✅ | ❌ |
| Clean call stack | --stack-spoof | --stack-spoof | --stack-spoof | --stack-spoof |
| Memory scan evasion | --sleep-encrypt | --sleep-encrypt | --sleep-encrypt | --sleep-encrypt |
| Kernel ETW-Ti bypass | ❌² | ❌² | ❌² | ❌² |
.text section (at your code address, not ntdll)² ETW-Ti fires inside the kernel — no user-mode technique bypasses it without kernel access
Next Steps
MSVC Integration
Complete Visual Studio project setup
MinGW Integration
MinGW and Clang compiler integration
