Features • Installation • Usage • Techniques • HollowCorpus • Scope
VisorHollow runs shellcode injection into a spawned target process and then asks Sysmon whether it noticed. It implements two techniques (section and classic), queries Sysmon events 8, 10, and 25, and prints a HIT or MISS per event ID. HollowCorpus extends this to a six-tier ladder that walks from the loudest possible injection path to direct-syscall ntdll-hook bypass. The output is a coverage matrix that shows the exact tier at which the detection stack stops catching the technique.
A generic EDR review tells you "Sysmon is installed." VisorHollow tells you which signal Sysmon actually emits when a real injection runs, and which technique slips past it. The HollowCorpus run produces an evidence-backed coverage number, not an attestation.
- Single Go binary, no CGO, single dependency (
golang.org/x/sys) - Two injection techniques:
section(NtMapViewOfSection) andclassic(VirtualAllocEx + CreateRemoteThread) - HollowCorpus six-tier detection ladder, ID-keyed (T1 through T6)
- Sysmon event-log query for events 8, 10, and 25 with configurable lookback window
- Coverage matrix output: per-tier HIT/MISS plus "first undetected tier" summary
- Default payload calls
WinExec("calc.exe", SW_SHOW)via PEB-walk API resolution. Replacepayload.Shellcodefor custom shellcode - Cross-compile from Linux or macOS, run on Windows
# Native Windows build
go build -o visorhollow.exe .
# Cross-compile from Linux or macOS
GOOS=windows GOARCH=amd64 go build -o visorhollow.exe .Requires Go 1.21 or later. Single dependency: golang.org/x/sys. No CGO.
visorhollow hollow --technique section --target notepad.exe --check
visorhollow hollow --technique classic --target calc.exe
visorhollow check --since 10m --technique section
visorhollow corpus list
visorhollow corpus run
visorhollow corpus run --tier 1-3
visorhollow corpus run --id T1055-04-hijack --target calc.exehollow flags
| Flag | Default | Effect |
|---|---|---|
--technique |
section |
section or classic |
--target |
notepad.exe |
process to spawn and inject into |
--check |
off | query Sysmon automatically after injection |
check flags
| Flag | Default | Effect |
|---|---|---|
--since |
5m |
look-back window (e.g. 10m, 1h) |
--technique |
section |
expected event set: section or classic |
| Flag | Technique | Key APIs | Detection signals |
|---|---|---|---|
section |
NtMapViewOfSection variant | NtCreateSection, NtMapViewOfSection x2, SetThreadContext, ResumeThread | ETW KERNEL_THREATINT_KEYWORD_MAPVIEW, Sysmon E25, E10 |
classic |
VirtualAllocEx + WriteProcessMemory | VirtualAllocEx (RWX), WriteProcessMemory, CreateRemoteThread | Sysmon E8, E10 |
CreateProcess (suspended)
-> NtCreateSection (anonymous, pagefile-backed, RWX)
-> NtMapViewOfSection -> current process (local RWX mapping)
-> memcpy shellcode into local mapping
-> NtMapViewOfSection -> target process (remote RX mapping)
-> SetThreadContext: RIP = remote mapping address
-> ResumeThread
Avoids NtWriteVirtualMemory entirely. Detection depends on ETW Threat Intelligence (KERNEL_THREATINT_KEYWORD_MAPVIEW) or Sysmon E25 (ProcessTampering, added in Sysmon v13). Without v13+, the section technique is a MISS on E25.
CreateProcess (suspended)
-> VirtualAllocEx (RWX)
-> WriteProcessMemory
-> CreateRemoteThread (start = RWX region)
-> ResumeThread
The canonical path. Loud on E8. Useful as a baseline: if classic is a MISS, the Sysmon config is broken.
Six techniques, each one removing a detection signal from the previous tier.
| Tier | ID | Technique | ExpectEvents | Evasion added |
|---|---|---|---|---|
| T1 | T1055-01-classic | WriteProcessMemory + CreateRemoteThread | E8, E10 | (baseline) |
| T2 | T1055-02-section | NtMapViewOfSection + SetThreadContext | E10, E25 | no NtWriteVirtualMemory |
| T3 | T1055-03-apc | NtMapViewOfSection + QueueUserAPC | E10, E25 | no CreateRemoteThread |
| T4 | T1055-04-hijack | Thread Context Hijacking (existing thread) | E10 | no new process, no section object |
| T5 | T1055-05-stomp | Module Stomping (DLL .text overwrite) | E8, E10 | no anonymous RWX VAD, E25 blind |
| T6 | T1055-06-direct-syscall | Direct Syscall | E10, E25 | ntdll user-mode hooks bypassed entirely |
VisorHollow — injection starting
[technique] NtMapViewOfSection
[target] notepad.exe
[payload] 271 bytes
[spawned] PID 4812 TID 4816 (suspended)
[section] handle 0x6c
[local map] 0x22b0a4e0000 (RWX, 271 bytes)
[copied] shellcode written to local mapping
[remote map] 0x22b0a4e0000 (RX, PID 4812)
[ctx] RIP -> 0x22b0a4e0000
[resumed] PID 4812 executing at 0x22b0a4e0000
Detection Benchmark Results
EvtID STATUS COUNT DESCRIPTION
10 HIT 1 OpenProcess access from injector (Event 10)
25 HIT 1 Process tampering / remote mapping detected (Event 25)
[RESULT] ALL DETECTED — EDR/Sysmon config is catching this technique
HollowCorpus Detection Coverage Matrix
Tier Technique E8 E10 E25 Score
T1 WriteProcessMemory + CreateRemoteThread HIT HIT --- 2/2
T2 NtMapViewOfSection + SetThreadContext --- HIT HIT 2/2
T3 NtMapViewOfSection + QueueUserAPC --- HIT HIT 2/2
T4 Thread Context Hijacking --- MISS --- 0/1
T5 Module Stomping (DLL .text overwrite) HIT HIT --- 2/2
T6 Direct Syscall (bypass ntdll hooks) --- MISS MISS 0/2
Total coverage: 7/10 events detected
[RESULT] First undetected tier: T4
Techniques at T4+ evade your current detection stack.
First undetected tier: T4 means T1 through T3 all fired their expected events, T4 slipped through. T5 is detected again because Module Stomping re-introduces E8 and E10. T6 (direct syscall) bypasses ntdll user-mode hooks entirely and is the hardest tier to catch.
| Event | Technique | What triggers it |
|---|---|---|
| E8 (CreateRemoteThread) | classic, stomp | thread creation with start address outside loaded PE |
| E10 (ProcessAccess) | both | OpenProcess with PROCESS_ALL_ACCESS from injector |
| E25 (ProcessTampering) | section, apc, direct-syscall | remote executable mapping via NtMapViewOfSection |
ETW KERNEL_THREATINT_KEYWORD_MAPVIEW fires on NtMapViewOfSection when source process differs from target. Requires Defender or a compatible EDR with ETW Threat Intelligence enabled.
For the section technique:
<!-- Event 25: ProcessTampering (Sysmon v13+) -->
<ProcessTampering onmatch="include">
<all/>
</ProcessTampering>
<!-- Event 10: ProcessAccess -->
<ProcessAccess onmatch="include">
<GrantedAccess condition="is">0x1FFFFF</GrantedAccess>
</ProcessAccess>For the classic technique, add:
<!-- Event 8: CreateRemoteThread -->
<CreateRemoteThread onmatch="include">
<all/>
</CreateRemoteThread>Windows x64 execution only. The injection and Sysmon-query code calls Windows APIs and builds only for GOOS=windows. Cross-compilation from Linux or macOS is supported, but the resulting binary must run on a Windows host. VisorHollow tests host-layer detection (Sysmon, EDR). It does not discover attack surface, deliver adversarial prompts, or run on Linux or macOS targets. Only run it on hosts you own or have explicit written authorization to test.
- aimap — AI/ML infrastructure fingerprint scanner
- scanner — active-banner stage between passive discovery and deep enumeration
- VisorLog — finding ledger and ingest pipeline
- VisorCAS — content-addressed false-positive ledger
- BARE — semantic exploit-module ranking over scanner findings
MIT. Part of the NuClide toolchain. Contact: nuclide-research.com