Skip to content

Repository files navigation

KNHV

🚧 Work in progress

IDE Platform Standard Target

KanoHypervisor is a Windows x64 kernel driver for Intel VT-x research and bring-up. It is intended for an isolated test installation with a kernel debugger. Current status: research and bring-up; it is not a production hypervisor.

Validation profile

The primary validation profile is an isolated reference target:

  • Windows 11 25H2, x64
  • Intel Core i7-14700KF
  • a recovery snapshot and an attached kernel debugger
  • no production, safety-critical, or personal-data workloads

Host-only contract tests can run on other supported Windows x64 systems. VMX, service, and signature results must be collected on the isolated target. The compile host is not a runtime validation target; building an artifact there does not establish driver, HyperDbg, nested-VMX, passthrough, or performance compatibility.

Scope

  • Intel VT-x late launch and VM-exit state handling
  • fail-closed capability checks
  • orderly multi-processor teardown with bounded retries
  • quarantine when VMX ownership cannot be proven to be released
  • versioned provider and session ABI for a future BootL0 interposer
  • pure software VMCS12/nested-VMX, VMCS shadow, EPT policy, and TSC/QPC contract models
  • a versioned VMX control-capability and per-processor consistency model for target-side validation
  • an isolated KNHV-NestedTest.sys contract-test driver
  • a read-only Windows Hypervisor Platform capability broker
  • no physical BootL0 handoff, EPT/VMCS02 acceleration, device passthrough, or production support

Repository layout

Path Responsibility
src/core Driver entry, lifecycle facade, and shared runtime state
src/vmx Feature gates, VMCS setup, launch, exits, diagnostics, stop paths, and CPU capability model
src/include Public, private, and logging contracts
src/asm VMX entry, instruction wrappers, launch, and restore routines
src/nested VMCS12, VMCS shadow, VMX instruction, address, and exit models
src/ept Pure EPTP, nested mapping, generation, and debug-lease policy model
src/time Fixed-point TSC transform, calibration, and drift contract model
src/iommu Device, DMA-domain, and quarantine contract model
src/exit Fail-closed VM-exit policy and routing model
src/interrupt Bounded injection and posted-interrupt contract model
src/whp WHP partition, mapping, vCPU, and exit lifecycle model
src/broker Read-only WHP capability probe executable
src/provider Capability-gated provider selection
src/validation Versioned target evidence, wire codec, and release-gate model
src/control Shared secure WDM control-device implementation
src/test_driver Independent nested contract-test driver entry point
drivers Separate INF packages for the two control services
tests Source, ABI, artifact, and opt-in runtime checks
tools Build, signing, certificate, and TESTSIGNING helpers

The C++ and MASM frame layouts share src/asm/vmx_asm.inc and are guarded by static assertions and contract tests. Change both sides together when editing an offset or calling convention.

Requirements

  • Windows 11 25H2 x64 for the primary validation profile
  • Visual Studio x64 C++ tools and MASM
  • a Windows SDK and a matching Windows Driver Kit (WDK)
  • CMake 3.23 or newer and Ninja

ntifs.h is provided by the WDK, not by the Windows SDK alone. Open the repository from a Visual Studio Developer PowerShell. If more than one WDK is installed, pass its root with -WdkRoot or -DWDK_CONTENT_ROOT.

To record the target before a hardware test, use these read-only commands:

Get-CimInstance Win32_OperatingSystem |
  Select-Object Caption, Version, BuildNumber
Get-CimInstance Win32_Processor |
  Select-Object -First 1 Name, NumberOfCores, NumberOfLogicalProcessors

Configure and build

Run these commands from the repository root in a Developer PowerShell:

$env:VSLANG = "1033"
cmake --preset vscode-debug
cmake --build --preset vscode-debug --parallel 4

For an optimized image:

$env:VSLANG = "1033"
cmake --preset vscode-release
cmake --build --preset vscode-release --parallel 4

VSLANG=1033 requests the MSVC message language where that resource is installed; CMake also detects the compiler's /showIncludes prefix. It does not change the language of the driver or the test binaries.

