
安装方法取决于你的 IDA 版本,因为内置的插件管理器(以及相应的 hcli 工具和 ida-plugin.json 清单)仅存在于 IDA 9.0 及以上版本。IDA 7.6 和 8.x 没有插件管理器,只会扫描插件文件夹的顶层目录。
hcli)该仓库附带了一个 ida-plugin.json 清单,因此 IDA 9.0+ 会从其自身子目录加载插件。安装方式如下:```
hcli plugin install DriverBuddyReloaded
这将插件放入你的用户插件文件夹的子目录中(例如
`%APPDATA%\Hex-Rays\IDA Pro\plugins\DriverBuddyReloaded\` 或 `~/.idapro/plugins/DriverBuddyReloaded/`),并将
`DriverBuddyReloaded.py` 入口点 *放在* 该子目录内。这是预期的布局:IDA 读取清单,
从子目录加载声明的入口点,并将子目录添加到 `sys.path` 中,以便入口点能够
导入同级的 `DriverBuddyReloaded` 包。你**不需要**将 `DriverBuddyReloaded.py` 移动到顶层。
使用 `hcli plugin status` 验证安装,然后启动 IDA 并确认插件出现在
`Edit -> Plugins` 下(检查输出窗口是否有启动时的 Python 错误)。
要从本地检出进行测试(例如在你自己的修改之后),在仓库根目录下运行 `hcli plugin install .`;
`hcli plugin lint .` 会先验证清单/布局。
### IDA 7.6 / 8.x(手动复制)
这些版本没有插件管理器,因此通过 `hcli` 安装的子目录插件将**不会**被识别。直接将
`DriverBuddyReloaded` 文件夹和 `DriverBuddyReloaded.py` 脚本文件复制到 IDA 插件文件夹的**顶层**,例如:
- `%APPDATA%\Hex-Rays\IDA Pro\plugins\`
- `C:\Program Files\IDA Pro 8.4\plugins\`
- `~/.idapro/plugins/`
最终的布局是 `plugins\DriverBuddyReloaded.py` 与 `plugins\DriverBuddyReloaded\`(包文件夹)并列。
### 注意事项
如果你的 IDA 配置为使用 Python 2,运行 `idapyswitch` 二进制文件(位于 IDA 文件夹中)切换到 Python 3。
**注意:** Driver Buddy Reloaded 运行于 IDA 7.6+、8.x(包括 8.4)和 9.0+ 以及 Python 3。所有特定于版本的
IDA API 差异(在 IDA 9.0 中移除了 `get_inf_structure`、`ida_struct` 模块和 `idc.*struc*` 辅助函数等)
都由 `DriverBuddyReloaded/ida_compat.py` 兼容层内部处理。
## 快速使用
要使用自动分析功能:
1. 启动 IDA 并加载一个 Windows 内核驱动程序。
2. 转到 `Edit -> Plugins -> Driver Buddy Reloaded` 或按 `CTRL+ALT+A` 开始自动分析。
3. 检查"输出"窗口中的分析结果,以及运行结束时打开的 **Driver Buddy Reloaded - Findings** 窗口(双击行跳转到其地址)。
4. 以下文件将写入 IDA 的 DB 目录下(均以 `<DRIVER_NAME>-YYYY-MM-DD-TIMESTAMP-` 为前缀):
- `findings.json` - 机器可读的结果(IOCTL、标记的函数、设备名、池标签、调用链、启发式检查、设备 ACL 审计、符号链接、导出审计、特权操作码)
- `report.html` - 一个独立的、按严重性分组的 HTML 报告
- `pooltags.txt` - 以 `pooltags.txt` 格式转储的池标签,适用于 WinDbg
- `autoanalysis.txt` - 完整的文本分析日志(镜像输出窗口)
要解码一个 IOCTL:
1. 将鼠标光标放在包含可疑 IOCTL 代码的行上。
2. 右键单击并选择 `Driver Buddy Reloaded -> Decode IOCTL`;也可以按 `CTRL+ALT+D` 快捷键。
要随时(无需重新运行分析)重新打开 IOCTL 窗口或 findings 窗口:
- 按 `CTRL+ALT+I` 打开 IOCTL 窗口。
- 按 `CTRL+ALT+F` 打开 findings 窗口。
### 高级使用
- [vulnerable_function_lists](https://github.com/voidsec/driverbuddyreloaded/blob/main/DriverBuddyReloaded/vulnerable_functions_lists) 目录包含可能存在危险/问题的函数、Windows API 和操作码列表;并提供了关于为什么列出特定函数/API 的简要描述。你可以编辑 `custom` 列表,包含驱动程序特定的函数。
**注意**:`winapi_function_prefixes` 将部分匹配函数名称的开头(例如 `Zw` 将匹配 `ZwClose`、`ZwCommitComplete` 等),而 `winapi_functions` 仅执行精确匹配。
- 在 [find_opcodes.py](https://github.com/voidsec/driverbuddyreloaded/blob/main/DriverBuddyReloaded/find_opcodes.py) 中,`find_opcode_data` 选项(默认为 `False`)
抑制落在数据段中的操作码匹配
([issue #11](https://github.com/VoidSec/DriverBuddyReloaded/issues/11))。将其设置为 `True` 也会显示
数据中的原始字节匹配;如果以此方式错过了真实操作码,转到报告的地址并重新将字节定义为代码通常可以恢复。匹配结果像其他阶段一样报告(results 窗口、`findings.json`、`report.html`)。
**注意**:将其设置为 `True` 会产生更多误报!
## 关于 Driver Buddy Reloaded
**Driver Buddy Reloaded** 是一个 IDA Pro Python 插件,帮助自动化一些繁琐的 Windows 内核驱动程序逆向
工程任务。它有许多方便的功能,例如:
* 识别驱动程序类型(WDM、KMDF、UMDF、WDF、Mini-Filter、Stream Minidriver、AVStream、PortCls)
* 定位**每种**驱动程序的 `DispatchDeviceControl` / `DispatchInternalDeviceControl` 函数
(`MajorFunction[IRP_MJ_DEVICE_CONTROL]` 存储扫描即使在 minifilter/WDF 驱动程序中也能找到处理程序,即使该驱动程序还暴露了一个传统控制设备,并且即使分配位于辅助函数中而非 `DriverEntry`)
* 为 `WDF` 和 `WDM` 驱动程序填充常用结构
* 尝试识别和标记如 `IRP` 和 `IO_STACK_LOCATION` 等结构
* 标记通常不会被标记的 `WDF` 函数调用
* 创建一个 `IRP_MJ_FUNCTION` IDA 枚举并将其应用于 `DriverEntry`(WDM)中的 `MajorFunction` 数组槽
* 查找和解码 IOCTL 代码
* 对已识别的分发函数进行自动多策略扫描(无需光标定位):
反编译器 ctree(恢复被跳转表或二分搜索分发隐藏的代码,这些代码从未以立即数形式出现),IDA 开关表恢复,以及原始立即操作数回退(回退仅在实际读取 IRP 的 IoControlCode 的函数上运行,因此一个被错误识别的库辅助函数不会泄露其内部常量作为假 IOCTL)
* NTSTATUS 值从 IDA 类型数据库动态解析(带有广泛的硬编码回退),并且驱动程序仅向下游发送的 **出站** IOCTL(`IoBuildDeviceIoControlRequest` / `ZwDeviceIoControlFile` / ...)被排除,以免被误认为是驱动程序自身的攻击面
* 标记容易被误用的函数
* 查找潜在的 `DeviceName`(mmap 扫描 + IDA 字符串数据库回退,带有源地址)
* 转储 `Pooltags`(基于导入的主要方式 + 寄存器传播的回退,用于在寄存器中暂存的标签)
* **启发式漏洞检查**在每个分发器及其传递调用的函数上进行:未验证的用户拷贝、TOCTOU/双重提取、释放后使用(函数内和跨函数通过释放的全局变量)、缺少权限门、IRQL 不匹配、不安全的 MDL 映射、栈分配缓冲区(`_alloca`)、未经验证大小的池分配、特权 CPU 指令(端口 I/O `in`/`out`、`mov cr*`)、任意写(write-what-where)以及对 `\Device\PhysicalMemory` 的引用(BYOVD 模式) - 请参阅 [启发式漏洞检查](#heuristic-vulnerability-checks)
* **设备 ACL 审计和符号链接跟踪**:标记使用无安全描述符(全局可访问)的 `IoCreateDevice` 创建的设备 / 弱 `IoCreateDeviceSecure` SDDL,并解码 `IoCreateSymbolicLink` 目标路径
* **导出审计**:标记具有零内部交叉引用的驱动程序导出(潜在攻击面)
* **风险评分**对解码的 IOCTL 按 IOCTL 进行评分(优先考虑 `METHOD_NEITHER` / `FILE_ANY_ACCESS`,并且仅当从 IOCTL **自身**的 case 处理程序可到达危险接收器/操作码时提升 IOCTL 的评分 - `MmMapIoSpace`、`memcpy`、`__writemsr`、端口 I/O、PCI 配置访问 - 以便单调分发器中的良性代码不再被危险兄弟的接收器玷污;当归因不精确时,提升被限制而不是强制为 CRITICAL)并在一个可点击的结果窗口中按严重性呈现所有发现(双击跳转到地址)
* **追踪调用链**从分发/IOCTL 处理程序到危险接收器(启发式、基于名称)
* 将结果导出为机器可读的 **JSON** 文件和一个独立的 **HTML** 报告

### 查找 DispatchDeviceControl
该工具可以自动定位和识别 `DispatchDeviceControl` 例程。这个函数用于将所有传入的 `DeviceIoControl` 代码路由到与该代码关联的特定驱动程序函数。自动识别此函数使查找每个驱动程序的有效 `DeviceIoControl` 代码更快。此外,当因崩溃调查驱动程序中可能存在的漏洞时,知道此函数的位置有助于将焦点缩小到与崩溃的 `DeviceIoControl` 代码关联的特定函数调用。
当分析成功时,一些子函数将被重命名如下:
- `DriverEntry`:驱动加载后调用的第一个驱动程序提供的例程。它负责初始化驱动程序。
- `Real_Driver_Entry`:通常是从 `DriverEntry` 转移执行到的函数。通常是在此处初始化 `DeviceName` 的地方。
- `DispatchDeviceControl`/`DispatchInternalDeviceControl`:如果工具能够恢复某些特定偏移处的函数,则函数将被重命名为适当的名称。
- `Possible_DispatchDeviceControl_#`:如果工具无法恢复 `DispatchDeviceControl` 或 `DispatchInternalDeviceControl`,它会采用实验性搜索,跟随执行流,并检查函数是否加载了已知的 `IO_STACK_LOCATION` 和 `IRP` 地址;表明该函数可能是 DispatchDeviceControl。由于基于启发式,可能返回多个结果,并且容易产生误报。

### 标记 WDM 和 WDF 结构
所有 `WDM`/`WDF` 驱动程序共享几种驱动程序结构。该工具能够自动识别这些结构,例如 `IO_STACK_LOCATION`、`IRP` 和 `DeviceObject` 结构,并可以在逆向工程过程中节省时间,为驱动程序中使用这些函数的区域提供上下文。

### 查找和解码 IOCTL 代码
在逆向驱动程序时,经常会在分析过程中遇到 IOCTL 代码。这些代码解码后会揭示有用的信息,并可能将焦点引向驱动程序中更可能存在漏洞的特定部分。
通过右键单击潜在的 IOCTL 代码,会出现一个上下文菜单选项(或者当光标位于包含可疑 IOCTL 代码的行上时使用 `Ctrl+Alt+D` 快捷键),可用于解码该值。这将打印一个包含所有解码 IOCTL 代码的表格。通过在反汇编视图中右键单击解码的 IOCTL 代码,可以将其标记为无效;这将保留任何非 IOCTL 注释不变。
- 解码的 IOCTL 会输出到输出窗口,并列出在按严重性着色的 IOCTL 窗口中;自动分析后,它们也会记录在 `findings.json` / `report.html` 中。
自动分析还对已识别的分发函数运行多策略扫描,以自动发现 IOCTL,无需手动光标定位。对于每个分发器,它使用 Hex-Rays 反编译器(如果可用)直接从重构的控制流中读取 switch-case 标签和 `==`/`!=` 比较常量,回退到 IDA 的开关表元数据,然后进行原始立即操作数扫描。反编译器路径恢复了从未在反汇编中逐字出现的代码 - 例如,编译器生成为跳转表(只有表基/边界作为立即数幸存)或二分搜索比较树(中间代码仅作为增量幸存)的分发器。在一个代表性语料库上,这将恢复率从 7/28 提高到 28/28(HEVD)和 4/17 提高到 17/17(ALSysIO64),且没有误报。


