日期:2014-05-17  浏览次数:20830 次

win9x kernel 16/32bit 混合的悲剧
你曾经在win98下,调用过rundll kernel, ExitKernel 吗?调用的结果是:会立即无警告自动关机/重启 
  
Win16有一个退出系统的公开API ExitWindows,(Win32下叫ExitWindowsEx),在Windows3.x下,ExitWindowsEx的实现是通过调用user和kernel中的一系列东西,首先通过QueryQuitEnum来关闭所有窗口,然后关闭剪贴板和鼠标指针,就是所有牵涉到回调的函数,都必须导出,因此这个极端危险的调用,就被kernel导出了。 
  
Win98的所谓32位,其实也是在win3的386增强模式上加了一大堆东西:一个新的虚拟内存和虚拟设备驱动程序系统。但是,关机过程其实跟我上述讲得差不多,而为了保持和16位程序最大的兼容,win16库的函数导出表没有太大变化,就是一些win1.x/2.x的老函数删除了而已,事实上还是win16的内核上面实现了一套win32。因此,一旦win16部分调用了 ExitKernel();然后还有个问题,Win9x下因为有向下twunk的机制,32位程序也能调用win16的函数,因此任何程序都能调用ExitKernel(),这个函数实现的功能,和Win3.x下基本相同,然后没有任何验证,因此,win9x下只要任何东西调用了它,win9x内核就会在没有完成正常退出的准备下强制退出。 
  
当初一些word宏病毒,就调用了这个api,win9x下任何程序都能在CPU的特权极之间穿梭无阻,能直接把任何一段代码赋予vxd的权限。(例如,CIH) 
  
NT下ExitWindowsEx,自体只能实现注销功能,你如果要关机,先要申请进程权限,到能够关机的某个权限,然后ExitWindowsEx这个Win32层的函数,还不能直接调用NT层的关闭系统,还需要通过LPC去访问smss。smss负责完成win32子系统的关闭,之后再调用NT层ntdll.dll的函数NtShutdownSystem,完成NT内核的关闭过程。 
  
而nt下虽然有NtShutdownSystem,但是这个必须在驱动的权限上,才能调用。而且还有个更强大的函数NtSetSystemPowerState,可以直接控制电源管理关闭电源,但是都需要很高权限,不会出现win9x系统那种毫无限制的状况。 
  
win16下还有大量已经导出的危险函数,比如关闭显示驱动的Death()、User的DISABLEOEMLAYER,User的DISABLEOEMLAYER,这个可以把键盘、鼠标驱动一起停止,导致系统假死。之后,一个kernel中的对全局内存对象分配的函数,居然不检查输入,GlobalRealloc本来应该有三个参数,但是rundll输入一个居然能调用成功,因为压进了不明数据,因此整个内核的全局内存对象,可能因此而完全出错,导致死机。往globalrealloc的参数栈里压入了rundll32内存中的东西,因为未指定后两个参数,比如原来第二个参数是指定重新分配到多少,是个size_t,也就是32位整数,压进了很大的数的话,会数据溢出,分配不了,直接导致干掉整个系统,这次异常情况本身不会引起其他机制的触发,但是系统会试图分配超大内存,这个bug在95,98SE里有,ME好像改了。 
  
在win16下,任何能执行API的带编程机能的程序,都能实现“自杀”,例如调用DisableKernel,在NTVDM下是导致死循环出现这个(见附图),win3 win9x下,就是死机了 
[img]http://i25.tinypic.com/rsyl9k.jpg[/img] 
  
  
还有一些一些搞不清用途的导出,例如:K327,K329,K403,K404。这是微软早期开发风格遗留的。 


---------感谢程序员ACF群的yk同学一起研究----------

------解决方案--------------------
额,认真仔细的看完,