The output directory is build/vscode/<Configuration>/. Generated runtime images are classified by kind, while linker PDB files stay in the configuration root:

  • bin/KNHV_ContractTests.exe
  • bin/KNHV_NestedProbe.exe
  • bin/KNHV_NativeVmxProbe.exe
  • bin/KNHV_NativeLikeBench.exe
  • bin/KNHV_VmxExitBench.exe
  • bin/KNHV_TscQpcBench.exe
  • bin/KNHV_EptHookBench.exe
  • bin/KNHV_DeviceIoBench.exe
  • bin/KNHV_Preflight.exe
  • bin/KNHV_CpuMatrix.exe
  • bin/KNHV_WHPBroker.exe
  • bin/KNHV_EvidenceTool.exe
  • sys/KNHV.sys
  • sys/KNHV-Control.sys
  • sys/KNHV-NestedTest.sys
  • KNHV*.pdb

CMakeFiles/ and Testing/ remain CMake's internal build directories. The native self-test source is HV_PROBE_TESTER/native_vmx_probe.cpp.

The two auxiliary SYS files expose only the versioned control contract. They do not execute physical VMXON; the current KNHV.sys remains the native, late-launch research baseline. A physical top-level KNHV L0 requires a separately validated boot-time handoff and is outside the current release profile.

KNHV-NestedTest.sys advertises a deliberately marked kFlagSyntheticSnapshot so the host-only nested model can be exercised. That flag is laboratory-only: it is not evidence of a BootL0 handoff, VMCS02/EPT hardware, WHP integration, or transparent passthrough. The current control contract keeps VirtualizationReady=false for that synthetic path while still allowing the model IOCTLs to run. It also uses a bounded session table, a generation key, and the creating file-object binding. It still does not verify a production image manifest/signature or provide a production broker identity. Do not deploy these auxiliary images as a production hypervisor or as a security boundary.

The control device also exposes an additive ABI v2 capability and lease contract. IOCTL_KNHV_QUERY_CAPS_V2 is read-only; the acquire and release lease calls require a versioned session key, a matching generation, and known feature and policy bits. A hardware lease is returned only for a verified KNHV Boot L0 owner. The nested test image can return a lease marked kLeaseFlagSynthetic; that lease is a laboratory model and never authorizes physical VMX, EPT, IOMMU, or DMA work. Unknown versions, truncated buffers, stale generations, and unknown flags are rejected.

The CMake Tools integration exports compile_commands.json with the project headers and WDK km include directory. After changing the WDK or toolchain, run CMake: Delete Cache and Reconfigure. If IntelliSense still reports a missing ntifs.h, reset the C/C++ IntelliSense database and reopen the source file under src/vmx.

Tests

The default suite is host-only. It does not execute VMX instructions, load a driver, change TESTSIGNING, or start a service:

.\build\vscode\Debug\bin\KNHV_ContractTests.exe --root .
ctest --test-dir build\vscode\Debug --output-on-failure

The host-only suite includes provider-selection, BootL0 ownership-state, VMCS12/nested-instruction, EPT mapping/generation, debug-lease, and fixed-point TSC/QPC model tests. It does not load either auxiliary driver, change TESTSIGNING, or execute VMX instructions.

After the signed KNHV-NestedTest.sys test driver is running on an isolated x64 Windows target, the dedicated probe can validate its public synthetic nested-model device contract:

.\build\vscode\Release\bin\KNHV_NestedProbe.exe --caps-only
.\build\vscode\Release\bin\KNHV_NestedProbe.exe

The full probe opens \\.\KNHVNestedTest, registers the known laboratory provider, and exercises VMXON, VMCS12 setup, VMLAUNCH, reflected L2 exits, VMRESUME, VMXOFF, and session release. It does not execute physical VMX instructions or verify a physical BootL0/VMCS02/EPT02 implementation.

On an isolated target where KNHV.sys is already running, the native VMX self-test is available as:

.\build\vscode\Release\bin\KNHV_NativeVmxProbe.exe

The native probe must not be used as a nested or coexistence test. It checks only the existing KNHV VM-exit path and is intentionally separate from the synthetic nested-model probe.

The benchmark executables are host-only diagnostic tools. They use the common knhv-bench-1 JSON schema; a .csv output contains sample columns only. The five tools cover native-like CPU and memory work, TSC/QPC clock sampling, synthetic VM-exit accounting, synthetic EPT-hook accounting, and a virtual device-I/O queue. They do not execute physical VMX instructions, access PCI devices, or enable DMA.

