Benowin Blanc — Windows through a detective's lens.
(Name credits go to my beloved spouse. ꨄ︎)
A set of command-line tools that parse Windows SDK and PHNT headers via libclang
and let you inspect what's actually in them: struct layouts, field offsets,
enum values, constants, #define macros, and function declarations with full ABI breakdowns — the works.
Think of it as dt + x from WinDbg, but you don't need a debugger running,
and it works against any SDK version, architecture, or PHNT release you throw at it.
Try bb viewer in your browser
bb-viewer — a vanilla TypeScript SPA built with Bun, powered by bb's JSON exports.
Browse 8,000+ functions, 5,000+ types, and 25,000+ constants from the Windows SDK and PHNT headers across all architectures (amd64, x86, arm64, arm) — with ABI layouts, memory visualizations, C expressions, and an interactive type graph. No install required.
bb-typesStruct and class layouts, right in your terminal |
bb-constsConstants, enums, and macro definitions |
bb-types-tuiInteractive struct browser |
bb-consts-tuiInteractive constant browser |
What is this?
Windows ships with thousands of C/C++ headers (the Windows SDK) that define every struct, enum, constant, macro, and function the OS exposes. Separately, the community-maintained PHNT (Process Hacker NT headers) documents internal structures and syscalls that Microsoft doesn't publish.
bb parses these headers with libclang and gives you fast, searchable, pretty-printed access to all of it — struct layouts, constant values, function ABIs with per-parameter register/stack locations, and more (hell, even TUIs!) — no debugger, no IDE, no digging through .h files by hand.
|
You might want this if you...
|
Quick start
Building
On a Windows host, you will need the following:
- Visual Studio 2019/2022 Build Tools
- LLVM + Clang (libclang.dll) version >=18.1
- Rust 2024 edition
- Python >=3.9 (for submodule setup)
Afterwards, you may produce the binaries by invoking the following command:
.\update-submodules.ps1 # init + generate submodule data cargo build --release
The project uses two submodules, managed by update-submodules.ps1:
| Submodule | Purpose | Required for | Setup |
|---|---|---|---|
| phnt | PHNT NT header generation (phnt-single-header) | --phnt flag |
.\update-submodules.ps1 phnt |
| sparse | MSDN API metadata (sparse) | Enriched function views | .\update-submodules.ps1 sparse |
You can update them individually or all at once (.\update-submodules.ps1). Both support env var overrides for custom data:
| Env var | What it does |
|---|---|
BB_PHNT_HEADER |
Use a custom phnt.h instead of generating from the submodule |
BB_SPARSE_JSON |
Use a pre-generated sparse.json instead of running the Python tool |
First commands
Inspect a struct layout:
Recurse into nested types:
bb-types --phnt --struct _PEB --depth 2
Search for constants by wildcard:
bb-consts --name GENERIC_*Scope to a specific enum:
bb-consts --enum _MINIDUMP_TYPE
Use Enum::Constant syntax to search within enums:
bb-consts --name "_MINIDUMP_TYPE::*"Target a different architecture from your host:
bb-types --arch arm64 --struct _CONTEXT
Inspect a function's ABI breakdown:
bb-funcs --name CreateFileW
List exported functions from a header:
bb-funcs --name "Create*" --filter fileapi.h --exportedFilter functions with SQL WHERE clauses:
bb-funcs --where "params > 3 AND return_type = 'BOOL'" bb-funcs --where "name LIKE '%File%' AND is_exported = true"
Export as JSON or SQLite for your own tooling:
bb-types --arch arm64 --struct _CONTEXT --json bb-consts --name "PROCESS_*" --json bb-funcs --name "Nt*" --phnt --json # or export to SQLite bb-funcs --name "Create*" --sqlite funcs.db bb-types --struct "_*" --sqlite types.db
JSON mode in bb-types performs full nested type expansion, producing all matched types alongside their deduplicated referenced_types — regardless of the --depth flag. SQLite exports mirror the same level of detail as JSON.
Typo? Both CLIs suggest close matches:
bb-types --struct _PBE error: no structs matching '_PBE' did you mean? _ABC _PSP _PEB
The tools
CLI applications
|
TUI applications
|
Libraries
|
Web viewer
| What it does | |
|---|---|
| bb-viewer | Web explorer for bb's JSON output — functions, types, constants, type graph |
Supported headers
Architecture support
All tools support cross-compilation via --arch — inspect layouts and ABIs for any target from any host:
| Flag | Target | Notes |
|---|---|---|
amd64 |
x86_64-pc-windows-msvc |
Default |
x86 |
i686-pc-windows-msvc |
|
arm64 |
aarch64-pc-windows-msvc |
|
arm |
thumbv7-pc-windows-msvc |
bb-types --arch arm64 --struct _CONTEXT
How it works
The flow is described below:
We use bb-sdk to discover (or gather) the SDK environment, then we generate a SDK-specific "synthetic header" (also known as an Unsaved/CXUnsavedFile in the Clang-world) which will be passed through partial compilation with libclang.dll and in turn give us a TranslationUnit.
From the translation unit, we lift the AST entities into bb-clang serializable objects, and we use the information that we expose there to develop the tools.
For functions, bb-clang computes the full ABI layout: which register or stack slot each parameter occupies, per architecture and calling convention (cdecl, stdcall, fastcall). bb-funcs enriches this with MSDN metadata (DLL, lib, min Windows version) from sparse and cross-references known constant values for each parameter. SQL WHERE clause filtering is supported via bb-sql.
For macros specifically, bb-consts does a two-pass resolution: first pass evaluates simple literals and variables, second pass substitutes known constant names into unresolved macro token streams before re-evaluating. This handles things like #define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF).





