打印

[分享] 如何调试Windows子系统的服务器进程(csrss.exe)

如何调试Windows子系统的服务器进程(csrss.exe)

Windows环境子系统进程(CSRSS.EXE,简称CSRSS)是WINDOWS子系统服务器进程。尽管从NT4开始,窗口管理(包括屏幕输出、用户输入和消息传递)和GDI的主体实现移入到内核(win32k.sys)中,但CSRSS仍然是WINDOWS子系统的灵魂,它监管着系统内运行着的所有WINDOWS进程和线程,每个进程在创建后都要到它这里注册登记后方能运行,退出时也要到这此报告注销。除了掌管着各个进程的“生死存亡”,CSRSS在桌面管理、终端登录、控制台管理、HANDERROR报告和DOS虚拟机等方面也起着重要作用。总之,把CSRSS称为WINDOWS系统的“大内总管”不算为过。CSRSS身担如此多的重任,所以WINDOWS系统真的离不开它,如果尝试强行杀死CSRSS进程(使用KILL或其他工具),那么系统便会以蓝屏(BSOD,BLUE SCREEN OF DEATH)结束。


尽管CSRSS在WINDOWS系统中地位重要,但关于它的介绍却如凤毛麟角。就连著名的WINDOWS内幕一书对它的介绍也如蜻蜓点水。微软的文档也从未见过关于CSRSS原理和设计的正式介绍,在MSDN中搜索一下,找到的大多都是CSRSS有关的系统故障信息。因此,可以说CSRSS是WINDOWS世界中被“保密”的最好的模块之一。这种神秘性使得很多WINDOWS领域的老将也不大熟悉CSRSS这个名字,更不知道它长什么样。有时竟还以为它是病毒呢。不过不管你是否熟悉它,CSRSS始终在每一个WINDOWS系统(不包括3.X或更早的WINDOWS)中运行着,而且起着不可土地替代的作用。


那么是不是真的没有必要了解CSRSS呢?NO,因为其地位的重要性,要了解某些WINDOWS机制(如进程管理,控制台窗口,用户态调试,Harderror等),探索它又变的无法回避。


没有文档,没有代码,如何了解CSRSS呢?对于这样的难题,调试跟踪无疑是最佳利刃,然而这也不是件容易的事。


首先,因为CSRSS是WINDOWS的关键进程,关乎系统安全之大计,所以缺省状态下,系统是禁止CSRSS的调试的。别外对于WINDOWS2000或之前的版本,CSRSS是调试子系统的一部分,所以如要不启动特别选项,调试对话也是无法建立和工作的。

其次,不要以为这个大内总管很悠闲,在一个典型的WINDOWS XP系统中,CSRSS通常有十几个工作纯种在打理着系统的日常工作,虽然它们总共占用的CPU资源也就在1~2%左右,使用PSTAT观察一下,你会发现它们大多数是忙碌着的,模式切换次数很高,说明它们频繁奔走在内核态和用户态之间。更严重的是,当我们在调试器调试CSRSS时,那么中断到调试器必然导致CSRSS进程被挂起(WINDOWS系统还不充许以线程为单位建立调试会话),那么他的所有线程也就被挂起了,于是整个WINDOWS便如凝固了一样,我们也就无法继续在其上作任何事了。
是日已过,命亦随减。如少水鱼,斯有何乐? 大众当勤精进,如救头燃。但念无常,慎勿放逸

                      

TOP

tid 线程ID;pri 线程的优先级; Ctx Switch 模式切换;StrtAddr 起始地址;User Time 在用户态运行的时间;Kernel Time 在内核态运行的时间;State 线程状态


Pid (进程ID):4cc;pri(优先级):13;Hnd(句柄):895;pF(Page Fault,内存页交换次数):104959;Ws(工作集):10980k csrss.exe.


解决第一个问题的方法是通过修改WINDOWS的全局标志来启用对CSRSS的调试。全局标志是一个32位的整数,每一位对应一个选项。控制CSRSS调试的标志位叫FLG_ENABLE_CSRDEBUG,其所在位对应的16进制数是0X20000.通过以下两种方法之一可以设置FLG_ENABLE_CSRDEBUG标志(你应该有管理员权限);

直接修改注册表,将如下表键中的GlobaFlag(REG_DWORD)值,将其当前值与0X20000作或运算。
HKLM\system\CurrentControlSet\Control\Session?Manager