For a local baseline, write results to a directory owned by the caller:

.\build\vscode\Release\bin\KNHV_NativeLikeBench.exe `
  --mode baseline --workload cpu,mem --duration-ms 1000 --repeat 3 `
  --out results\native_like.json

tools/Run-Benchmarks.ps1 runs the host-only suite and records commands, provenance, hashes, and result files in the output directory supplied by the caller. The native-l0 and nested-l1 modes are capability-gated and fail closed when a verified provider, owner, or nested capability is unavailable. The device-I/O tool accepts only its explicit virtual profile; it never detaches, resets, or transfers data to a physical device. Comparison mode requires matching workload, scope, configuration, and host provenance before reporting a result.

KNHV_Preflight.exe is the read-only gate for a future Native L0 target. It reports CPUID, topology, firmware-table, Secure Boot, DeviceGuard, WHP, service, and provider observations in knhv-preflight-1 JSON. Unknown privileged state is retained as unknown and blocks a native-l0 profile; the tool never changes boot policy, loads a driver, or executes VMX instructions.

The owner_observation and owner_gate fields record the selected action, reason, owner, and generation. Only a complete, active KNHV Boot L0 handoff can produce acquire-native; unknown or conflicting evidence remains blocked.

KNHV_CpuMatrix.exe is a separate read-only target-machine probe. It temporarily binds one user-mode thread to each active logical processor, records the observable CPUID feature set, restores the original affinity, and emits a knhv-cpu-matrix-1 JSON file. A pass requires a complete uniform matrix with VMX and Invariant TSC; a blocked result is expected when a hypervisor owns VMX, affinity cannot be restored, or processors expose different features. VMX control MSRs, EPT/VPID, and IOMMU are reported as unknown because they need privileged target-side validation.

KNHV_EvidenceTool.exe is a host-only encoder and gate reader for the target evidence contract. --emit-synthetic creates a clearly marked laboratory package, --validate checks its fixed wire header and SHA-256 envelope digest, and --gate evaluates profile, stage, generation, and required flags. The tool never turns a synthetic package into hardware evidence. --verify-signature uses Windows WinVerifyTrust with revocation checks disabled and cache-only URL retrieval. It reports trusted, not-signed, untrusted, or private-test-root without changing the certificate store or setting SignatureVerified in a manifest. A private test root is accepted only with the explicit --allow-test-root option and remains unsuitable as a production signing result.

Example offline flow:

