mqac文件函数ACDeviceControl漏洞分析
字数 1714 2025-08-22 12:22:24
MQAC文件函数ACDeviceControl漏洞分析教学文档
1. 背景知识
1.1 Windows驱动通信机制
在Windows系统中,驱动程序使用设备控制代码(IOCTLs)与用户态应用程序进行通信:
- 接收来自应用程序的命令(如打开、读取、写入或配置设备的操作)
- 在硬件层面上执行这些操作
- 将结果返回给发起请求的应用程序
1.2 ACDeviceControl函数
ACDeviceControl是一个回调函数,用于处理用户端发来的设备控制命令。其关键参数:
a2:IRP(I/O Request Packet)类型的数据结构- 主要调用
ACSendMessage函数处理请求
2. 关键函数分析
2.1 ACSendMessage函数
Information = ACSendMessage(Irp, Options, (CQueue *)FileObject->FsContext, (struct CACSendParameters *)UserBuffer);
参数解析:
Options:来自CurrentStackLocation->Parameters.Create.OptionsFileObject:来自CurrentStackLocation->FileObjectUserBuffer:来自Irp->UserBuffer
函数内部流程:
- 初始化两个内存指针
- 检查
(CQueue *)this是否有效(CFG检查) - 检查
UserBuffer合法性 - 将
UserBuffer指向v19,循环5次,每次偏移0x80 - 交换4个指针
- 调用
ACDeepProbeSendParams将用户态数据复制到内核态
2.2 ACDeepProbeSendParams函数
主要操作:
- 检查
UserBuffer偏移量:- 0x94、0x98、0x9c、0xA0
- 如果为假,设置对应偏移0x49、0x4B、0x4D、0x4F处指针指向0
- 调用
ACDeepProbeMsgPropsForSend(a1, a2)进行进一步数据复制 - 检查
(char *)*((_QWORD *)a1 + 0x49)和(char *)*((_QWORD *)a1 + 0x4B)是否为真- 如果为真,调用
ACDeepCopyQueueFormat复制队列格式
- 如果为真,调用
2.3 ACDeepCopyQueueFormat函数
关键行为:
- 接收三个参数:用户层队列格式、大小、内核层队列格式
- 根据用户提供的大小在内核层分配内存
- 如果分配不成功,尝试分配另一种标签的内存
- 分配的分页内存块大小来自
UserBuffer(用户控制) - 安全问题:分配时没有加锁
2.4 ACFreeDeepCopyQueueFormat函数
释放内存的关键点:
- 释放内存的大小从
UserBuffer获取,而非创建时的值 - 释放逻辑:
- 根据不同类型从不同偏移量释放,每次释放0x20大小
- 类型3或8:从偏移0x8处释放
- 类型6:从偏移0x10处释放
- 直到
NumElement减为0,释放所有元素后释放分页内存
- 根据不同类型从不同偏移量释放,每次释放0x20大小
- 安全问题:释放内存时没有加锁
3. 漏洞原理
3.1 条件竞争漏洞
漏洞成因:
- 内存分配和释放的大小完全由用户控制
- 分配和释放操作都没有加锁保护
- 导致可能的竞争条件:
- 线程A:持续分配内存(设置较小的大小值)
- 线程B:在内存中修改分配的分页内存大小
- 结果:影响释放内存时的释放大小,可能导致任意内存释放
3.2 漏洞触发过程
- 在分配分页内存和释放内存处设置断点
- 观察两个内存的大小值
- 典型崩溃场景:
- 最后一次操作中,一个大小为1,另一个大小为10000
- 导致程序崩溃
- 触发具有随机性(文档中提到第4次就触发了)
4. 漏洞利用分析
4.1 利用条件
- 能够控制
UserBuffer内容 - 能够创建多个线程并发操作
- 能够精确控制内存分配和释放的时序
4.2 潜在影响
- 任意内存释放可能导致:
- 内核内存破坏
- 权限提升
- 系统崩溃(蓝屏)
5. 防护建议
-
输入验证:
- 对用户提供的
UserBuffer大小进行严格验证 - 设置合理的最大最小值限制
- 对用户提供的
-
同步机制:
- 在内存分配和释放操作中加锁
- 使用适当的同步原语(如自旋锁)
-
内存管理:
- 分配和释放时使用一致的大小值
- 考虑使用内核池标记技术
-
防御性编程:
- 检查内存操作返回值
- 实现安全的内存释放机制