Luchinkin/ntbind

GitHub: Luchinkin/ntbind

基于 PDB 的 Windows 内核 SDK 生成器,通过链接后补丁实现跨版本驱动的单次编译多版本部署。

Stars: 0 | Forks: 0

# ntbind Windows 内核 SDK 生成器。读取 Microsoft PDB 并输出类型访问器的 Rust crate 或 C++ 头文件树。字段偏移量和内核符号地址在部署时通过链接后补丁工具(`ntbind-patch`)解析,因此只需编译一次驱动程序,即可适用于补丁工具拥有 PDB 的所有 Windows 版本。 ## 仓库布局 ``` crates/ ntbind/ Rust runtime: field!/public! macros, types ntbindgen/ generator binary: PDB -> Rust crate or C++ headers ntbind-patch/ post-link symbol resolver examples/ sample-driver/ minimal .sys driver linking the generated SDK cpp/include/ntbind/ C++ runtime headers ``` ## 快速开始 ``` $SYMBOLS = "I:\path\to\symbols" # holds ntkrnlmp.pdb etc. directly # 生成 SDK。 cargo run --release -p ntbindgen -- --symbols $SYMBOLS --out sdk --only ntkrnlmp.pdb # 构建示例 driver。 cd examples\sample-driver cargo -Z json-target-spec build --release cd ..\.. # 针对目标系统进行 Patch(在目标上运行,或传入 --pdb # 以进行跨机器 patching)。 cargo run --release -p ntbind-patch -- ` --input examples\sample-driver\target\x86_64-pc-windows-driver\release\sample_driver.sys ` --output examples\sample-driver\target\x86_64-pc-windows-driver\release\sample_driver.patched.sys ` --auto-modules ` --strip-symtbl ``` ## 目标 `ntbindgen --target rust|cpp|both` 用于选择后端。 - **rust**(默认):独立的 Cargo crate;每个 PDB 类型对应一个 `.rs` 文件。字段偏移量通过 `ntbind::field!` 访问器处理。 - **cpp**:生成 `/include/ntbind//` 头文件树。每个 `.hpp` 文件都配有一个 `magic/.start.hpp` / `.end.hpp` 垫片。 要使用生成的 C++ SDK,需要在 include 路径中配置 `xstd`,以及 `cpp/include/ntbind/` 下的运行时头文件。在原生的 clang 上,运行时的 `__builtin_symbol_read*` 调用会通过 `cpp/include/ntbind/common.hpp` 中的纯 C++ 回退机制进行解析;打过补丁的 LLVM 工具链会将此回退机制替换为内置的符号表读取(每次访问只需一次 MOVQ + XOR)。 - **both**:将 `/rust/` 和 `/cpp/` 并排写入。 ## 为驱动程序或 DLL 打补丁 `ntbind-patch` 会遍历二进制文件的符号表,查找每个引用模块的运行时地址,并将其写回映像中。适用于内核模式驱动程序和用户模式 DLL/EXE。参数: - `--module =`:`` 在*目标*系统上的加载地址。每个映像可重复使用。对于同一个映像,此参数优先级高于 `--auto-modules`。 - `--auto-modules`:枚举正在运行的系统上已加载的模块,并为二进制文件引用但未显式提供的每个映像自动填充 `--module`。合并两个模块集:内核模式驱动程序(`ntoskrnl.exe`、`hal.dll` 以及所有已加载的 `.sys` 文件)通过 `EnumDeviceDrivers` 获取;用户模式模块(位于补丁工具自身进程中的 `ntdll.dll`、`kernel32.dll` 以及补丁工具已加载的任何 DLL)通过 `EnumProcessModulesEx` 获取。 - `--list-modules`:打印二进制文件引用的映像(包含每个模块的符号计数)并退出。 - `--module =`:`` 在*目标*系统上的加载地址。每个映像可重复使用。对于同一个映像,此参数优先级高于 `--auto-modules`。 - `--auto-modules`:枚举正在运行的系统上已加载的模块,并为二进制文件引用但未显式提供的每个映像自动填充 `--module`。合并两个模块集:内核模式驱动程序(`ntoskrnl.exe`、`hal.dll` 以及所有已加载的 `.sys` 文件)通过 `EnumDeviceDrivers` 获取;用户模式模块(位于补丁工具自身进程中的 `ntdll.dll`、`kernel32.dll` 以及补丁工具已加载的任何 DLL)通过 `EnumProcessModulesEx` 获取。 - `--list-modules`:打印二进制文件引用的映像(包含每个模块的符号计数)并退出。 - `--pdb =`:目标系统版本的 `` 对应的 PDB。可选;提供特定于版本的 RVA 查找。如果没有提供 PDB,补丁工具将复用生成器内置的 RVA,但这仅在目标运行与生成 SDK 时相同的系统版本时才正确。 - `--strip-symtbl`:从修补后的映像中移除符号表索引节。建议在生产环境中使用——可以将磁盘占用和已提交内存减少大约相当于该节原始大小的空间。 “示例解析”日志行会为每个模块打印一个已解析的 `(image, symbol, va)` ——在加载前请根据目标系统对其进行验证。 对于用户模式目标,如果二进制文件引用了补丁工具自身未加载的 DLL(`d3d11.dll`、`win32u.dll` 以及任何不在补丁工具导入图中的 DLL),请显式使用 `--module =` ——`--auto-modules` 只能看到补丁工具进程已映射的内容。 ## 获取匹配的 PDB 对于 SDK 目标中的每个模块,请提取与*目标*系统版本相匹配的 PDB: 1. 从目标模块(类型为 2 的调试目录条目)读取 CodeView `RSDS` 记录,以获取其 PDB GUID 和 age。 2. `https://msdl.microsoft.com/download/symbols///` 3. 将 PDB 放入 `--symbols` 目录,重新生成 SDK,并重新编译引用该 SDK 的二进制文件。 新模块通过 `PdbEntry` 表在 `crates/ntbindgen/src/config.rs` 中注册——每个条目将一个 PDB 文件名映射到其命名空间标签和 `hint_image`(托管其公开符号的运行时 DLL/EXE)。 ## 编写驱动程序 `examples/sample-driver/` 是参考模板。它作为 NATIVE 子系统的 `.sys` 文件针对生成的 SDK 进行编译,通过 `nt::api::dbg_print` 调用 `DbgPrint`,并通过 SDK 访问器遍历内核的活动进程列表。在迁移到实际目标时,值得保留的两个部分是 `DbgPrint3` ABI 垫片和 `resolve_dbg_print`;进程遍历主体仅用于演示。 新的驱动 crate 的 `Cargo.toml` 应参考示例:包含 `cdylib` crate 类型,`panic = "abort"`,将 `ntbind` 和生成的 SDK crate 作为依赖项,并在 `.cargo/config.toml` + `x86_64-pc-windows-driver.json` 中配置内核模式链接标志。`examples/sample-driver/rust-toolchain.toml` 中的工具链版本锁定是必须的(`-Z build-std` 仅在 nightly 版本可用);请将其复制到任何编译内核驱动的使用者 crate 中。 ## CLI 旋钮 - `--symbols `:PDB 根目录。 - `--out `:输出根目录。 - `--only `:限制为单个 PDB(例如 `ntkrnlmp.pdb`)。 - `--target rust|cpp|both`:后端。 - `--build `:限制为 `config::BUILDS` 中的一个条目。 - `--no-publics`:跳过每个命名空间的 `api.rs` / `api.hpp`。当不需要内核函数接口时,可加快迭代速度。 - `--no-encrypt`:以明文形式交付符号表(不使用 XOR-LCG)。每个条目的密钥都将变为 `0`,运行时解码会折叠为纯粹的 `read_volatile`,并且 `.symdsc` 负载可以进行逐字节检查。 生成的 Rust SDK crate 支持通过 `NTBIND_CRATE_PATH` 环境变量覆盖其 `Cargo.toml` 中的 `ntbind = { path = ... }` 依赖项。 ## 致谢 Wire 格式和基于 PDB 的 `.symtbl` 补丁工具设计最初由 can1357 开发的 [Selene](https://github.com/can1357/selene) 提供。
标签:PDB解析, SOC Prime, Windows内核, 代码生成器, 可视化界面, 开发工具, 白帽子, 网络安全监控, 跨平台编译, 通知系统, 驱动开发