.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --emit-synthetic evidence.bin --out evidence-emit.json
.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --validate evidence.bin --out evidence-validate.json
.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --gate evidence.bin --profile synthetic-lab --stage release
.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --verify-signature .\build\vscode\Release\sys\KNHV.sys `
  --out driver-signature.json

The pure knhv_vmx_capability contract is the next validation boundary for a privileged target collector. It normalizes VMX control MSR masks, checks the primary/secondary/tertiary dependency rules, and rejects a mixed per-CPU EPT, VPID, or feature-control profile. The model contains no MSR or VMX instruction; the target collector must provide the raw snapshots and retain the per-CPU evidence.

The knhv_owner_observation contract provides an owner observation gate and applies the same fail-closed rule to ownership evidence. It combines CPUID hypervisor state, Windows hypervisor and VBS/HVCI observations, provider state, boot-handoff evidence, and a generation counter. Only an active KNHV Boot L0 with complete handoff evidence can return acquire-native; an external owner, WHP owner, synthetic owner, or unknown state receives an explicit action and reason. The model does not claim that HyperDbg or another hypervisor can share physical VMX ownership, and it never executes VMX or MSR instructions.

The knhv_target_evidence contract defines a versioned target evidence manifest for future hardware collection and release gates. It binds the chosen profile, stage, owner state, CPU coverage, artifact and PDB hashes, generation, signature state, time/telemetry status, recovery readiness, and device or performance proof. A gate accepts a manifest only when its requested profile, stage, generation, verdict, and required evidence flags all match. The current model validates supplied evidence only; it does not collect privileged state or claim that a Native L0 hardware validation has completed.

The manifest writer is the host-only boundary that turns an already collected snapshot into the fixed manifest. It checks the snapshot's version, profile, stage, owner generation, source-clean observation, and signature result before writing it. Synthetic snapshots require an explicit laboratory flag and cannot carry hardware evidence. Native Intel capability and release profiles require target hardware evidence and a trusted signature; the writer never reads VMX, VT-d, DMA, device, or certificate-store state itself.

The target snapshot adapter is the boundary before the writer. It accepts a versioned snapshot plus raw per-processor CPU and VMX samples, recomputes both matrices, checks owner and generation consistency, and forwards only a valid candidate to the writer. The adapter is host-only; privileged collection and hardware execution remain explicit target-side operations.

The collector binding contract is the provenance boundary after package verification. A target-side collector supplies its identity, capture id, generation, timestamp window, sample counts, package digest, artifact hash, and signature result. The host validator compares those fields with the decoded snapshot and fails closed on stale, mixed, or incomplete evidence. It does not make an unsigned record trusted and does not collect privileged state itself. GetTargetEvidenceSnapshotPackageDigest exposes the digest only after the wire header and stored SHA-256 have both been verified, so callers do not need to reimplement package offsets.

For offline transport, KNHV_EvidenceTool.exe can encode the approved snapshot and its raw samples into a bounded, SHA-256 protected package, then decode and re-run the same validation before materializing a manifest:

.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --emit-synthetic-snapshot snapshot.bin --out snapshot-emit.json
.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --validate-snapshot snapshot.bin --out snapshot-validate.json

After validation, the same executable can apply the profile, stage, and generation gate to the decoded snapshot in one operation:

.\build\vscode\Release\bin\KNHV_EvidenceTool.exe `
  --gate-snapshot snapshot.bin --profile synthetic-lab --stage release `
  --expected-generation 1 --out snapshot-gate.json

A blocked or malformed package returns a nonzero exit code and never becomes a release manifest. This command evaluates supplied evidence only; it does not acquire VMX ownership, start a driver, or touch devices.

The synthetic command is a laboratory fixture only. A target collector must provide the real per-processor samples and a matching generation; malformed, truncated, or tampered packages are rejected before a manifest is written.

Run it once on the isolated validation target after copying the matching build:

.\build\vscode\Release\bin\KNHV_CpuMatrix.exe `
  --out results\cpu_matrix.json

KNHV_WHPBroker.exe dynamically loads the system WinHvPlatform.dll and queries WHvGetCapability to emit a knhv-whp-probe-1 JSON snapshot. It does not create a partition, map guest memory, create a vCPU, or execute a vCPU. --run is intentionally blocked until a separately validated runner exists:

.\build\vscode\Release\bin\KNHV_WHPBroker.exe --caps-only `
  --out results\whp_capabilities.json

To validate a built SYS and its matching PDB:

.\build\vscode\Debug\bin\KNHV_ContractTests.exe `
  --root . `
  --driver .\build\vscode\Debug\sys\KNHV.sys

The following checks are explicit opt-ins and belong only on the isolated Windows 11 25H2 / i7-14700KF target:

.\build\vscode\Debug\bin\KNHV_ContractTests.exe --root . --hardware

.\build\vscode\Debug\bin\KNHV_ContractTests.exe `
  --root . `
  --driver .\build\vscode\Debug\sys\KNHV.sys `
  --signature `
  --allow-test-root

.\build\vscode\Debug\bin\KNHV_ContractTests.exe `
  --root . `
  --driver .\build\vscode\Debug\sys\KNHV.sys `
  --runtime --start --stop

--signature expects a test-signed image. --runtime requires a prepared service, a kernel debugger, and a recovery path. The test only stops a service that it started itself.

Deterministic fault injection

Fault injection is disabled in normal builds. Use a separate build directory to validate a launch-rollback configuration:

$env:VSLANG = "1033"
cmake -S . -B build\vscode\FaultDebug -G Ninja `
  -DCMAKE_BUILD_TYPE=Debug `
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON `
  -DWDK_WINVER=0x0A00 `
  -DKNHV_BUILD_TESTS=ON `
  -DKNHV_FAULT_INJECTION=ON `
  -DKNHV_TEST_FAIL_CPU=0 `
  -DKNHV_TEST_FAIL_STAGE=8 `
  -DKNHV_ARTIFACT_ROOT=build\vscode\FaultDebug
