Skip to main content

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 all Nt* exports from ntdll by virtual address — the sorted index equals the SSN.
Advantages:
  • Works even if every stub is hooked
  • Reads only VAs, never function bytes
  • Very fast (one-time VA sort)
  • Hook-resistant
How it works:
  1. Enumerate all Nt* exports from ntdll
  2. Sort by virtual address (ascending)
  3. Sorted index = syscall number

Static Embedding

Embeds SSNs from the bundled j00ru syscall table at generation time.
Advantages:
  • Fastest (no runtime parsing)
  • No ntdll interaction needed
Disadvantages:
  • SSN table in binary is a detection signal
  • Must match target Windows version exactly
  • Less flexible than dynamic methods
Update the table:

Hell’s Gate

Reads the mov eax, <SSN> opcode directly from each ntdll stub.
Opcode pattern:
Advantages:
  • Reads actual ntdll code
  • Fast
Disadvantages:
  • 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.
How it works:
  1. Try to read SSN from target stub (Hell’s Gate)
  2. If hooked, scan neighbors: Nt[Function-8] through Nt[Function+8]
  3. Find first clean neighbor, calculate offset
  4. Infer target SSN: neighbor_SSN + offset
Advantages:
  • 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.
Detected hook opcodes:
  • E9 xx xx xx xx — near relative JMP (most common)
  • FF 25 xx xx xx xx — far absolute JMP via memory
  • EB xx — short JMP
  • CC — int3 breakpoint
  • E8 xx xx xx xx — call (rare)
Advantages:
  • 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.
How it works:
  1. NtOpenSection(\KnownDlls\ntdll.dll)
  2. NtMapViewOfSection() — map clean ntdll to memory
  3. Read SSNs from clean .text section
  4. NtUnmapViewOfSection() — cleanup
Advantages:
  • Maximum hook resistance — EDR hooks irrelevant
  • Reads from on-disk image, guaranteed clean
Disadvantages:
  • Slower (disk mapping overhead)
  • Requires system privileges for \KnownDlls access

RecycledGate

Most resilient method. Combines FreshyCalls (sort-by-VA) with Hell’s Gate opcode validation.
How it works:
  1. Get candidate SSN from sorted VA position (FreshyCalls)
  2. If stub is clean, verify SSN matches opcode (double-check)
  3. If stub is hooked, trust the sorted-index SSN (hook-resistant)
Advantages:
  • 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.
How it works:
  1. Set DR0 = address of syscall instruction in ntdll stub
  2. Register VEH handler
  3. Call into stub — VEH catches EXCEPTION_SINGLE_STEP
  4. At breakpoint, EAX contains the SSN — capture it
  5. Clear DR0, skip syscall, continue
Advantages:
  • No reading of potentially-tampered bytes
  • Works even with complex hooks
Disadvantages:
  • Slower (exception handling overhead)
  • Advanced technique

Comparison Table

Invocation Methods

How the syscall instruction is executed affects EDR detection.

Embedded (Direct Syscall)

Default. The syscall instruction lives in your stub.
Generated ASM:
Detection vector: At kernel entry, RIP points into your PE (not ntdll) — detectable by EDRs.

Indirect

Jumps to a syscall;ret gadget inside ntdll.dll.
Generated ASM:
Advantages:
  • At kernel entry, RIP appears to be inside ntdll
  • Looks identical to a legitimate API call
  • No syscall opcode in your PE on disk

Randomized Indirect

Selects a random gadget from a pool of up to 64 on every call.
Generated ASM:
Advantages:
  • Defeats EDR heuristics that whitelist specific gadget addresses
  • Per-call entropy (no API call needed)
  • Maximum stealth
Note: SW3 had a bug where rdtsc corrupted edx (arg2). SW4 correctly saves/restores rdx.

Egg Hunt

Stubs contain an 8-byte random egg marker instead of syscall. SW4_HatchEggs() replaces eggs at runtime.
Generated ASM (before hatching):
Runtime hatching:
Advantages:
  • No syscall opcode in binary on disk
  • Defeats static analysis
Disadvantage:
  • Must call SW4_HatchEggs() before any syscalls

Evasion Features

Obfuscation

Randomizes stub ordering and injects junk instructions.
14 junk instruction variants:
Result: Each stub has unique instruction patterns — defeats signature-based detection.

SSN Encryption

XOR-encrypts SSN values at rest.
Generated code:
ASM stub:
Advantage: No plaintext SSN table in binary at rest.

Call Stack Spoofing

Replaces the visible return address with a pointer into ntdll.
Usage:
How it works:
Result: Stack-walking EDRs see legitimate ntdll return addresses.

ETW Bypass

Patches ntdll!EtwEventWrite to return STATUS_ACCESS_DENIED.
Usage:
Note: This bypasses user-mode ETW only. Kernel-mode ETW-Ti callbacks are unaffected.

AMSI Bypass

Patches amsi.dll!AmsiScanBuffer to return E_INVALIDARG.
Usage:
How it works:
  1. Locate amsi.dll!AmsiScanBuffer
  2. Patch first bytes to return E_INVALIDARG
  3. AMSI thinks scan arguments are invalid, allows execution

ntdll Unhooking

Maps a clean ntdll from \KnownDlls\ and overwrites the hooked .text section.
Usage:
Flow:
  1. NtOpenSection(\KnownDlls\ntdll.dll)
  2. NtMapViewOfSection() — map clean ntdll
  3. Find .text section in clean copy
  4. VirtualProtect(RWX) on hooked ntdll
  5. memcpy(clean → hooked)
  6. VirtualProtect(RX) — restore protection
  7. Cleanup
Result: ALL inline hooks removed from ntdll.

Anti-Debugging

Performs 6 checks to detect debugger/analysis presence.
Usage:
6 checks:

Sleep Encryption

Ekko-style memory encryption during sleep.
Usage:
How it works:
  1. Generate random XOR key via RDTSC
  2. XOR-encrypt own .text section
  3. Set waitable timer + queue APC to decrypt
  4. Sleep in alertable state
  5. Timer fires → APC decrypts .text → execution resumes
Defeats:
  • Memory scanners during sleep (code is gibberish)
  • Periodic module scans
  • YARA/signature scans on in-memory PE

Maximum Evasion (Red Team)

Includes:
  • Randomized indirect syscalls (64 gadgets)
  • RecycledGate (most resilient SSN resolution)
  • All evasion features enabled

Bypass Heavily Hooked EDR

Strategy:
  • Read clean SSNs from disk (bypasses all hooks)
  • Unhook ntdll .text section
  • Indirect syscalls (RIP in ntdll)

Fast & Stealthy

Balance: Good evasion without significant performance overhead.

No Syscall on Disk

Strategy: Egg hunt (no 0F 05 on disk) + junk instructions.

EDR Detection Landscape

¹ Syscall opcode is in your PE’s .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