欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

WINDOWS 7 RC 7100 GDI驱动Win32k.sys内核D.O.S漏洞

程序员文章站 2022-04-07 18:00:56
感谢:Iceboy发现此问题并提供DUMP 漏洞厂商及产品:Microsoft Windows 7 rc 7100 090421 存在漏洞组件:win32k.sys Timestamp :49ee8dc8 存在漏洞函数:NtUserGetDc/NtUserGetDcEx ... 09-05-24...

感谢:iceboy发现此问题并提供dump
漏洞厂商及产品:microsoft windows 7 rc 7100 090421
存在漏洞组件:win32k.sys timestamp :49ee8dc8
存在漏洞函数:ntusergetdc/ntusergetdcex

漏洞描述:win32k.sys是windows的gdi驱动程序,包含大量复杂的图形界面处理,由于其中大量代码是从win3.1中修改过来,因此成了windows漏洞多发之地。

这个漏洞主要是因为windows 7 在其ntusergetdc/ntusergetdcex函数中(也许不仅仅是这两个函数)不正确地使用了共享临界锁,导致了任何权限下的gdi程序可以引发内核bsod,从而进行dos攻击
 

漏洞分析:
在windows vista中,在这两个函数进入前,会调用userenterusercirtsec,进入临界区,同时会将gpticurrent设置为当前线程的win32thread

userenterusercritsec的实现如下:

pwin32thread userenterusercritsec()
{

pwin32thread pwin32thread;

pwin32thread = exenterpriorityregionandacquireresourceexclusive(gpresuser);
gpticurrent = pwin32thread;
gbvalidatehandleforil = 1;
return pwin32thread;
}

exenterpriorityregionandacquireresourceshared是ntoskrnl 导出一个提供给win32k使用的共享资源锁函数,这个函数将共享锁住gpresuser这个资源,同时返回当前线程的win32thread,即 kegetcurrentthread->win32thread

同时内核函数exenterpriorityregionandacquireresourceexclusive也与其类似。
(xp则是调用keentercriticalregion后,用exacquireresourceexclusivelite锁住 gpresuser,然后用psgetcurrentthread->psgetthreadwin32thread获得当前线程 win32kthread,存放到gpticurrent)

而在windows 7 中,这两个函数进入前,改为了调用userentersharedcrit,进入共享临界区

userentrysharedcirt的实现很简单

pwin32thread entersharedcrit()
{
return exenterpriorityregionandacquireresourceshared(gpresuser);
}

可以注意到,这里并不设置gpticurrent,事实上,ntusergetdc/ntusergetdcex会将这个函数保存在寄存器中以便使用currentwin32thread中存放的数据

从关键临界转为共享临界,无疑这样的修改将提升ntusergetdc/ntusergetdcex的效率,减少了锁竞争的可能,但是在这里这样修改是错误的.

因为在共享临界中,没有修改gpticurrent,那么就很可能遇到gpticurrent非法的状态,比如遇到一个没有做psconverttoguithread的线程导致了gpticurrent为空.

win32k中有大量内部例程(经常以zzz,xxx开头),他们都认为在调用自己之前,gpticurrent是一个有效的状态。这其中就包括了xxxdestorywindow

一个bsod的例子是:ntusergetdc->getwindowdc->getdcex->spbcheckdce->spbcheckrect->spbcheckrect2->freespb

调用到freespb时,这里要释放一个spb对象了

接着就到
freespb->hmassigmentunlock->hmunlockobject->hmunlockobjectinternal->hmdestroyunlockedobject, 最终调用到了ganti表中的函数,由于这里是getwindowdc,所以将调用xxxdestroywindow,xxxdestroywindow 第一句代码就无检查引用了gpticurrent指针中的数据,自然直接导致bsod

解决方案:
等待微软更新官方补丁.

微软可能的更新手段:
牺牲效率将ntusergetdc等中的不正确共享锁替换为关键临界锁,或者将所有ntusergetdc等函数可能用到的内部函数中的gpticurrent引用去掉或换为不引用gpticurrent的其他函数