cmake --build build\vscode\FaultDebug --parallel 4
.\build\vscode\FaultDebug\bin\KNHV_ContractTests.exe `
  --root . `
  --driver .\build\vscode\FaultDebug\sys\KNHV.sys

This command validates the fault-injection build and its artifact contract; it does not load the driver or trigger a VMX launch.

KNHV_TEST_FAIL_CPU selects the logical processor and KNHV_TEST_FAIL_STAGE selects a bounded stage. These hooks request a controlled rollback; they do not emulate arbitrary hardware failures. To exercise one, sign and register this separate SYS only on the isolated target, attach KD, and retain the rollback log. The normal --runtime --start --stop check expects a successful launch, so it is not the expected-result check for an intentionally injected launch failure.

Tool scripts

All scripts are intended to be run from the repository root. They use the installed Visual Studio and WDK rather than hard-coded compiler paths.

Script Purpose State changes
tools/Build-Driver.ps1 Discover VS/WDK, configure, and build unsigned SYS/EXE/PDB artifacts Writes only the selected build directory using sys/, bin/, and the root for linker PDBs
tools/Build-And-Sign-Driver.ps1 Build, create or reuse a local test certificate, then sign the SYS Writes certs/, may install test certificates, and changes the SYS
tools/Generate-Test-Certificate.ps1 Create a private Root CA and kernel-code-signing leaf certificate Writes certs/ and may update certificate stores
tools/Sign-Driver.ps1 Sign an existing SYS and verify Authenticode plus kernel policy Changes the specified SYS; requires signtool.exe and a certificate
tools/Set-TestSigning.ps1 Read or change Windows TESTSIGNING state -Status is read-only; -Enable and -Disable change BCD and require a reboot
tools/Run-Benchmarks.ps1 Run the host-only benchmark suite and write a reproducibility manifest Writes only the caller-selected output directory

Build helper

.\tools\Build-Driver.ps1 -Configuration Debug
.\tools\Build-Driver.ps1 -Configuration Release
.\tools\Build-Driver.ps1 -Configuration Debug -ConfigureOnly

Use -WdkRoot 'C:\Program Files (x86)\Windows Kits\10' when automatic WDK selection is not appropriate.

The legacy standalone probe entry point remains available from an x64 Native Tools Command Prompt:

cd HV_PROBE_TESTER
build_msvc.bat

It writes build\standalone\bin\KNHV_NativeVmxProbe.exe and its PDB instead of placing a binary beside the source file.

Test certificate and signing

Signing is never enabled by the CMake presets. For an isolated test target:

.\tools\Build-And-Sign-Driver.ps1 -Configuration Debug

The generated private key and password stay under the ignored certs/ directory. Do not commit them. -Recreate on Generate-Test-Certificate.ps1 replaces the local test chain and should only be used when the existing chain is intentionally being retired.

For an existing certificate and SYS, the lower-level command is:

.\tools\Sign-Driver.ps1 `
  -DriverPath .\build\vscode\Debug\sys\KNHV.sys `
  -Certificate .\certs\KNHV_test.pfx `
  -Password '<test-password>' `
  -AllowUntrustedTestCertificate

Do not put a real password in source control or shell history. A production release needs the platform's approved kernel-code-signing process; a private test root is not production trust.

TESTSIGNING

.\tools\Set-TestSigning.ps1 -Status

Only on the isolated test installation, from an elevated PowerShell:

.\tools\Set-TestSigning.ps1 -Enable
# reboot before loading a test-signed driver
.\tools\Set-TestSigning.ps1 -Disable
# reboot again after disabling test mode

Secure Boot, enterprise policy, or firmware settings may reject TESTSIGNING. Do not change it on a production machine.

Acknowledgements

The implementation was informed by the Intel Software Developer's Manual and public research projects such as HyperDbg.

License

MIT License. See LICENSE.

About

WIP - Type-2 Hypervisor implementation for Intel Processors based on VT-x technology. (Demo)

Topics

Resources

Stars

20 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages