Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a93a73b
feat(symbols): resolve kernel globals from PDB
meowdiocre Jul 29, 2026
209362b
feat(firmware_hook): improve firmware table filtering and masking
meowdiocre Jul 30, 2026
caf52e6
feat(pnp_hook): add PnP device enumeration filtering
meowdiocre Jul 30, 2026
f067759
Merge pull request #79 from meowdiocre/development/pdb-symbol-resolver
hzqst Aug 5, 2026
6a10f55
Remove unneeded stuffs.
hzqst Aug 5, 2026
214c517
Add CLAUDE.md
hzqst Aug 5, 2026
62e86c2
update LICENSE
hzqst Aug 5, 2026
993d563
Add systeminformer as deps.
hzqst Aug 5, 2026
a3b724d
update CLAUDE.md
hzqst Aug 5, 2026
105bea2
feat(symbols): load kernel symbols from KPH dynamic data
hzqst Aug 5, 2026
39b09c3
fix(build): support Debug x64 dynamic data build
hzqst Aug 5, 2026
7225949
已完成 FindRunningKernel 改造:
hzqst Aug 5, 2026
45a33b4
remove bin.
hzqst Aug 5, 2026
f3430c9
update gitignore.
hzqst Aug 5, 2026
e9514df
VmLoaderLoadKernelSymbols 现同时支持 ntoskrnl.exe 和 ntkrla57.exe。
hzqst Aug 5, 2026
dfa1f49
add serena memories.
hzqst Aug 5, 2026
afe8183
rename FindRunningKernel.
hzqst Aug 5, 2026
fca6365
update README.md
hzqst Aug 5, 2026
1f6bfca
remove unneeded imgs.
hzqst Aug 5, 2026
0581009
update CLAUDE.md
hzqst Aug 5, 2026
ee8283e
update gitigore.
hzqst Aug 5, 2026
f41e3aa
Add install.ps1
hzqst Aug 5, 2026
76b5e59
Add VmLoaderCleanupRegistryEntries.
hzqst Aug 5, 2026
561f2ba
Add VMLOADER_DBG_PRINT.
hzqst Aug 5, 2026
b7a9e24
update gitignore.
hzqst Aug 5, 2026
05cecaf
update source driver name.
hzqst Aug 5, 2026
c6a99dd
update install.ps1
hzqst Aug 5, 2026
2e0556e
Add test_signing.ps1:
hzqst Aug 5, 2026
9e10111
已完成 x86 清理并补齐 ARM64 构建支持。
hzqst Aug 5, 2026
bb3cd20
update gitignore.
hzqst Aug 5, 2026
15738ad
add workflow/windows.yml
hzqst Aug 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
45 changes: 45 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# CLAUDE.md

This file provides guidance to coding agents working in this repository.

## Serena memories (progressive disclosure)

1. Activate this repository in Serena at agent startup, then use `list_memories` to discover the available memories by name. Do not load every memory by default.
2. Read `mem:core` first. It is the graph root for the project purpose, source map, driver lifecycle, dynamic-data trust model, and runtime constraints.
3. Follow only the references needed for the current task:
- `mem:tech_stack` — toolchain, dependency submodule, generated artifacts, and supported configurations.
- `mem:suggested_commands` — build, preparation, registry, test-signing, and diagnostic commands; read before executing project commands.
- `mem:conventions` — kernel coding conventions, hook lifecycle invariants, input validation, and safety constraints; read before changing code.
- `mem:task_completion` — build/runtime verification and handoff requirements; read before declaring implementation work complete.
- `mem:memory_maintenance` — memory graph structure, retention criteria, and maintenance actions; read when creating or updating memories.
4. If memories are missing, stale, or insufficient, inspect the relevant source files directly. Persist only stable, non-obvious project knowledge, and keep memory references accurate with Serena's `write_memory`, `edit_memory`, or `delete_memory` operations.

## Repository context (prefer memories)

The high-level architecture and invariants are maintained in `mem:core`; this file intentionally keeps only the navigation points needed for discovery:

- Project purpose, source map, driver lifecycle, and dynamic-data security model: `mem:core`.
- Toolchain, System Informer dependency, and generated outputs: `mem:tech_stack`.
- Build and runtime commands: `mem:suggested_commands`.
- Code and safety rules for kernel hooks and symbol handling: `mem:conventions`.
- Completion verification and handoff gate: `mem:task_completion`.

## Source-file entry points when memories are insufficient