使用Gflags工具,直接执行gflags/r+20000或者通过图形界面选中“Enable debugging of Wind32 Subsystem”

需要重新启动系统以上改动才能生效。但由于我们后面的操作还要重新启动系统,所以大家可以统筹安排合适进行重新启动。

解决第二个问题的方法是使用两个WINDOWS系统,即使用一个WINDOWS系统来调试另一个WINDOWS系统中的CSRSS。这需要分两步来做:

第一步,使用WinDbg工具在两个WINDOWS系统间建立内核调试对话。WinDbg是微软公司的免费调试工具,可以从微软网站免费下载,链接如下:
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
两个Windows系统可以是物理上的两个PC上的WINDOWS;或者使用一台电脑利用Virtual Pc来安装第二个windows系统。如果使用两台PC,那么可以使用串口线(Null Modem)或1394(firewire)线建立连接;如果使用Virtual Pc,那么可以利用管道模拟串口连接。

对于前一种方法,WinDbg的帮助文件有非常详细的说明,不再赘述。对于如何使用Virtual Pc和VMWare进行内核调试,请参考以下链接中的文章:

http://advdbg.org/blogs/advdbg_system/articles/130.aspx
是日已过,命亦随减。如少水鱼,斯有何乐? 大众当勤精进,如救头燃。但念无常,慎勿放逸

                      

TOP

第二步,在被调试的windows系统(debuggee)中,使用NTSD调试CSRSS。NTSD是WinDbg软件包中包含的另一个调试工具,它支持命令行下工作,还支持通过内核调试会话将输入和输出定向到另一台机器上,我们正是利用这一功能来在第二台Windows(debugger)中控制NTSD实现对CSRSS的调试。NTSD支持复杂的命令行选项,对于我们的用途,其命令行应该为:

nstd -d -g -G -o -pd <CSRSS 进程ID>

-d表示将输入和输出(通过DbgPrint)定向到另一个WINDOWS中的WinDbg中;-g表示忽略被调试进程的初始断点,如果不加此开关,那么将NTSD附加到CSRSS进程的第一个breakin断点会导致被调试系统僵死;-Gg表示忽略进程终止时的最后一个断点;-o表示调试被调试进程启动的子进程;-pd表示调试器应该自动与被调试的进程分离;-p用来指定被调试进程的进程ID。注意WinDbg的帮助文件说CSRSS的进程ID总为-1,这对于windows2000和其后的windows都不再成立。不过因为NTSD提供了一个简洁的方法,只要使用一项就是调试CSRSS。所以在成功建立内核调试后,只要在被调试机上切换到WinDbg目录,然后输入NTSD--.


如果一切顺利,输入NTSD--后,在调试机上应该收到类似如下的信息,笔者使用的环境是两台机器安装的都是windows xp(sp1),WinDbg的版本为6.6.


***wait with pending attach

...

Executable search path is:
ModLoad:4a680000 4a684000 cwindows\system32\csrss.exe
ModLoad:77f500000 77f57000 cwindows\system32\ntdll.dll
ModLoad:75b400000 75b4a0000 cwindows\system32\csrsrv.dll
ModLoad:75b50000 75b5e000 c:\windows\system32\basesrv.dll
ModLoad:75b60000 75ba6000 c:\windows\system32\winsrv.dll
ModLoad:.......c:\windows\system32\user32.dll
ModLoad:.......c:\windows\system32\kernel32.dll
ModLoad:.......c:\windows\system32\gdi32.dll
ModLoad:........c:\windows\system32\advapi32.dll
ModLoad:.........c:\windows\system32\rpcrt4.dll
ModLoad:.........c:\windows\system32\sxs.dll
是日已过,命亦随减。如少水鱼,斯有何乐? 大众当勤精进,如救头燃。但念无常,慎勿放逸

                      

TOP

本功能由奇虎搜索实现

相关主题

标题 作者 最后发表
[站外] WindowsXP操作系统进程   [转帖] _╱ㄣ ︻$▅▆▇◤ 2008-09-01
[站外] :高手教你了解进程的秘密   [转帖] Elapse 2008-09-01
[站外] 推荐Windows XP 常见的进程列表   [转帖] E城天下 2008-09-01
点击阅读更多关于的相关帖子  更多相关主题