### 标记函数
Driver Buddy Reloaded 包含 C/C++ 函数、操作码和 Windows API 列表(定义在 [vulnerable_function_lists](https://github.com/voidsec/driverbuddyreloaded/blob/main/DriverBuddyReloaded/vulnerable_functions_lists) 目录中),这些列表中的函数通常容易受到攻击或可能导致缓冲区溢出条件。所有找到的实例都会在自动分析期间报告,有助于在查找可能受用户控制的代码路径到达敏感函数时提供帮助。

### 查找 DeviceName
该工具自动尝试查找驱动程序注册的设备路径(`DeviceName`),如果无法通过查看二进制文件中的 Unicode 字符串找到路径,则分析人员可以尝试手动使用 Mandiant 的 [FLOSS](https://github.com/mandiant/flare-floss/) 来查找混淆的路径。

### 转储 Pooltags
在自动分析期间,该工具还会以适用于 `pooltags.txt` 的格式转储二进制文件使用的 `Pooltags`。然后可以将输出复制粘贴到文件的末尾,稍后由 WinDbg 使用。
- 一个 `DriverName.sys-DATE-TIME_STAMP-pooltags.txt` 文件,包含所有转储的 Pooltags,将写入 IDA 的 DB 目录下。

### 启发式漏洞检查
`heuristics.py` 模块在调用链追踪之后运行,检查每个分发器 **以及它传递调用的函数** - 因此分析的是每个 IOCTL 的处理程序,而不仅仅是分发器的序言。被调用者匹配是导入感知的(导入的 `call cs:__imp_<Name>` 与本地调用匹配相同的名称)。它在 **heuristic** 类别中输出发现(特权指令发现使用 **opcode** 类别):
| 检查项 | 标记内容 | 严重性 |
|---|---|---|
| 未验证的用户拷贝 | `memcpy`/`RtlCopyMemory`/等,附近没有 `ProbeForRead`/`ProbeForWrite`/安全字符串保护 | HIGH(处理程序)、MEDIUM(其他) |
| TOCTOU / 双重提取 | 在一个控制流路径上重新读取用户模式指针字段,且中间没有 `ProbeForRead`(仅在 METHOD_NEITHER 处理程序上,因此不会标记内核缓冲区重新读取) | MEDIUM |
| 释放后使用 | 在函数内重新使用已释放的指针(寄存器 CFG 遍历),或者全局变量被释放后未置空,然后从另一个函数解引用 | HIGH |
| 缺少权限门 | 从分发器可到达一个敏感操作(`ZwOpenProcess`/`MmMapIoSpace`/PCI 配置等),而路径上没有任何 `SeAccessCheck`/`SeSinglePrivilegeCheck`/令牌检查 | HIGH |
| IRQL 不匹配 | 当存在提升 IRQL 的函数时调用可分页/`Zw*`/`MmMap*` | MEDIUM |
| 不安全的 MDL 映射 | 在反汇编中出现 `MmMapLockedPages`/`MmProbeAndLockPages`/等与 `UserMode` 一起 | HIGH,否则 MEDIUM |
| 栈分配 | `_alloca`/`_malloca`/`_chkstk` 调用(大或动态栈分配) | LOW |
| 未经验证大小的池分配 | `ExAllocatePool*` 调用,附近没有安全算术保护(溢出前整数溢出模式) | HIGH |
| 特权指令 | 从处理程序可到达的端口 I/O(`in`/`out`)、控制/调试寄存器移动(`mov cr*`/`mov dr*`)、描述符表加载、`cli`/`sti`/`hlt`(BYOVD 硬件访问原语) | CRITICAL(`out`)/ HIGH(`in`)/ MEDIUM |
| 任意写(write-what-where) | 通过双重解引用的用户指针 `*(*p) = c` 进行存储;受控拷贝 `*p = *q` 报告为较弱的线索 | HIGH / MEDIUM |
| `\Device\PhysicalMemory` 引用 | 物理内存设备对象字符串的交叉引用(通过 `ZwOpenSection`/`ZwMapViewOfSection` 的 BYOVD 模式) | HIGH(处理程序)、MEDIUM(其他) |
这些是**线索生成器**,并非确认的漏洞。将 HIGH/CRITICAL 的发现视为手动审查的起点。
## 功能标志
所有可选的分析阶段由 `DriverBuddyReloaded/config.py` 控制。编辑 `Feature` 类以启用或禁用它们:
| 标志 | 默认值 | 描述 |
|---|---|---|
| `IOCTL_SCAN` | `True` | 发现并解码 IOCTL(分发器扫描 + `IoControlCode` 回退) |
| `IOCTL_DECOMPILER` | `True` | 在分发器扫描中使用 Hex-Rays ctree(恢复跳转表/二分搜索代码) |
| `HEURISTICS` | `True` | 启发式漏洞检查(见上表) |
| `TOCTOU_CHECK` | `True` | 双重提取 / TOCTOU 启发式检查 |
| `UAF_DETECT` | `True` | 释放后使用启发式检查(函数内寄存器遍历 + 跨函数全局变量) |
| `ACL_AUDIT` | `True` | 标记全局可访问的 `IoCreateDevice` / 弱 `IoCreateDeviceSecure` SDDL |
| `SYMLINK_TRACK` | `True` | 解码 `IoCreateSymbolicLink` 目标路径 |
| `CALLCHAIN` | `True` | 从处理程序到危险接收器的 BFS 调用链追踪 |
| `EXPORTS_AUDIT` | `True` | 标记具有零内部交叉引用的驱动程序导出 |
| `POOLTAG_FALLBACK` | `True` | 寄存器传播的池标签扫描器(当基于导入的扫描未找到时使用) |
| `IRP_MJ_ENUM` | `True` | 创建 `IRP_MJ_FUNCTION` IDA 枚举并应用于 `MajorFunction` 槽(仅 WDM) |
| `RISK_SCORING` | `True` | IOCTL 风险评分(METHOD/ACCESS 权重 + 每处理程序接收器提升) |
| `RESULTS_WINDOW` | `True` | 分析后显示 Driver Buddy Reloaded 发现窗口 |
| `JSON_EXPORT` | `True` | 写入 `findings.json` |
| `HTML_REPORT` | `True` | 写入 `report.html` |
| `SEGMENT_OPCODE_SCAN` | `False` | 线性段范围操作码扫描(嘈杂,默认关闭) |
## 测试
三层测试,从快速到全面:
- **纯 Python 回归**(无需 IDA)- 涵盖所有不涉及实时数据库的逻辑: ```
python tests/test_dbr.py
DBR_SDK=900 python tests/test_dbr.py # simulate the IDA 9.0 import paths
.sys 文件矩阵运行完整流水线,并打印通过/失败表格:pwsh tests/run_cross_version.ps1。pwsh tests/run_golden.ps1 在 tests/drivers/ 中每个参考驱动程序的原始副本上重新运行完整分析,并将结果与已提交的 tests/drivers/<driver>.golden.json 基线进行比较(对类别、标题、严重性以及 IOCTL 代码/方法/访问不区分顺序)。任何新增的发现(误报)、缺失的发现(漏报)或严重性变化都会导致运行失败。仅在变更有意改变发现时才重新生成金文件,并检查差异。金文件与其捕获时所用的 IDA 反编译器构建版本(8.4)绑定,因此请使用该版本运行回归测试。_is_valid_ctl_code() 进行验证:设备类型字段(位 31-16)必须非零,且该值不得是已知 NTSTATUS 代码或 0xFFFFFFFF (DWORD)-1 标记(在实际调度程序中看到的比较常量,例如 WinRing0)。这样可以排除循环计数器、小立即数和错误代码,同时保留所有有效的 IOCTL,包括供应商定义的设备类型(0x8000+)。相同的过滤器应用于所有四个发现路径:IoControlCode 交叉引用扫描以及三个调度程序收集器(反编译器 ctree、IDA switch-table 恢复和原始立即操作数扫描)。DriverBuddyReloaded/config.py 中。DispatchDeviceControl 搜索仅适用于 x64 驱动程序。find_opcode_data 选项(默认为 False)会抑制数据段中的操作码匹配。将其切换为 True 也会暴露数据中的原始字节匹配,这容易产生误报;如果遗漏了真正的操作码,通常可以通过导航到报告的地址并重新将字节定义为代码来恢复。匹配结果像其他阶段一样报告(结果窗口、findings.json、report.html)。