- `README.md` — user-facing overview, build prerequisites, dynamic-data preparation, runtime loading, and limitations.
- `VmLoader/driver.cpp` — `DriverEntry` orchestration and reverse-order unload.
- `VmLoader/kernel_symbols.cpp/.h` — running-kernel discovery, signed/embedded KPH dynamic-data lookup, and PE/RVA validation.
- `VmLoader/firmware_hook.cpp/.h` — firmware provider handler replacement for FIRM, ACPI, and RSMB.
- `VmLoader/pnp_hook.cpp/.h` — user-mode registry callback for VMware PCI, USB, and HDAUDIO enumeration.
- `shared/symbol_config.h` — service parameter names shared by the driver and external tools.
- `VmLoader/PrepareDynData.ps1` — KPH manifest validation, dynamic-data generation/signing/verification, and artifact publication.
- `VmLoader/VmLoader.vcxproj` and `VmLoader.sln` — maintained build entry points.
- `thirdparty/systeminformer/` — System Informer git submodule providing KPH libraries and build/signing tools; avoid editing vendor or generated files unless the task explicitly requires it.

## Important rules

- Treat undocumented Windows kernel globals and firmware-provider layouts as build- and version-sensitive. Keep changes local and preserve rollback behavior.
- Treat kernel symbol data, PE metadata, signatures, file paths, and resolved RVAs as untrusted input; preserve the validation rules documented in `mem:core` and `mem:conventions`.
- The maintained targets are x64 Debug and Release. ARM64 configurations exist but are not validated for output.
- Test-signing mode is required for local driver loading; never commit private signing keys or generated secrets.
- Use the verification gate in `mem:task_completion` for implementation work. If required build, network, WDK, or disposable VM prerequisites are unavailable, report that limitation explicitly rather than claiming full validation.
2 changes: 2 additions & 0 deletions .codex/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ~/.codex/config.toml
project_doc_fallback_filenames = [".claude/CLAUDE.md"]
96 changes: 96 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Windows

on:
pull_request:
push:
tags:
- "v*"

permissions:
contents: read

jobs:
build:
name: ${{ matrix.platform }} ${{ matrix.configuration }}
runs-on: windows-2022
strategy:
fail-fast: false
matrix:
platform: [x64, ARM64]
configuration: [Debug, Release]

steps:
- name: Checkout source
uses: actions/checkout@v4
with:
submodules: recursive

- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2

- name: Build driver
shell: cmd
run: >-
msbuild VmLoader.sln /m /t:Rebuild
/p:Configuration=${{ matrix.configuration }}
/p:Platform=${{ matrix.platform }}

- name: Verify published runtime files
shell: pwsh
run: |
$requiredFiles = @(
'bin\vmloader.sys',
'bin\dyndata.bin',
'bin\dyndata.sig'
)
$missingFiles = $requiredFiles | Where-Object { -not (Test-Path -LiteralPath $_ -PathType Leaf) }
if ($missingFiles) {
throw "Missing published runtime files: $($missingFiles -join ', ')"
}

- name: Package bin directory
shell: pwsh
env:
BUILD_PLATFORM: ${{ matrix.platform }}
BUILD_CONFIGURATION: ${{ matrix.configuration }}
run: |
$platform = $env:BUILD_PLATFORM.ToLowerInvariant()
$configuration = $env:BUILD_CONFIGURATION.ToLowerInvariant()
$archiveName = "VmwareHardenedLoader-windows-$platform-$configuration.7z"
& 7z a $archiveName '.\bin\*' -r
if ($LASTEXITCODE -ne 0) {
throw "7-Zip failed with exit code $LASTEXITCODE."
}
if (-not (Test-Path -LiteralPath $archiveName -PathType Leaf)) {
throw "Expected archive was not created: $archiveName"
}

- name: Upload release archive
uses: actions/upload-artifact@v4
with:
name: VmwareHardenedLoader-windows-${{ matrix.platform }}-${{ matrix.configuration }}
path: VmwareHardenedLoader-windows-*.7z
if-no-files-found: error

release:
name: Publish release
needs: build
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
runs-on: windows-2022
permissions:
contents: write

steps:
- name: Download release archives
uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true

- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: VmwareHardenedLoader-${{ github.ref_name }}
files: release-assets/*.7z
fail_on_unmatched_files: true
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
ARM64/
x64/
x86/
bld/
Expand Down Expand Up @@ -328,3 +329,18 @@ ASALocalRun/

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Packaged artifacts
bin/*.sys
bin/*.bin
bin/*.sig

# Track the installer while keeping all other packaged artifacts ignored.
!bin/
bin/*
!bin/uninstall.ps1
!bin/uninstall.bat
!bin/install.ps1
!bin/install.bat
!bin/test_signing.ps1
!bin/test_signing.bat
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "thirdparty/systeminformer"]
path = thirdparty/systeminformer
url = https://github.com/hzqst/systeminformer/
1 change: 1 addition & 0 deletions .serena/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/cache
9 changes: 9 additions & 0 deletions .serena/memories/conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Code and safety conventions

- Kernel C++ uses SAL annotations, `#pragma once` headers, anonymous namespaces for file-local state, `VmLoader...` exported module APIs, `k...` constexpr constants, and `g_...` global hook state.
- Prefer explicit NTSTATUS propagation and early returns; zero/clear output structures on entry and clean pool allocations on every failure path. Existing helpers use tagged paged/nonpaged allocations and `PAGED_CODE()` where required.
- Hook lifecycle is stateful and reversible: acquire the firmware ERESOURCE around provider traversal/patching, cap list walks at 64 entries, preserve original handlers, and restore them on unload. PnP callback registration is guarded by a boolean and callback cookie.
- PnP filtering is intentionally user-mode-only (`ExGetPreviousMode() == UserMode`) and limited to enum branches ending in \\Enum\\PCI, \\Enum\\USB, or \\Enum\\HDAUDIO; VMware markers are VEN_15AD/VID_0E0F.
- Firmware filters mutate provider buffers in place; ACPI mutations must preserve table bounds and recompute checksum. Keep replacement strings equal length.
- Treat kernel symbol inputs as hostile: validate bounded PE headers, exact machine/timestamp/image-size identity, dynamic-data version/fields, file/signature size limits, local non-network path normalization, and writable + non-executable RVAs before dereference.
- Avoid broad refactors around undocumented kernel globals or SYSTEM_FIRMWARE_TABLE_HANDLER layout; Windows updates can invalidate assumptions. Keep changes local and preserve rollback behavior.
16 changes: 16 additions & 0 deletions .serena/memories/core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Core project map

- Purpose: VMwareHardenedLoader-ng is a Windows WDM kernel driver that filters selected VMware firmware/PnP observations inside Windows guests.
- Source map:
- `VmLoader/driver.cpp`: DriverEntry orchestration and reverse-order unload.
- `VmLoader/kernel_symbols.cpp/.h`: running-kernel discovery, signed/embedded KPH dynamic-data lookup, PE/RVA validation.
- `VmLoader/firmware_hook.cpp/.h`: firmware provider handler replacement for FIRM, ACPI, and RSMB.
- `VmLoader/pnp_hook.cpp/.h`: user-mode Configuration Manager registry callback for VMware PCI/USB/HDAUDIO enumeration.
- `shared/symbol_config.h`: service Parameters value names; currently only DynDataDirectory.
- `VmLoader/PrepareDynData.ps1`: downloads/validates KPH XML, builds CustomBuildTool, generates/signs/verifies v20 dynamic data, emits public-key header and bin artifacts.
- `VmLoader/VmLoader.vcxproj`, `VmLoader.sln`: maintained build entrypoints.
- `thirdparty/systeminformer`: git submodule providing kphlib and CustomBuildTool/CustomSignTool.
- DriverEntry invariant: load kernel symbols -> install firmware hooks -> install PnP hooks; failure stops later stages and rolls back firmware hooks if PnP registration fails. Unload removes PnP then firmware hooks.
- Dynamic-data invariant: external dyndata.bin/dyndata.sig is accepted only after embedded public-key signature verification, size limits, exact kernel identity match, required firmware fields, and writable/non-executable/distinct RVA checks; embedded v20 data is fallback.
- Runtime constraints: undocumented Windows kernel globals and firmware-provider layout may change across updates; x64 and ARM64 Debug/Release are maintained build targets, but ARM64 runtime behavior still requires validation on each target Windows build.
- Read `mem:tech_stack` for toolchain/dependency details, `mem:conventions` for code and safety invariants, `mem:suggested_commands` for Windows commands, and `mem:task_completion` for completion verification.
33 changes: 33 additions & 0 deletions .serena/memories/memory_maintenance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Memory Maintenance

## Discovery Model

- Core principle: progressive discovery through references, building a graph of memories.
- Initially, agents are provided with the list of all memories (names only).
- Agents should read `mem:core` as the top-level entry point (graph root).
This memory should contain references to other memories covering major project domains.
The referenced memories shall, in turn, shall contain references to even more specific memories, and so on.
The depth of the graph shall depend on the project complexity.
- Use topics/folders to group related memories in order to make the content structure explicit.
Folders can mirror project structure (e.g. modules like frontend/backend) or topics like debugging, architecture, etc.
- Memory references must use a mem: prefix inside backticks, e.g. `mem:frontend/core`.
The surrounding text should clearly indicate when to read the memory/which content to expect.
The text should provide more precise guidance than the memory name alone,
i.e. avoid a reference like "frontend debugging: `mem:frontend/debugging` and instead make clear which aspects of frontend debugging are covered.
- Memories themselves should not contain information about when to read them; this is the responsibility of the referring memory.

## Style

Dense agent notes, not prose docs. Prefer invariants, terse bullets.
Avoid obvious context, rationale, and examples unless they prevent likely mistakes.
Keep guidance durable and generalizable, not task-local.

## Add/update threshold

Add or update memories only with stable, non-obvious project conventions that avoid complex rediscovery in the future.
Do not add: quick-read facts; generic language/framework knowledge; one-off task notes; volatile line-level details; behavior likely to change soon.

## Maintenance Actions

- Renaming memories: References are updated automatically if handled via Serena's memory rename tool.
- Checking for stale memories (e.g. after deletion): Call `serena memories check` for a report.
12 changes: 12 additions & 0 deletions .serena/memories/suggested_commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Windows commands

- Initialize dependency submodule from repository root: `git submodule update --init --recursive`.
- Build from a VS 2022 Developer Command Prompt with WDK:
- Release x64: `msbuild VmLoader.sln /m /t:Rebuild /p:Configuration=Release /p:Platform=x64`
- Debug x64: `msbuild VmLoader.sln /m /t:Rebuild /p:Configuration=Debug /p:Platform=x64`
- Release ARM64: `msbuild VmLoader.sln /m /t:Rebuild /p:Configuration=Release /p:Platform=ARM64`
- Debug ARM64: `msbuild VmLoader.sln /m /t:Rebuild /p:Configuration=Debug /p:Platform=ARM64`
- The x64 and ARM64 MSBuild targets invoke `VmLoader/PrepareDynData.ps1` before C/C++ compilation; do not assume a cached manifest is acceptable. It downloads the latest KPH XML, validates it, builds the generator, signs/verifies generated data, and publishes artifacts.
- Optional external-data configuration (elevated Command Prompt): `reg add "HKLM\\SYSTEM\\CurrentControlSet\\Services\\vmloader\\Parameters" /v DynDataDirectory /t REG_SZ /d "C:\\VmLoader" /f`; directory must contain matching `dyndata.bin` and `dyndata.sig`.
- Test VM boot setting (elevated): `bcdedit /set testsigning on`; reboot, sign `bin\\vmloader.sys` with a trusted test certificate, and disable later with `bcdedit /set testsigning off`.
- Inspect runtime diagnostics with DbgView or a kernel debugger; driver messages use the `VmLoader:` prefix and report NTSTATUS values.
8 changes: 8 additions & 0 deletions .serena/memories/task_completion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Completion and verification gate

- For driver/source changes, run the relevant x64 and/or ARM64 rebuild from a VS 2022 Developer Command Prompt with WDK; prefer Release for final validation and Debug when diagnostics matter.
- A successful preparation phase must show validated firmware-record counts, generated KPH v20 layout, and successful signature verification before compilation proceeds.
- Confirm published artifacts when build succeeds: x64 under `bin\\` and ARM64 under `bin\\ARM64\\`, each containing `vmloader.sys`, `dyndata.bin`, and `dyndata.sig`; the driver remains unsigned by the project and needs test/production signing before loading.
- There is no root automated test suite. For runtime-sensitive changes, inspect `VmLoader:` DbgView/kernel-debugger output and exercise the affected firmware/PnP query path in a disposable test VM.
- If build prerequisites, network/NuGet access, WDK, or a usable Windows kernel test VM are unavailable, report that limitation explicitly; do not claim the change is fully validated.
- Before handoff, review the diff for unrelated generated files/secrets. Keep VmLoader-specific RSA key files under the ignored System Informer Resources directory and never commit the private key.
8 changes: 8 additions & 0 deletions .serena/memories/tech_stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Toolchain and dependencies

- Language/runtime: C++ WDM kernel driver; Windows 10+ guest target with x64 and ARM64 build support. ARM64 runtime behavior depends on undocumented kernel layouts and requires target-build validation.
- IDE/build: Visual Studio 2022 with Windows Driver Kit 10; MSBuild solution `VmLoader.sln`; maintained configurations `Debug|x64`, `Release|x64`, `Debug|ARM64`, and `Release|ARM64`.
- Dynamic-data preparation: Windows PowerShell script plus .NET SDK 9+ `dotnet msbuild` for System Informer's `CustomBuildTool`; HTTPS access to GitHub and possible NuGet restore are required.
- Third-party dependency: `thirdparty/systeminformer` git submodule from `https://github.com/hzqst/systeminformer/`; its kphlib provides KPH dynamic-data headers/sources and signing tools.
- Generated/runtime artifacts: intermediate public-key header; `bin/vmloader.sys`, `bin/dyndata.bin`, and `bin/dyndata.sig`.
- No test framework or automated unit-test target is present in the root solution; verification is build plus targeted runtime/kernel-debug checks.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 hzqst
Copyright (c) 2018 to 2026 hzqst

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Loading
Loading