内核呓语系列2 —— windows子系统

2013-12-18 Nie.Meining Coding

上一篇写到Windows将图形支持作为windows子系统的一部分放到了内核支持中。其实windows子系统既有内核部分也有用户态部分,其内核部分由win32.sys实现,负责窗口管理(会话、窗口站、桌面)和GDI。win32.sys对应用层不处理任何IO请求,只作为内核功能扩展导出Shadow SSDT表向用户层提供大量系统服务。因此基于这个定位,win32.sys不是一个完整的内核驱动,而是一个内核动态链接库,其加载方式是 MmLoadSystemImage + call oep。

任何一个线程,只要调用了Shadow SSDT中的函数则会转变成一个GUI线程(PsConvertToGuiThread),纳入csrss.exe的管理范畴。转换过程包括分配子系统相关的对象、切换一个更大的内核栈(KeSwitchKernelStack)、切换KeServiceDescriptorTableShadow 等。具体可以参考wrk。另外,win32.sys 并不常驻内存,因此在有些进程中可能看不到Shadow SSDT表(例如 system):

nhyy2_1.png

因此需要先通过attach到一个别的进程中(最好是一个GUI进程)中:

nhyy2_2.png

这样就看到Shadow SSDT中的内容了。

这个特性也导致hook Shadow SSDT不能像hook SSDT一样直接简单粗暴,因为DriverEntry是运行在system地址空间中的。此外还有一点与SSDT不同,Shadow SSDT的地址不导出,因此hook Shadow SSDT需要attach到别的GUI进程中并查找Shadow SSDT的地址,通常的方法是在 KeAddSystemServiceTable 附近搜索 0x888d 特征值:

nhyy2_3.png

也有的代码通过KeServiceDescriptorTable +/- 偏移定位 KeServiceDescriptorTableShadow,因为Windows中这连个东西是内存中是连续的:

nhyy2_4.png

不过觉得直接从GUI线程中读取 KTHREAD.ServiceTable 域会更加方便,而且系统版本依赖性更小:

nhyy2_5.png

更多的细节就留到讲系统服务的时候再讲吧。

除了内核部分,windows子系统也有用户模式部分,主要由csrss.exe进程和一堆dll(user32.dll等)组成。csrss.exe是windows环境子系统进程,负责管理windows子进程中的进程、线程的创建、删除等。所以遍历csrss.exe的句柄表是检测隐藏进程、线程的一种方法(同时也是突破进程、线程保护复制句柄的一种方法)。

正因为windows子系统整合到了内核中,因此即使没有交互用户登录到windows服务器,windows子系统也是必须运行的,这跟linux的xwindow有很大差异。原则上来讲,任何应用程序都运行在windows子系统中,即使是CUI程序(例如命令行cmd.exe)也必须依靠宿主进程处理windows子系统的消息循环。Windows XP以前CUI的宿主进程是csrss.exe,后来出于安全考虑,vista过后每个CUI会对应一个自己的conhost.exe宿主:

nhyy2_6.png

今天先到这里了,windows子系统中还有一些有趣的部分,留到下次再讲吧。

评论:

XRumerTest
2014-06-01 18:44
Hello. And Bye.
0x01f
2014-04-09 17:24
“由win32.sys实现”这是笔误了吧?

发表评论:

Powered by emlog