Windows Mini Filter Driver Deployment Guide
January 3, 2026 · View on GitHub
Overview
This guide covers deploying the agentsh Windows mini filter driver in production environments, including code signing requirements, installation procedures, and monitoring.
Requirements
Development/Testing
- Windows 10/11 64-bit
- Test signing mode enabled (
bcdedit /set testsigning on) - Administrator privileges
Production
- EV (Extended Validation) Code Signing Certificate
- Microsoft Hardware Dev Center account (for attestation signing on Windows 10 1607+)
- WHQL certification (optional, recommended for enterprise deployment)
Code Signing
Test Signing (Development)
- Create a test certificate:
makecert -r -pe -ss PrivateCertStore -n "CN=AgentSH Test" agentsh-test.cer
- Sign the driver:
signtool sign /v /s PrivateCertStore /n "AgentSH Test" /t http://timestamp.digicert.com agentsh.sys
- Enable test signing on target machine:
bcdedit /set testsigning on
Production Signing
-
Obtain an EV Code Signing Certificate from a trusted CA (DigiCert, Sectigo, etc.)
-
Sign the driver catalog:
inf2cat /driver:. /os:10_x64
signtool sign /v /ac cross-cert.cer /n "Your Company" /tr http://timestamp.digicert.com /td sha256 /fd sha256 agentsh.cat
- Submit for attestation signing (Windows 10 1607+):
- Create account at https://partner.microsoft.com/dashboard
- Submit driver package for attestation signing
- Download signed package
Installation
Manual Installation
REM As Administrator
copy agentsh.sys %SystemRoot%\System32\drivers\
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 132 agentsh.inf
fltmc load agentsh
Verify Installation
fltmc
Expected output:
Filter Name Num Instances Altitude Frame
------------------------------ ------------- ------------ -----
AgentSH 3 385200 0
Uninstallation
fltmc unload agentsh
rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 agentsh.inf
del %SystemRoot%\System32\drivers\agentsh.sys
Configuration
Fail Modes
| Mode | Behavior |
|---|---|
FAIL_MODE_OPEN (default) | Allow operations when policy service unavailable |
FAIL_MODE_CLOSED | Deny operations when policy service unavailable |
Configure via Go client:
client.SetConfig(&DriverConfig{
FailMode: FailModeClosed,
PolicyQueryTimeoutMs: 5000,
MaxConsecutiveFailures: 10,
})
Cache Tuning
| Parameter | Default | Range | Description |
|---|---|---|---|
| CacheMaxEntries | 4096 | 100-100000 | Maximum cached decisions |
| CacheDefaultTTLMs | 5000 | 100-3600000 | Default cache entry TTL |
Monitoring
Registry Monitoring
The driver intercepts Windows registry operations via CmRegisterCallbackEx. This provides:
- Operation interception: Create, set, delete, rename keys and values
- Policy enforcement: Allow, deny, or require approval based on registry rules
- High-risk path detection: Automatic detection of persistence and security-sensitive paths
- MITRE ATT&CK mapping: Events include technique IDs for security monitoring
Registry Policy Configuration
In your policy file (agentsh.yaml):
registry_rules:
# Allow application settings
- name: allow-app-settings
paths: ['HKCU\SOFTWARE\MyApp\*']
operations: ["*"]
decision: allow
# Block persistence locations
- name: block-run-keys
paths:
- 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*'
- 'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*'
operations: [write, create, delete]
decision: deny
priority: 100
notify: true
# Require approval for service modifications
- name: approve-service-changes
paths: ['HKLM\SYSTEM\CurrentControlSet\Services\*']
operations: [write, create, delete]
decision: approve
message: "Agent wants to modify service: {{.Path}}"
timeout: 2m
Registry Operations
| Operation | Description |
|---|---|
read | Query key/value (QueryValue) |
write | Set key/value (SetValue) |
create | Create key (CreateKey) |
delete | Delete key/value (DeleteKey, DeleteValue) |
rename | Rename key (RenameKey) |
High-Risk Registry Paths
The driver includes built-in detection for high-risk paths commonly used in attacks:
| Path | Risk | MITRE Technique |
|---|---|---|
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run* | Critical | T1547.001 - Registry Run Keys |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon* | Critical | T1547.004 - Winlogon Helper DLL |
HKLM\SYSTEM\CurrentControlSet\Services\* | High | T1543.003 - Windows Service |
HKLM\SOFTWARE\Policies\Microsoft\Windows Defender* | Critical | T1562.001 - Disable Security Tools |
HKLM\SYSTEM\CurrentControlSet\Control\Lsa* | Critical | T1003 - Credential Dumping |
Write operations to these paths are blocked by default even if default_action: allow is set.
Metrics
Retrieve via Go client:
metrics, _ := client.GetMetrics()
fmt.Printf("Cache hit rate: %.2f%%\n",
float64(metrics.CacheHitCount) / float64(metrics.CacheHitCount + metrics.CacheMissCount) * 100)
Key metrics:
CacheHitCount/CacheMissCount- Cache efficiencyPolicyQueryTimeouts- Policy service responsivenessFailOpenMode- Current fail mode stateAllowDecisions/DenyDecisions- Policy enforcement stats
Windows Event Log
Driver events appear in:
- Event Viewer → Windows Logs → System
- Source: AgentSH
Debug Output
In development, view DbgPrint output with DebugView (Sysinternals).
Troubleshooting
Driver won't load
- Check test signing:
bcdedit | findstr testsigning - Verify driver signature:
signtool verify /v /pa agentsh.sys - Check Event Viewer for errors
High latency
- Check metrics for cache hit rate (should be >80%)
- Verify policy service is running
- Consider increasing cache size
Fail-open triggered
- Check policy service connectivity
- Review
ConsecutiveFailuresmetric - Increase
MaxConsecutiveFailuresor fix connectivity
Security Considerations
- Production deployments must use EV-signed drivers
- Never disable Secure Boot in production
- Use FAIL_MODE_CLOSED for high-security environments
- Monitor fail mode transitions in SIEM
- Rotate session tokens regularly
WinFsp Coexistence
When using both the minifilter driver and WinFsp filesystem mounting, the agentsh process is automatically excluded from minifilter interception to prevent double-capture of file events.
How It Works
- Before mounting WinFsp, the Go client calls
ExcludeSelf()on the driver client - The driver stores the agentsh process ID in
gExcludedProcessId - All minifilter pre-callbacks (PreCreate, PreWrite, PreSetInfo) check for the excluded PID
- If the current process matches, the operation is allowed without policy check
Configuration
The exclusion is automatic when both systems are active. No additional configuration is required.
// This happens automatically in Filesystem.Mount()
if fs.driverClient != nil && fs.driverClient.Connected() {
fs.driverClient.ExcludeSelf()
}
Troubleshooting
If you see duplicate file events:
- Verify the driver client is connected before mounting WinFsp
- Check that
ExcludeSelf()completes without error - Ensure the minifilter driver is running (version with MSG_EXCLUDE_PROCESS support)
To verify exclusion is working:
// Check metrics - file events should not double-count
metrics, _ := client.GetMetrics()
fmt.Printf("File queries: %d\n", metrics.FilePolicyQueries)
Sandbox Integration
The Windows sandbox uses two complementary isolation layers:
AppContainer (Primary)
- Kernel-enforced capability isolation
- Automatic registry isolation
- Configurable network access
- Full stdout/stderr capture from sandboxed processes
- Automatic ACL cleanup on sandbox termination
- Requires Windows 8+
Minifilter (Secondary)
- Policy-based file/registry rules
- Works with AppContainer for defense-in-depth
- Can operate standalone for legacy systems
Configuration
config := platform.SandboxConfig{
Name: "my-sandbox",
WorkspacePath: "/path/to/workspace",
AllowedPaths: []string{"/path/to/tools"},
WindowsOptions: &platform.WindowsSandboxOptions{
UseAppContainer: true,
UseMinifilter: true,
NetworkAccess: platform.NetworkOutbound,
FailOnAppContainerError: true,
},
}
sandbox, err := manager.Create(config)
if err != nil {
log.Fatal(err)
}
defer sandbox.Close() // Automatically cleans up AppContainer profile and ACLs
// Execute command with full output capture
result, err := sandbox.Execute(ctx, "cmd.exe", "/c", "echo", "hello")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Exit code: %d\n", result.ExitCode)
fmt.Printf("Stdout: %s\n", string(result.Stdout))
fmt.Printf("Stderr: %s\n", string(result.Stderr))
Network Access Levels
| Level | Description |
|---|---|
NetworkNone | No network access (default, maximum isolation) |
NetworkOutbound | Internet client connections only |
NetworkLocal | Private network access only |
NetworkFull | All network access |