VoidSec/DriverBuddyReloaded

GitHub: VoidSec/DriverBuddyReloaded

一款 IDA Pro 插件,通过自动化逆向分析与启发式漏洞检测,显著简化 Windows 内核驱动程序的安全审计流程。

Stars: 429 | Forks: 59

# Driver Buddy Reloaded 快速入门 ## 目录 - [Driver Buddy Reloaded 快速入门](#driver-buddy-reloaded-quickstart) - [目录](#table-of-contents) - [安装说明](#installation) - [快速使用](#quick-usage) - [高级用法](#advanced-usage) - [关于 Driver Buddy Reloaded](#about-driver-buddy-reloaded) - [查找 DispatchDeviceControl](#finding-dispatchdevicecontrol) - [标记 WDM 和 WDF 结构](#labelling-wdm-and-wdf-structures) - [查找并解码 IOCTL 代码](#finding-and-decoding-ioctl-codes) - [标记函数](#flagging-functions) - [查找 DeviceName](#finding-devicename) - [导出 Pooltags](#dumping-pooltags) - [启发式漏洞检测](#heuristic-vulnerability-checks) - [功能开关](#feature-flags) - [已修复的问题](#fixed-issues) - [已知的注意事项与限制](#known-caveats-and-limitations) - [致谢与感谢](#credits-and-acknowledgements) ## 安装说明 将 `DriverBuddyReloaded` 文件夹和 `DriverBuddyReloaded.py` 脚本文件复制到 IDA plugins 文件夹中,例如: - `%APPDATA%\Hex-Rays\IDA Pro\plugins\` - `C:\Program Files\IDA Pro 8.4\plugins\` - `~/.idapro/plugins/` 如果你的 IDA 配置的是 Python 2,请运行 `idapyswitch` 可执行文件(位于 IDA 的文件夹中)将其切换到 Python 3。 **注意:** Driver Buddy Reloaded 运行在 IDA 7.x、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. 查看“Output”窗口获取分析结果,以及运行结束时打开的 **Driver Buddy Reloaded - Findings** 窗口(双击某一行即可跳转到对应地址)。 4. 以下文件将被写入 IDA 的 DB 目录下(均以 `-YYYY-MM-DD-TIMESTAMP-` 为前缀): - `autoanalysis.txt` - 完整的文本分析日志 - `findings.json` - 机器可读的分析结果(IOCTLs、被标记的函数、设备名称、pooltags、调用链) - `report.html` - 独立的、按严重程度分组的 HTML 报告 - `ioctl_pocs.c` - 按严重程度排序的 `DeviceIoControl` PoC 骨架代码 - `pooltags.txt` - 以 WinDbg 可用的 `pooltags.txt` 格式导出的 Pooltags 要解码单个 IOCTL: 1. 将鼠标光标放在包含疑似 IOCTL 代码的行上。 2. 右键点击并选择 `Driver Buddy Reloaded -> Decode IOCTL`;或者按下 `CTRL+ALT+D` 快捷键。 要解码函数内的所有 IOCTL: 1. 将鼠标光标放在你认为是 IOCTL 派发函数( `DispatchDeviceControl`、`DispatchInternalDeviceControl`、`Possible_DispatchDeviceControl_#`)的第一条指令上 2. 右键点击并选择 `Driver Buddy Reloaded -> Decode ALL IOCTLs in Function`;或者按下 `CTRL+ALT+F` 快捷键。 3. 一个包含到目前为止所有已解码 IOCTL 的 `DriverName.sys-2021-12-10-TIME_STAMP-IOCTLs.txt`/`DriverName.sys-2021-12-10-TIME_STAMP-IOCTLs.txt_dumb.txt` 文件 将被写入 IDA 的 DB 目录下。 ### 高级用法 - [vulnerable_function_lists](DriverBuddyReloaded/vulnerable_functions_lists) 目录包含了一系列潜在的 危险/问题函数、Windows API 和操作码的列表;并提供了关于特定函数/API 为何被列入其中的简要描述。你可以编辑 `custom` 列表以加入驱动程序的特定函数。 **注意**:`winapi_function_prefixes` 会对函数名的开头进行部分匹配(例如 `Zw` 会匹配到 `ZwClose`、`ZwCommitComplete` 等),而 `winapi_functions` 仅执行完全匹配。 - 在 [find_opcodes.py](DriverBuddyReloaded/find_opcodes.py) 中,`find_opcode_data` 选项会阻止 Driver Buddy Reloaded 在数据段中查找操作码。将其设置为 `True` 将会输出类似此[行](https://github.com/VoidSec/DriverBuddyReloaded/issues/11)的信息: `Found jnz short loc_15862 in sub_15820 at 0x00015852` 通常,前往显示的地址并将该区域重新定义为代码,即可找回所搜索的操作码。 **注意**:将其切换为 `True` 将会产生更多的误报! ## 关于 Driver Buddy Reloaded **Driver Buddy Reloaded** 是一个 IDA Pro 的 Python 插件,旨在帮助自动化完成一些繁琐的 Windows 内核驱动程序逆向 工程任务。它具有许多实用的功能,例如: * 识别驱动程序的类型(WDM, KMDF, UMDF, Mini-Filter, Stream Minidriver, AVStream, PortCls) * 定位 `DispatchDeviceControl` / `DispatchInternalDeviceControl` 函数 * 为 `WDF` 和 `WDM` 驱动程序填充通用结构 * 尝试识别并标记如 `IRP` 和 `IO_STACK_LOCATION` 等结构 * 为通常未被标记的 `WDF` 函数调用添加标签 * 创建一个 `IRP_MJ_FUNCTION` IDA 枚举,并将其应用到 `DriverEntry` 的 `MajorFunction` 数组槽中(WDM) * 查找并解码 IOCTL 代码 * 对已识别的派发函数进行自动化流程图扫描(无需手动放置光标) * 从 IDA 类型数据库中动态解析 NTSTATUS 值(无需静态列表) * 标记容易被滥用的函数 * 查找潜在的 `DeviceName`(mmap 扫描 + IDA Strings DB 后备,附带源地址) * 导出 `Pooltags`(基于导入表的主扫描 + 针对暂存于寄存器中的标签的寄存器传播后备扫描) * **启发式漏洞检测**:未经验证的用户拷贝、缺失的权限检查、IRQL 不匹配、不安全的 MDL 映射、栈分配的缓冲区(`_alloca`) - 参见 [启发式漏洞检测](#heuristic-vulnerability-checks) * **导出审计**:标记内部交叉引用为零的驱动程序导出项(潜在的攻击面) * 对解码出的 IOCTL 进行**风险评分**(优先考虑 `METHOD_NEITHER` / `FILE_ANY_ACCESS` 以及触达 诸如 `MmMapIoSpace`、`memcpy`、`__writemsr` 等危险接收器的处理程序),并按严重程度在 可点击的结果窗口中展示所有发现(双击可跳转至对应地址) * 追踪从派发程序 / IOCTL 处理程序到危险接收器的**调用链**(启发式、基于名称) * 将结果导出为机器可读的 **JSON** 文件、独立的 **HTML 报告**,以及生成的 **C/C++ `DeviceIoControl` PoC harness**,以快速启动测试/模糊测试 ![](/screenshots/auto-analysis.png) ### 查找 DispatchDeviceControl 该工具能够自动定位并识别 `DispatchDeviceControl` 例程。此函数用于将所有 传入的 `DeviceIoControl` 代码路由到与该代码关联的特定驱动程序函数。自动识别 此函数使得查找每个驱动程序的有效 `DeviceIoControl` 代码变得更加快捷。此外,当 调查由于崩溃导致的驱动程序潜在漏洞时,了解该函数的位置有助于将注意力缩小到 与引发崩溃的 `DeviceIoControl` 代码关联的特定函数调用上。 - `DriverEntry`:驱动程序加载后调用的原始的第一个驱动程序提供的例程。它负责 初始化驱动程序。 - `Real_Driver_Entry`:通常是 `DriverEntry` 的执行流程转移到的函数。它 通常是初始化 `DeviceName` 的地方。 - `DispatchDeviceControl`/`DispatchInternalDeviceControl`:如果工具能够恢复特定偏移量处的函数, 这些函数将被重命名为相应的名称。 - `Possible_DispatchDeviceControl_#`:如果工具无法恢复 `DispatchDeviceControl` 或 `DispatchInternalDeviceControl`,它会采用一种实验性的搜索方法,跟踪执行流,并 检查函数是否正在加载已知的 `IO_STACK_LOCATION` 和 `IRP` 地址;这表明该函数 可能就是 DispatchDeviceControl。由于这是基于启发式的,它可能会返回多个结果,并且 很容易产生误报。 ![](/screenshots/finding-dispatchdevicecontrol.png) ### 标记 WDM 和 WDF 结构 所有的 `WDM`/`WDF` 驱动程序共享一些驱动程序结构。该工具能够自动识别这些 结构,例如 `IO_STACK_LOCATION`、`IRP` 和 `DeviceObject` 结构,这有助于在 逆向工程过程中节省时间,并为正在使用这些函数的驱动程序区域提供上下文信息。 ![](/screenshots/WDM-structures.png) ### 查找并解码 IOCTL 代码 在对驱动程序进行逆向时,作为分析的一部分,通常会遇到 IOCTL 代码。这些代码解码后 会揭示有用的信息,并可能将注意力吸引到驱动程序中更有可能 存在漏洞的特定部分。 右键点击潜在的 IOCTL 代码,会弹出一个上下文菜单选项(或者当光标位于包含疑似 IOCTL 代码的行上时,使用 `Ctrl+Alt+D` 快捷键),该选项可用于解码该值。这会输出一个包含所有已解码 IOCTL 代码的表格。在反汇编视图中, 右键点击已解码的 IOCTL 代码时,可以将其标记为无效;这将保留任何非 IOCTL 的注释不变。 如果你右键点击(或者使用 `Ctrl+Alt+F` 快捷键),在你认为是 IOCTL 派发程序( `DispatchDeviceControl`、`DispatchInternalDeviceControl`、`Possible_DispatchDeviceControl_#`)的函数的第一条指令上,在 Driver Buddy Reloaded 菜单下,会出现一个“**Decode All**”选项,它会尝试解码它在该函数中能找到的所有 IOCTL 代码。 这有点取巧,但大多数情况下它可以加快分析速度。 - 一个包含所有已解码 IOCTL 的 `IOCTLs.txt` 文件(以 `-YYYY-MM-DD-TIMESTAMP-` 为前缀)将被 写入到 IDA 的 DB 目录下。 此外,自动分析会对已识别的派发函数进行流程图扫描,从而自动发现 IOCTL,而无需手动放置光标。 ![](/screenshots/IOCTL-table.png) ![](/screenshots/decode-IOCTL.png) ### 标记函数 Driver Buddy Reloaded 包含一系列 C/C++ 函数、操作码和 Windows API(定义在 [vulnerable_function_lists](DriverBuddyReloaded/vulnerable_functions_lists) 目录中),这些通常是存在漏洞的, 或者可能引发缓冲区溢出条件。在自动分析期间会报告所有找到的实例, 这有助于寻找可能触达敏感函数的受用户控制的代码路径。 ![](/screenshots/flagging-functions.png) ### 查找 DeviceName 该工具会自动尝试查找驱动程序注册的设备路径(`DeviceName`),如果通过 查看二进制文件中的 Unicode 字符串无法找到任何路径,那么分析师可以手动尝试使用 Madiant 的 [FLOSS](https://github.com/mandiant/flare-floss/) 来尝试寻找混淆的路径。 ![](/screenshots/devicename.png) ### 导出 Pooltags 在自动分析过程中,该工具还会以适用于 `pooltags.txt` 的格式导出二进制文件使用的 `Pooltags`。 随后可以将输出内容复制粘贴到该文件的末尾,并由 WinDbg 读取。 - 一个包含所有导出的 Pooltags 的 `DriverName.sys-2021-12-10-TIME_STAMP-pooltags.txt` 文件,将被写入到 IDA 的 DB 目录下。 ![](/screenshots/pooltag.png) ### 启发式漏洞检测 `heuristics.py` 模块在调用链追踪完成后运行,并检查每个识别出的派发处理程序函数。 它会在 **heuristic**(启发式)类别中输出检测结果: | 检查项 | 标记对象 | 严重程度 | |---|---|---| | 未经验证的用户拷贝 | 附近没有 `ProbeForRead`/`ProbeForWrite`/安全字符串防护的 `memcpy`/`RtlCopyMemory`/等 | HIGH(处理程序),MEDIUM(其他) | | 缺失权限校验 | 函数中没有 `SeSinglePrivilegeCheck`/`SeAccessCheck` 的ZwOpenProcess`/`ZwAllocateVirtualMemory`/等 | HIGH | | IRQL 不匹配 | 当存在提升 IRQL 的函数时,调用了 Pageable / `Zw*` / `MmMap*` | MEDIUM | | 不安全的 MDL 映射 | 反汇编中包含 `UserMode` 的 `MmMapLockedPages`/`MmProbeAndLockPages`/等 | HIGH,否则为 MEDIUM | | 栈分配 | 调用 `_alloca`/`_malloca`/`_chkstk`(大型或动态栈分配) | LOW | 这些是**线索生成器**,而不是已确认的漏洞。请将 HIGH/CRITICAL 级别的发现视为手动审查的起点。 ## 功能开关 所有可选的分析阶段均由 `DriverBuddyReloaded/config.py` 控制。编辑 `Feature` 类即可 启用或禁用它们: | 标志 | 默认值 | 描述 | |---|---|---| | `HEURISTICS` | `True` | 启发式漏洞检测(拷贝验证、权限校验、IRQL、MDL、alloca) | | `EXPORTS_AUDIT` | `True` | 标记内部交叉引用为零的驱动程序导出项 | | `POOLTAG_FALLBACK` | `True` | 寄存器传播的 pool tag 扫描器(在基于导入的扫描未发现任何内容时使用) | | `IRP_MJ_ENUM` | `True` | 创建 `IRP_MJ_FUNCTION` IDA 枚举并应用于 `MajorFunction` 插槽(仅限 WDM) | | `CALLCHAIN` | `True` | 从处理程序到危险接收器的 BFS 调用链追踪 | | `RISK_SCORING` | `True` | IOCTL 风险评分(METHOD/ACCESS 权重 + 接收器权重提升) | | `RESULTS_WINDOW` | `True` | 分析后显示 Driver Buddy Reloaded 的结果窗口 | | `JSON_EXPORT` | `True` | 写入 `findings.json` | | `HTML_REPORT` | `True` | 写入 `report.html` | | `POC_HARNESS` | `True` | 写入 `ioctl_pocs.c` PoC harness | | `SEGMENT_OPCODE_SCAN` | `False` | 线性段级操作码扫描(噪音较大,默认关闭) | ## 已修复的问题 以下上游问题在 v1.1.0 版本中已解决: | 问题 | 描述 | |---|---| | [#31](https://github.com/VoidSec/DriverBuddyReloaded/issues/31) | 未将 `GsDriverEntry`(IDA 8.2+ 的 security-cookie 包装器)识别为驱动程序入口点 | | [#30](https://github.com/VoidSec/DriverBuddyReloaded/issues/30) | 当通过 IDA Strings DB 解析时,`DeviceName` 的查找结果现在包含源地址(EA) | | [#29](https://github.com/VoidSec/DriverBuddyReloaded/issues/29) | 当存在 WDF 库前缀时,驱动程序类型被报告为 "WDF" 而不是 "KMDF" 或 "UMDF" | | [#27](https://github.com/VoidSec/DriverBuddyReloaded/issues/27) | 在 IDA < 7.6 上加载时显示明确的错误信息;记录了支持的最低版本 | | [#25](https://github.com/VoidSec/DriverBuddyReloaded/issues/25) | 创建了 `IRP_MJ_FUNCTION` IDA 枚举并应用于 `DriverEntry` 中的 `MajorFunction` 数组操作数 | | [#16](https://github.com/VoidSec/DriverBuddyReloaded/issues/16) | 错过了通过寄存器传播的 Pool tags(在 alloc 调用之前暂存于 `mov reg, 'ABCD'` 中) | | [#15](https://github.com/VoidSec/DriverBuddyReloaded/issues/15) | NTSTATUS 过滤器现在使用 IDA 类型数据库而不是静态列表(如果枚举不存在,则回退到一个小型的硬编码集合) | ## 已知的注意事项与限制 - 为了防止出现大量误报,仅会自动解码 >= `0x10000` 的 IOCTL 值。[Issue #15](https://github.com/VoidSec/DriverBuddyReloaded/issues/15) - 风险评分和调用链追踪是**启发式的、基于名称的线索生成器**,而不是数据流分析;请将 High/Critical 级别的发现视为优先检查的地方,而不是已确认的漏洞。功能开关位于 `DriverBuddyReloaded/config.py` 中。 - 实验性的 `DispatchDeviceControl` 搜索仅适用于 x64 驱动程序 - 快捷键与 F-Secure 的 [win_driver_plugin](https://github.com/FSecureLABS/win_driver_plugin) 不兼容 - 快捷键与 [findcrypt-yara](https://github.com/polymorf/findcrypt-yara) 不兼容 - 在 [find_opcodes.py](DriverBuddyReloaded/find_opcodes.py) 中,`find_opcode_data` 选项会阻止 Driver Buddy Reloaded 在数据段中查找操作码。将其设置为 `True` 将会输出类似此[行](https://github.com/VoidSec/DriverBuddyReloaded/issues/11)的信息: `Found jnz short loc_15862 in sub_15820 at 0x00015852` 通常,前往显示的地址并将该区域重新定义为代码,即可找回所搜索的操作码。 **注意**:这很容易产生误报!
标签:IDA插件, Python, Web报告查看器, Windows驱动, 云资产清单, 无后门, 逆向工具, 逆向工程