
Hypervisor isolated shellcode execution environment. Maps host process memory into a guest vCPU, intercepts DLL execute faults, and proxies API calls to the host, Stardust PIC shellcode compatible
Hypervisor isolated shellcode execution environment. Maps host process memory into a guest vCPU, intercepts DLL execute faults, and proxies API calls to the host, Stardust PIC shellcode compatible.
HyperLoader executes position independent shellcode inside an isolated virtual CPU created with the Windows Hypervisor Platform API (WHvP). The vCPU runs in its own address space.
Userland EDR hooks (inline hooks, IAT hooks) are bypassed by design, they live in the host process address space, and the shellcode never executes there. The shellcode's API resolution, PEB walk, and decision logic run entirely inside the vCPU, invisible to any userland instrumentation.
The technique does not bypass some kernel level detection. WHvCreatePartition and WHvRunVirtualProcessor are visible to EDR kernel sensors, and any API calls the host proxy executes on behalf of the guest go through the normal kernel callback chain (image load notifications, minifilter, ETW-TI).
Host process
├── WHvCreatePartition / WHvMapGpaRange
│ └── identity VA -> GPA map: ntdll, kernel32, PEB, TEB (read only, noexec)
├── Exception interception (#PF + execute faults)
└── Exit loop: DLL call proxy
└── executes DLL functions natively on the host
vCPU guest (isolated)
└── Stardust PIC shellcode
├── PEB walk -> resolves ntdll / kernel32 (read only view)
├── API resolution via FNV1a hash over EAT
└── DLL call -> execute fault -> host proxies -> result returned
A 2MB low memory region is allocated and mapped into the guest at GPA 0. The guest page tables (PML4/PDPT/PD) live here, along with the shellcode, stack, LSTAR trampoline, and syscall buffer.
GPA 0x0000 Stack / page tables (identity mapped 2MB, RWX)
GPA 0x1000 PML4
GPA 0x2000 PDPT
GPA 0x3000 PD (2MB large page)
GPA 0x4000 Shellcode (Stardust binary)
GPA 0x5000 Output buffer (RCX arg on entry)
GPA 0x6000 LSTAR trampoline
GPA 0x7000 Syscall buffer (SSN + args + retval)
GPA 0x8000+ PT pool (4KB pages for VA→GPA mappings)
Before launching the vCPU, HyperLoader maps the host process structures into the guest using WHvMapGpaRange:
ntdll.dll, kernel32.dll, kernelbase.dll: read-only, no execute0x7FFE0000)DLL pages are intentionally mapped without the execute flag. The guest can read them (EAT walk, import resolution) but cannot execute them.
When Stardust calls a DLL function, the vCPU raises an execute fault (WHvRunVpExitReasonMemoryAccess, access type 2). The exit loop:
The shellcode resumes as if the call completed normally. All DLL execution happens on the host, through the real (potentially hooked) functions, but the decision of what to call and when was made inside the isolated vCPU.
Pages not mapped at startup are handled on demand via #PF interception (WHvPartitionPropertyCodeExceptionExitBitmap). When the shellcode accesses an unmapped page, the host resolves it, maps it into the guest, and resumes execution transparently.
LSTAR is set to a small trampoline at GPA 0x6000 that saves the syscall number and arguments to the buffer at GPA 0x7000 and executes HLT. This handles any direct syscall instructions that reach the trampoline instead of going through the DLL proxy path.
WinHvPlatform.dll / WinHvPlatform.libReplace sc_stardust[] in HyperLoader.cpp with your Stardust binary:
xxd -i bin/stardust.x64.bin
Paste the byte array and recompile. The shellcode receives a pointer to the output buffer in RCX on entry.
This project is for educational and research purposes.