feat(tests): add documentation and build script for Windows kernel driver testing

This commit is contained in:
Alexandr Stelnykovych 2026-03-02 17:08:47 +02:00
parent 9e8acb2d25
commit def9d3407e
3 changed files with 373 additions and 0 deletions

View file

@ -0,0 +1,215 @@
# Building and Running Driver with Debug Logging
## Driver Signing Requirement
Windows requires **all kernel drivers to be signed**. Test signing provides a free alternative to expensive production code signing certificates for development and testing purposes.
## Important: Debug Builds Are Disabled
⚠️ **The driver cannot be compiled in debug mode.** The code contains a compile-time check (`compile_error!`) that prevents debug builds due to potential optimization-related issues and inconsistent compiler behavior between debug and release modes.
However, you can still enable verbose logging in release builds by changing the log level.
## Prerequisites
Already documented in [main README](../README.md), but quick recap:
1. **Visual Studio 2022** with C++ and Windows SDK
2. **Windows Driver Kit (WDK)** installed
3. **Rust toolchain** installed
4. **Test signing enabled** (see below)
## Step 1: Enable Test Signing (One-time Setup)
⚠️ **SECURITY WARNING**: Test signing reduces system security by allowing any locally-generated test certificate to load kernel drivers. **Strongly recommended to use a VM or dedicated test machine**. See "Disabling Test Signing" section below to restore security when done testing.
### Create Test Certificate
Open **PowerShell as Administrator**:
```powershell
# Create a self-signed certificate for driver testing
MakeCert -r -pe -ss PrivateCertStore -n "CN=DriverTestCert" DriverTestCert.cer
# Install the certificate to Trusted Root
CertMgr /add DriverTestCert.cer /s /r localMachine root
# Install to Trusted Publishers (needed for driver installation)
CertMgr /add DriverTestCert.cer /s /r localMachine trustedpublisher
```
### Enable Test Signing Mode
```powershell
# Enable test signing
Bcdedit.exe -set TESTSIGNING ON
# Restart required!
Restart-Computer
```
After restart, you should see **"Test Mode"** watermark in the corner of your screen.
### Verify Test Signing is Enabled
```powershell
bcdedit /enum | Select-String testsigning
# Should show: testsigning Yes
```
## Step 2: Enable Debug Logging in Driver
To see verbose logs from the driver, edit the log level before building.
**Edit `driver/src/logger.rs`:**
```rust
// Change line 8 from:
pub const LOG_LEVEL: u8 = Severity::Warning as u8;
// To one of:
pub const LOG_LEVEL: u8 = Severity::Debug as u8; // Recommended for testing
// pub const LOG_LEVEL: u8 = Severity::Info as u8; // Less verbose
// pub const LOG_LEVEL: u8 = Severity::Trace as u8; // Most verbose
```
For testing, `Debug` level is recommended.
## Step 3: Build Driver in Release Mode
Navigate to the driver directory:
```powershell
cd D:\Projects\Portmaster\portmaster\windows_kext\driver
# Build in release mode (only mode supported)
cargo build --release --target x86_64-pc-windows-msvc
# Output: driver/target/x86_64-pc-windows-msvc/release/driver.lib
```
**Note:** Debug builds (`cargo build` without `--release`) will fail with a compile error by design.
## Step 4: Link the Driver
Copy the `.lib` file to the root directory:
```powershell
cd D:\Projects\Portmaster\portmaster\windows_kext
Copy-Item driver/target/x86_64-pc-windows-msvc/release/driver.lib . -Force
```
Run the linker script:
```powershell
.\link-dev.ps1
```
This creates `driver.sys` in the current directory.
## Step 5: Sign the Driver
## Step 5: Sign the Driver
```powershell
cd D:\Projects\Portmaster\portmaster\windows_kext
# Sign the driver
SignTool sign /v /s PrivateCertStore /n DriverTestCert driver.sys
```
Verify signature:
```powershell
SignTool verify /v /pa driver.sys
```
You should see: **"Successfully verified: driver.sys"**
## Step 6: View Driver Logs
### Ring Buffer Logs (Recommended)
These logs come through the `GetLogs` command.
### Kernel Debugger Output (Not Available in Release)
The `wdk::dbg!()`, `wdk::info!()`, and `wdk::err!()` macros only work in debug builds, which are disabled for this driver. These would output to tools like DebugView via `DbgPrint`, but since debug builds are not allowed, this logging path is not available.
**Use the ring buffer logs** (captured by `dbg!`, `info!`, `warn!`, `err!` macros) for all debugging.
## Common Issues
### "The hash for the file is not present in the specified catalog file"
**Solution**: Your driver isn't signed or the certificate isn't trusted.
```powershell
# Re-sign the driver
SignTool sign /v /s PrivateCertStore /n DriverTestCert driver.sys
```
### "Windows cannot verify the digital signature"
**Solution**: Test signing not enabled or certificate not in Trusted Root.
```powershell
# Check test signing
bcdedit /enum | Select-String testsigning
# Reinstall certificate if needed
CertMgr /add DriverTestCert.cer /s /r localMachine root
```
### "Service marked for deletion"
**Solution**: Manually clean up:
```powershell
sc stop PortmasterKext
sc delete PortmasterKext
# Wait a few seconds
# Then try starting again
```
### "Access is denied" when creating service
**Solution**: Run as Administrator.
### No debug output (`GetLogs` command)
**Solution**:
1. Make sure you edited `driver/src/logger.rs` to set `LOG_LEVEL = Severity::Debug`
2. Rebuild the driver in **release mode** (`cargo build --release`)
3. The driver must be actively running and processing connections to generate logs
4. Default log level (`Warning`) only shows errors, not normal operations
## Quick Build & Test Cycle
```powershell
# 1. (Optional) Enable debug logging - edit driver/src/logger.rs first
# 2. Build driver in release mode
cd D:\Projects\Portmaster\portmaster\windows_kext\driver
cargo build --release
# 3. Link and sign
cd ..
Copy-Item driver/target/x86_64-pc-windows-msvc/release/driver.lib . -Force
.\link-dev.ps1
SignTool sign /v /s PrivateCertStore /n DriverTestCert driver.sys
# 4. Test (in playground, as Administrator)
```
## Disabling Test Signing (When Done Testing)
⚠️ **IMPORTANT**: When finished testing, disable test signing to restore system security.
```powershell
# Run as Administrator
Bcdedit.exe -set TESTSIGNING OFF
# Restart required for changes to take effect
Restart-Computer
```
After restart, the "Test Mode" watermark will disappear and the system will no longer accept test-signed drivers. This restores normal kernel driver security enforcement.Production vs Test Signing

