Bluepill-class type-2 Intel HV
Xeroxz Bluepill (CR3Swapper fork, archived) is a WDK type-2 Intel VMM for Windows 10. Use this skill for that lineage. Generic VMX/EPT scaffolding is hypervisor-dev. Detectability budget is stealth-hypervisor. Guest memory analysis from a VMM is hypervisor-memory-introspection.
Primary tree: https://github.com/CR3Swapper/bluepill (copy of githacks.org/_xeroxz/bluepill).
Scope
Route here when the next artifact is one of:
- VMXON / VMLAUNCH bring-up that dies with VM-instruction error 7 (invalid controls) or exit reason
0x80000021(invalid guest state) - Host-owned GDT, TSS with extra IST stacks, IDT that forwards
#DB/INT3to the guest - Self-referencing PML4 used as a two-PTE physical map (no PDPT/PD/PT walk)
- VMCALL command block for
translate/copy_virt/read_phys/write_phys/dirbase - SEH that must work in VMX-root whether the driver is
sc startor manually mapped
Tooling
| Need | Local |
|---|---|
| WDK / MSVC | VS 2022 Community + Kits 10.0.26100.0 / 10.0.28000.0 (tool-index.md) |
| Kernel debug | WinDbg classic C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ |
| Symbols | windows-symbols-debugging |
| Guest RE of the demo | IDA 9.4 / radare2 6.2 |
Workflow
Pin the lineage. Confirm the tree is Bluepill-shaped:
vmxon.cpp,vmcs.cpp,mm.cpp,idt.cpp,command.hpp,demo/vdm_ctx. Record Windows build and CPU (IA32_VMX_BASIC,IA32_VMX_PROCBASED_CTLS2high/low).- Done when revision ID, allowed-1 / allowed-0 control masks, and whether Intel PT / XSAVES exist are written down.
Fix VMCS controls before VMLAUNCH. Apply high/low MSR masks after setting desired bits. Never force
conceal_vmx_from_ptorenable_xsaveson a CPU whoseCTLSmask rejects them. See references/vmcs-bringup.md.- Done when a dump of pin/primary/secondary/exit/entry controls matches
(desired & allowed1) | allowed0.
- Done when a dump of pin/primary/secondary/exit/entry controls matches
Write guest state to Intel Vol 3C ch. 24 + 26. Set
VMCS_GUEST_ACTIVITY_STATE = 0. Copy live CR0/CR3/CR4, segment bases/limits/AR bytes fromSGDT/SIDT/segment reads, RIP after the launch site, RSP, RFLAGS. Invalid guest state (0x80000021) is almost always activity-state, unrestricted-guest CR0, or a segment AR-byte fail — not “segmentation is hard.”- Done when first VMEXIT reason is a handled exit (CPUID/VMCALL/EPT), not
0x80000021.
- Done when first VMEXIT reason is a handled exit (CPUID/VMCALL/EPT), not
Install host identity. Per-CPU host GDT is a copy of the guest GDT with a new TR base pointing at a host TSS. IST[4..6] get dedicated NonPaged stacks for
#PF/#GP/#DE. Host IDT is a copy of the guest IDT except those three vectors route to VMX-root SEH (RIP → catch block). Forward#DBandINT3to the guest so WinDbg still works.- Done when a deliberate
#PFinside a__tryin VMX-root lands in the except block, and a guestint 3still breaks WinDbg.
- Done when a deliberate
Build the self-ref map. Clone system PML4 into a host CR3. Reserve PML4[0..254] as PTE slots, not directory pointers. Install a self-ref at PML4[255]. Each logical processor owns two slots (
apic_id * 2 + map_type) for src/dst physical pages.map_page(phys, src|dest)writes the PTE PFN,__invlpg, returns a VA in the self-ref window. Never share a slot across src and dest in one copy.- Done when
read_phys/write_physcopy a known 4K pattern without an intermediate buffer.
- Done when
Expose VMCALL commands. Guest fills
vmcall_command_t(command.hpp):translate,copy_virt,write_phys,read_phys,dirbase. Host reads the command through the self-ref map using the caller dirbase, executes, writesresultback. Wire the demo through VDM lambdas so usermode can R/W physical and foreign CR3 virtual memory.- Done when the demo reads a known usermode buffer via
copy_virtand a known physical page viaread_phys.
- Done when the demo reads a known usermode buffer via
Only then add EPT. Bluepill’s original README lists EPT as a to-do. Identity-map + hooks live in
hypervisor-dev. Do not start EPT until steps 2–6 are green.- Done when this skill’s bring-up checklist is complete or the task has handed off to
hypervisor-dev/stealth-hypervisor.
- Done when this skill’s bring-up checklist is complete or the task has handed off to
VMCALL contract
enum vmcall_option { translate, copy_virt, write_phys, read_phys, dirbase }
translate: dirbase, virt_addr -> phys_addr
copy_virt: virt_src, dirbase_src, virt_dest, dirbase_dest, size
write_phys: virt_src, dirbase_src, phys_dest, size
read_phys: phys_src, dirbase_dest, virt_dest, size
dirbase: -> current guest CR3
present/result are host-written. Treat a missing result=true as a failed map, not a successful zero-fill.
Pair with
hypervisor-dev— EPT split, VMEXIT table, teardownstealth-hypervisor— CPUID/TSC/MSR hidehypervisor-memory-introspection— GVA→HPA analysis, MTF, VMFUNCwindbg-ttd— KDNET on the guest;#DB/INT3must stay guest-forwardedkernel-dev— WDK IRQL, NonPaged, manual-map hygiene
Verification
-
IA32_VMX_BASICrevision matches VMCS/VMXON header - Control fields survive high/low mask; no error 7
- First exit is not
0x80000021 - Host
#PF/#GP/#DESEH works in VMX-root - Guest
int 3still hits WinDbg - Two-PTE map copies a known pattern both directions
- Demo VMCALL
read_phys/copy_virtmatch a usermode ground truth