Static Analysis
Tools and techniques for analyzing Windows kernel drivers without execution.
Overview
Static analysis is the foundation of driver vulnerability research. It encompasses disassembly, decompilation, and automated semantic code analysis to identify vulnerability patterns in kernel binaries. Because kernel drivers run at the highest privilege level, static analysis allows researchers to study dangerous code paths without risking system stability -- every potential bug can be examined in a disassembler before committing to a debugging session or exploit attempt.
IDA Pro / HexRays
- Industry-standard disassembler and decompiler
- HexRays decompiler produces C pseudocode from x86/x64 binaries
- Extensive plugin ecosystem (
BinDiff,Diaphora, FLIRT signatures) - Key for: manual reverse engineering, understanding driver logic, analyzing IOCTL dispatch
- Workflow: Load driver -> identify
DriverEntry-> trace IRP dispatch table -> analyze IOCTL handlers - FLIRT signatures for Windows DDK improve function identification significantly, resolving many library calls automatically
- Cost: Commercial license required (~$1,500+ for named license)
Ghidra
- NSA open-source reverse engineering framework
- Comparable decompilation quality to HexRays for many use cases
- Built-in scripting (Java/Python) for automated analysis
- Key for: batch analysis, scripted vulnerability scanning, free alternative to IDA
Ghidraheadless mode (analyzeHeadless) enables CI/CD integration for automated decompilation pipelines- AutoPiff uses
Ghidrafor automated decompilation in Stage 5, exporting decompiled C code to MWDB for downstream analysis - Version Tracking feature provides built-in binary diffing capability
CodeQL for Drivers
- Semantic code analysis using database queries
- Microsoft provides
CodeQLqueries for common driver vulnerabilities - Can query decompiled C code or source (if available)
- Example queries:
- Find all
memcpycalls where size comes from user input without validation - Identify IOCTL handlers using
METHOD_NEITHERwithoutProbeForRead/ProbeForWrite - Detect missing NULL checks after
ObReferenceObjectByHandle - Requires building a
CodeQLdatabase from source or decompiled output
Joern
- Open-source code analysis platform using Code Property Graphs (CPGs)
- Works on decompiled C output from
Ghidra/IDA - Query language (CPGQL) for pattern matching across code
- Useful for: cross-function data flow tracking, taint analysis from IOCTL input to dangerous sinks
- Can trace a user-controlled buffer from
Irp->AssociatedIrp.SystemBufferthrough multiple function calls to a vulnerablememcpyor pool operation
IOCTLance
- Automated IOCTL vulnerability scanner
- Combines static analysis with symbolic execution
- Identifies: buffer overflows, integer overflows, null pointer dereferences in IOCTL handlers
- Produces ranked vulnerability reports with severity and location details
- Can be pointed at a directory of driver binaries for batch scanning
- Particularly effective at finding shallow bugs in IOCTL handler dispatch logic
Binary Diffing
BinDiff-- Google's binary diffing tool for matched function comparison between two versions of a binaryDiaphora-- Open-source binary diffing plugin forIDA Prowith advanced heuristicsghidriff--Ghidra-based binary diffing that works in headless mode- These tools are critical for patch analysis: comparing a pre-patch and post-patch driver reveals exactly which functions were modified and what checks were added
Pattern Matching
Semgrep-- Pattern matching on decompiled C output for vulnerability signaturesYARA-- Pattern matching on raw binary code for known vulnerable sequencesAutoPiff-- Automated patch diffing with semantic rule matching across the full vulnerability pipeline
Practical Workflow
A typical static analysis session for a Windows kernel driver follows these steps:
- Acquire target driver binary (from the running system or via
WinBIndexfor specific builds) - Load in
IDA/Ghidra-- let auto-analysis complete fully before manual review - Apply Windows DDK type libraries and FLIRT signatures for better function and structure recognition
- Identify
DriverEntry-> follow theIRP_MJ_DEVICE_CONTROLhandler assignment - Map the IOCTL dispatch table (switch/case on
IoControlCode) - For each IOCTL: trace input buffer handling, check size validation against
InputBufferLength/OutputBufferLength - Flag dangerous patterns: unchecked
memcpy,METHOD_NEITHERwithoutProbeForRead/ProbeForWrite, missing NULL checks after object reference calls - Cross-reference findings with
CodeQL/Joernqueries for systematic coverage across all code paths