Windows condrv.sys 本地拒绝服务漏洞分析

今天这个蓝屏比较火,故做了下分析

直接原因分析:
漏洞堆栈如下:
324496_R6DRMXJ9CWBRD39

从堆栈可以看到,当用户态打开路径.globalrootdeviC++econdrvkernelconnect时,内核对象管理器会依次解析对象目录,直到解析到devicecondrv 发现这是个设备对象,而设备对象的设备类型是有ParseProcedure例程的.故调用设备的对象的ParseProcedure即函数IopParseDevice. 函数内部在处理完请求会去关闭打开的文件对象.
324496_M8BAEGKRJA834HY

关闭文件对象内核会调用相应的驱动的IRP例程. IRP_MJ_CLEANUP 以及IRP_MJ_CLOSE。
即condrv驱动的函数:CdpDispatchCleanup CdpDispatchClose.

而CdpDispatchCleanup在处理IRP_MJ_CLEANUP时会尝试引用文件对象FILE_OBJECT的FsContext成员,此成员应该为驱动condrv自己创建的一个透明数据结构.但是事实是这个成员是未预期的值NULL. 所以导致空指针引用蓝屏.如下图:

324496_RBZS4F9JVRWKPGN
324496_4MYZSY5T5DT5ZWT

根因分析:
我们可以假设这个文件对象是“非法”的,那么可能从它创建初始化的时候就出现问题。对内核有了解的应该知道,如果要引用设备对象那么必然要有打开操作即肯定要向condrv驱动发送IRP: IRP_MJ_CREATE 那么我看下condrv驱动的Create例程:
324496_X2GFQ55CV9A853S

如上图所示,它其实是在循环比较要打开的文件名是不是预先定义的如果是则调用相应的回调函数 如下图:
324496_HCVKXWTSQDTH5VC
由于Poc打开的是kernelconnect 所以我们看下函数CdCreateKernelConnection
324496_EA3CJPG566EV4YC

第一个判断就是如果先前模式是usermode 则返回拒绝. 也就是condrv驱动的设计初衷就是不允许用户态直接访问这个符号链接.

但是问题出就处在此处返回拒绝上. 因为这是在处理IRP,它没有设置IRP的状态码以及调用IoCompleteRequest 来结束IRP.
324496_MS3Q5K62XB5R8YB

如上图可以看到Irp->IoStatus.Status 为0. 而0 表示成功.
而在IopPraseDevice中是以IRP的IoStatus.Status成员来判断IoCallDriver是否成功.也就是本意是拒绝用户态打开这个符号链接,但实际因为开发疏忽导致内核认为打开成功.此时文件对象的fscontext成员没有被condrv赋值. 所以当关闭文件对象时,导致蓝屏。实际测试修改
IRP的IoStatus.Status的值为失败时,不会蓝屏。

总结:
其实归根到底就是condrv的驱动开发人员在处理IRP_MJ_CREATE时,没有正确处理拒绝情况, 导致本应该失败的 内核误以为是成功. 进而在后续对文件对象的操作时蓝屏.

转载自看雪论坛,原文地址:https://bbs.pediy.com/thread-265438.htm

标签