-
Notifications
You must be signed in to change notification settings - Fork 166
HolyGrail BYOVD Scanner
HolyGrail is the BYOVD (Bring Your Own Vulnerable Driver) analyzer for kernel drivers. Upload a .sys, get back: whether it's in LOLDrivers, whether Microsoft's driver-block lists ban it on Windows 10/11, what dangerous capabilities it exposes (terminate-process, communication, direct memory access), and what its certificate chain looks like.
upload .sys ─► /holygrail (POST) ─► saved as Uploads/<hash>_<name>.sys
+ file_info.json (with pe_info)
analyze hash ─► /holygrail?hash=<md5> ─► byovd_results.json
+ dedicated risk score
Upload is the same endpoint shape as the file uploader, with a .sys-only validation. Analysis is intentionally a separate page (/holygrail) so the operator workflow stays distinct from "drop a payload, run static, run dynamic" — drivers need their own scoring lens.
1. PE parse → arch (x32/x64), version, original filename
2. Hash → SHA256 for LOLDrivers + Microsoft block-list lookup
3. Import scan → dangerous APIs (process, memory, IO, comms)
4. LOLDrivers lookup → match against bundled lol_drivers.json
5. Microsoft policy check → Win10 + Win11 SiPolicy XML rules
6. Certificate parse → extract signers, thumbprints, TBS hashes
7. Score → see Detection Score Explained
Saved as Results/<hash>_<name>/byovd_results.json. The full HTML report includes a per-driver section.
The expensive PE parse + checksum recomputation is skipped at analyze time — compile_time and other pe_info already exist in file_info.json from upload, so HolyGrail reads from JSON instead of redoing the work. Saves multi-second roundtrips on multi-MB drivers.
Loads lol_drivers.json (bundled with the HolyGrail tool — pulled from loldrivers.io) and matches by SHA256.
A LOLDriver hit doesn't automatically mean "easy BYOVD" — it means the driver was once vulnerable. Microsoft's block lists may have caught up since. The score combines both signals (see below).
Walks the bundled Win10 and Win11 SiPolicy XML files (in HolyGrail's Policies/ directory) and tests four match modes:
| Rule | What it matches |
|---|---|
| Hash-based | File hash + image hash |
| Version | Filename + version range |
| Certificate | Signing-cert thumbprint or TBS hash |
| Unsigned | Drivers with no valid signature → blocked |
Each block decision comes with a block_reason string surfaced into the result so the operator knows why Windows would refuse to load the driver. Both Win10 and Win11 policies run independently; either or both can fire.
The PE import scan groups risky APIs into capability buckets:
| Category | Sample APIs | What it implies |
|---|---|---|
| Physical memory access |
MmMapIoSpace, MmGetPhysicalAddress
|
Direct DRAM read/write — ring-0 memory corruption surface |
| Process manipulation |
PsLookupProcessByProcessId, PsTerminateProcess
|
Can kill or open handles to arbitrary processes |
| Section mapping |
ZwMapViewOfSection, MmCreateSection
|
Inject memory into other processes |
| Communication |
IoCreateDevice, IoCreateSymbolicLink
|
Exposes an IOCTL surface to userland — the BYOVD attack vector |
When PE parsing fails (uncommon — corrupted PEs), HolyGrail falls back to a string-scan of the binary for known dangerous import names. Less reliable but recovers something.
- Reads the PE security directory.
- Parses PKCS#7 structures.
- Computes thumbprints (SHA1) and TBS-cert hashes for every signer in the chain.
- Validates against the policy certificate-rule set (
certificate.thumbprintandcertificate.tbsrules in the SiPolicy XML).
BYOVD scoring is its own branch — the file/static/dynamic/EDR lanes don't apply. From risk_analyzer.py:
| Signal | Score change |
|---|---|
| Has dangerous capabilities (any of: dangerous imports, terminate-process, communication, listed critical imports) | +55 |
| Not blocked on Windows 11 | +25 |
| Blocked on Windows 11 | -50 |
| Not blocked on Windows 10 | +20 |
| Blocked on Windows 10 | -20 |
| Not in LOLDrivers DB | +10 |
| Listed in LOLDrivers DB | -5 |
Short-circuit: blocked on both Windows 10 and 11 → score = 0 (no exploitation potential, regardless of capabilities). Final value is clipped to [0, 100].
The reasoning: a fresh "find me a vuln driver that still works" search wants high scores on (dangerous + not blocked + not in LOLDrivers). A driver that's already in LOLDrivers and blocked on both Windows versions is a curiosity, not a tool.
# Upload a driver and immediately analyze
grumpycat.py upload-driver vuln.sys --holygrail
# Analyze a driver already uploaded
grumpycat.py results <md5> --type holygrail
# Or via the wrapped library
from litterbox_client import LitterBoxClient
c = LitterBoxClient()
c.upload_and_analyze_driver("vuln.sys")
c.get_holygrail_results("<md5>")The MCP server exposes upload_driver, analyze_holygrail, and get_holygrail_results for LLM-driven workflows.
| File | Purpose |
|---|---|
Uploads/<hash>_<name>.sys |
The driver binary |
Results/<hash>_<name>/byovd_results.json |
Full analysis output |
Results/<hash>_<name>/file_info.json |
PE info (read by HolyGrail to skip the redundant parse) |
Scanners/HolyGrail/Policies/ |
Microsoft SiPolicy XMLs (Win10 + Win11 block lists) |
Scanners/HolyGrail/Analysis/ |
Tool-internal scratch — cleared by the cleanup endpoint |
Tool path and policies path are in Config/config.yaml under analysis.holygrail.
- Detection Score Explained — full BYOVD score formula
-
Configuration Reference —
analysis.holygrailconfig block - LOLDrivers project — source for the vulnerable-driver hash list
- Microsoft recommended driver block rules — source of the block lists