View file

@ -0,0 +1,13 @@
# Test Directory
> ⚠️ **Notice**: This folder and its contents were primarily generated with the assistance of AI and may contain errors or inaccuracies. They are intended solely for local testing and development and must not be used in production.
## Contents
- `build_test.ps1` - Script to build the test-signed driver
- `_out/` - Output directory for built test driver
- `_testcert/` - Test certificates for driver signing
## Purpose
This directory contains tools and utilities for testing the Portmaster Windows kernel driver during development. These are developer tools only and are not part of the production build or release process.

View file

@ -0,0 +1,145 @@
# Build and Sign Test Driver Script
# Must be run from Developer PowerShell for Visual Studio
$ErrorActionPreference = "Stop"
# Get script directory and set paths
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$rootDir = Split-Path -Parent $scriptDir
$driverDir = Join-Path $rootDir "driver"
$certPath = Join-Path $rootDir "test\_testcert\DriverTestCert.cer"
$outDir = Join-Path $scriptDir "_out"
# Create output directory if it doesn't exist
if (-not (Test-Path $outDir)) {
New-Item -ItemType Directory -Path $outDir -Force | Out-Null
}
Write-Host "=================================================" -ForegroundColor Cyan
Write-Host " Building and Signing Test Driver" -ForegroundColor Cyan
Write-Host "=================================================" -ForegroundColor Cyan
Write-Host ""
# Verify we are in the correct directory
if (-not (Test-Path $driverDir)) {
Write-Host "ERROR: Driver directory not found at: $driverDir" -ForegroundColor Red
Write-Host "Please run this script from the windows_kext root directory or ensure paths are correct." -ForegroundColor Red
exit 1
}
# Verify certificate exists
if (-not (Test-Path $certPath)) {
Write-Host "ERROR: Certificate not found at: $certPath" -ForegroundColor Red
Write-Host "Please create the test certificate first." -ForegroundColor Red
exit 1
}
#
# Step 1: Build Driver in Release Mode
#
Write-Host "[1/3] Building driver in release mode..." -ForegroundColor Yellow
Push-Location $driverDir
try {
cargo build --release --target x86_64-pc-windows-msvc
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Cargo build failed with exit code $LASTEXITCODE" -ForegroundColor Red
exit $LASTEXITCODE
}
Write-Host " Driver built successfully" -ForegroundColor Green
} finally {
Pop-Location
}
#
# Step 2: Link the Driver
#
Write-Host "[2/3] Linking driver..." -ForegroundColor Yellow
Push-Location $outDir
try {
# Copy the .lib file to output directory
$libSource = Join-Path $driverDir "target\x86_64-pc-windows-msvc\release\driver.lib"
$libDest = Join-Path $outDir "driver.lib"
if (-not (Test-Path $libSource)) {
Write-Host "ERROR: Built driver.lib not found at: $libSource" -ForegroundColor Red
exit 1
}
Copy-Item $libSource $libDest -Force
Write-Host " Copied driver.lib" -ForegroundColor Green
# Run linker script (from output directory so files are created here)
$linkScript = Join-Path $rootDir "link-dev.ps1"
if (-not (Test-Path $linkScript)) {
Write-Host "ERROR: link-dev.ps1 not found at: $linkScript" -ForegroundColor Red
exit 1
}
& $linkScript
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Linking failed with exit code $LASTEXITCODE" -ForegroundColor Red
exit $LASTEXITCODE
}
# Rename driver.sys to test name
$sysFile = Join-Path $outDir "driver.sys"
if (-not (Test-Path $sysFile)) {
Write-Host "ERROR: driver.sys was not created" -ForegroundColor Red
exit 1
}
$testSysFile = Join-Path $outDir "PortmasterKext_test.sys"
Move-Item $sysFile $testSysFile -Force
Write-Host " Driver linked successfully (PortmasterKext_test.sys)" -ForegroundColor Green
} finally {
Pop-Location
}
#
# Step 3: Sign the Driver
#
Write-Host "[3/3] Signing driver..." -ForegroundColor Yellow
Push-Location $outDir
try {
$sysFile = Join-Path $outDir "PortmasterKext_test.sys"
# Sign the driver
SignTool sign /v /fd SHA256 /s PrivateCertStore /n DriverTestCert $sysFile
if ($LASTEXITCODE -ne 0) {
Write-Host "ERROR: Signing failed with exit code $LASTEXITCODE" -ForegroundColor Red
Write-Host "Make sure the certificate is installed in PrivateCertStore" -ForegroundColor Yellow
exit $LASTEXITCODE
}
Write-Host " Driver signed successfully" -ForegroundColor Green
# Verify signature
Write-Host ""
Write-Host "Verifying signature..." -ForegroundColor Yellow
SignTool verify /v /pa $sysFile
if ($LASTEXITCODE -ne 0) {
Write-Host "WARNING: Signature verification failed" -ForegroundColor Yellow
} else {
Write-Host " Signature verified" -ForegroundColor Green
}
} finally {
Pop-Location
}
Write-Host ""
Write-Host "=================================================" -ForegroundColor Cyan
Write-Host " Build Complete!" -ForegroundColor Green
Write-Host "=================================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Output directory: $outDir" -ForegroundColor White
Write-Host "Driver file: PortmasterKext_test.sys" -ForegroundColor White
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host " 1. Run playground as Administrator" -ForegroundColor White
Write-Host " 2. Use start command to load the driver" -ForegroundColor White
Write-Host ""