Windows Vista服务隔离深度剖析
作者:彭爱华
难度:Level 300
提示 如需测试本文所描述的实验,请务必下载安装最新版本的Process Explorer(本文撰写时的最新版本是V10.11):
http://www.sysinternals.com/Utilities/ProcessExplorer.html
在Windows 2000/XP下,我们经常把应用程序安装为服务,这样的好处是由于应用程序运行在Local System帐户权限下,所以即使注销后,该应用程序(服务)还能继续运行。例如为了对登录问题进行排错,我们可以把regmon和filemon安装为服务,这样它们就可以对登录、注销过程记录日志。关于Windows 2000/XP下把应用程序安装为服务的方法,可以参考笔者的文章《将Virtual PC虚拟机安装为服务》。
然而Windows Vista,却不再提供这种免费午餐!原因是Windows Vista中的所有服务,都运行在Session 0环境下,而且Session 0现在默认不能交互(non-interactive),这称为Session 0隔离(可以参考笔者的《您必须知道的Windows Vista安全功能(上)》)!
Windows Vista的所有服务都运行在Session 0下,而第一个交互登录的帐户则是运行在Session 1环境下(后续通过快速用户切换登录的用户就位于Session 2、3…)。所以就算设置服务类型为Interactive,但是由于其窗口(对话框)是在Session 0打开,所以位于Session 1的我们永远无法看到!这就好比在黑暗中向美女眨眼睛……
不过Windows Vista还是提供了一种兼容的方法,让我们可以通过切换Session的办法,来访问服务的UI。这样我们就可以勉强把应用程序安装为服务,下面以Process Explorer应用程序为例,介绍如何在Windows Vista下把应用程序安装为服务。
(1) 首先确保已经安装了Windows Server 2003 Resource Kit Tools(可以到微软网站上下载),假设安装在默认路径下。
(2) 以提升权限打开命令提示符窗口,并运行以下命令:
sc create Procexp type= interact type= own start= auto binpath= "C:\Program Files\Windows Resource Kits\Tools\srvany.exe" obj= LocalSystem displayname= "Process Explorer"
(3) 然后打开注册表编辑器,可以看到在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下新增了一个Procexp子项,进入其下的Parameters子项,在右侧的详细窗格里新建一个字符串键值Application,并将其数值数据设置为以下内容:
C:\Program Files\Process Explorer\procexp.exe
(4) 打开services.msc服务管理单元窗口,确保“Interactive Services Detection”服务没有被禁用。
(5) 启动新建的“Process Explorer”服务,这时候“Interactive Services Detection”服务会自动启动,并检测到Process Explorer试图在Session 0打开自己的程序窗口,就会弹出一个“Interactive Services Dialog detection”对话框,如下图所示。
(6) 单击其上的“Check request”按钮,系统就会切换到Session 0状态下,这样我们就可以看到Process Explorer的窗口了,如下图所示。操作完毕,单击“Interactive Services Dialog detection”对话框上的“My desktop”按钮,即可回到原来的桌面。
在Session 0里,可以看到系统启动了两个UI0Detect.exe进程,这就是“Interactive Services Detection”服务的Host进程。这两个进程(服务)分别工作在Session 0和1下,负责发送切换Session的消息。
超级另类的“UAC”
利用这个实验居然还能构造出一个非常“另类”的UAC进程,这个进程是以LocalSystem帐户身份启动的,但是却能够获得一个UAC访问令牌!
(1) 启动先前创建好的Process Explorer服务,并根据提示切换到Session 0下,以便显示其图形界面。
(2) 单击Process Explorer的File→Run as Limited User,在打开的对话框里输入某个进程的名字,例如cmd,并回车,如下图所示。
(3) 接下来就可以打开一个命令提示符窗口,由于其父进程是Process Explorer(运行在LocalSystem帐户下),所以cmd默认也以LocalSystem身份运行。然而cmd进程居然获得的是一个UAC访问令牌(),同时怪异的是其Mandatory Label SID居然还是显示为“System Mandatory Level”!如下图所示。
接下来就对这个怪异的cmd窗口进行测试,发现其“特异功能”还不少,以下仅举两例:
(1) 首先尽管它获得的是一个UAC Token,但是由于其帐户身份是LocalSystem,所以还是可以运行一些普通UAC进程所无法运行的管理任务,例如在该cmd窗口里,可以顺利运行bcdedit命令显示当前系统的启动设置。
原因是因为LocalSystem帐户的特殊性,系统中绝大多数的目录和注册表键值都对LocalSystem“显式”地赋予完全控制权限,所以尽管cmd的访问令牌过滤了administrators帐户组的SID,但是照样可以访问BCD数据库,而这是普通UAC进程办不到的(除非系统提示提升权限)。
(2) 不过也有它办不了的事情,从上图中可以看出,该cmd窗口的访问令牌里没有SeTimePrivilege,所以该命令提示符下无法修改系统时间,例如无法用time命令修改当前的系统时间,系统会“哭诉”没有SeTimePrivilege特权,如下图所示。
所以说,尽管LocalSystem身居“宰相首辅”的“要职”,一时风光无限,但是居然也有皱眉头的时候!
为什么Vista有两个CSRSS进程?
这篇文章还捎带着解释了一个我困惑已久的问题,那就是为什么Windows Vista默认状态下就拥有两个csrss进程,读者朋友可以自己打开任务管理器进行验证。
大家知道csrss是Windows子系统(Windows Subsystem)的用户模式部分,在Windows 2000/XP/2003下,通常我们只能看到一个csrss进程。
但是为什么Windows Vista会拥有两个进程?这个现象让笔者百思不得其解。通过今天的实验,突然有了醍醐灌顶的感觉,心里透亮─问题就出在Windows Vista服务上!就是因为服务的session 0隔离,导致Interactive用户登录以后,系统将会同时打开两个session(0和1),所以Windows Vista才需要两个csrss进程,分别为这两个session服务!
其实对于我们的Windows XP/2003,也会有类似的情况发现:
1.Windows Server 2003
在Windows Server 2003下,假设当前的登录帐户是Admin,位于Session 0。这时候如果用另外一个帐户Peter通过远程桌面登录到服务器上,这时候Peter位于Session 1。然后打开Process Explorer,这时候也会发现有两个csrss进程,分别位于Session 0和Session 1。
2.Windows XP
在Windows XP下,假设有两个管理员帐户Admin和Peter,当前登录帐户是Admin,位于Session 0,这时候利用快速用户切换功能(FUS)登录到Peter,现在Peter用户位于Session 1。然后打开Process Explorer,这时候也会发现有两个csrss进程,分别位于Session 0和Session 1。这个道理类似于远程桌面─FUS本来就可以看成是远程桌面的特殊形式。
如果仔细观察的话,就会发现采用以上方法的Windows XP/2003除了拥有两个csrss进程外,还同时拥有两个explorer等进程。这在Windows Vista下是看不到的,这是因为Session 0在Vista下被标识为Noninteractive,所以没有必要拥有另外一套Shell进程。