Windows Vista UAC 模式下的进程创建实战的故事(上)
作者:张康宗
难度:Level 300
Windows Vista UAC 模式的引入,无疑对进程的创建和使用造成了很大的影响。本文将从实战的角度出发,来说明这个问题。
在开始本文之前,有几个相关术语需要说明一下:
Access Token:是一个包含了登陆会话安全信息的 Windows 软件对象,用于指名一个用户以及他所在组以及相应的特权。
UAC Token:定义了Windows Vista 用户在UAC支持开启的时候的默认交互式登陆特权。一个 UAC Token 定义了最小的运行特权。
Full Token:给账户提供了最大的经过授权的特权。Full Token 实际上是由该用户隶属于的用户组决定的。
我们知道,在Windows Vista 下,除了系统内建的 Administrator 用户在进行交互式登陆的时候能够获得Full Token以外,所有的Administrators组成员都会受到UAC的限制,这是因为默认情况下Administrators组成员只能获得UAC Token。在Windows XP/Server 2003下,Administrators 组成员所获得的是 Full Token,而Windows Vista下,Administrators组成员只有经过权限的提升才能获得Full Token。就目前看来,这种提升是必须有用户交互参与的。
考虑这样一种情况,当一个Administrators组成员登陆以后,需要运行一个程序,而这个程序需要Full Token才能正常地工作,而默认情况下Administrators组成员只有UAC Token,那么在这种情况下会发生什么现象呢?最常见的现象就是Windows Vista会询问你是否允许这个程序的运行,或者更准确地说是Windows询问你是否将Full Token给这个被运行的程序。
上述情况是一种最常见的现象,但是这种情况只有当使用ShellExecute() API去创建一个进程的时候才会出现(Windows Explorer 就是使用ShellExecute() 去创建一个进程,所以当在Windows Explorer 里面启动程序的时候,能够很容易的看到Windows Vista 的询问对话框。一个最典型的例子就是使用“运行”对话框去启动msconfig.exe程序)。

但是创建进程的函数不仅仅是ShellExecute() API,ShellExecute() API是一个依附于Windows Shell库(shell32.dll)的API函数,并不是所有的成素都使用ShellExecute() 去创建一个进程的,更多的程序可能会使用一个更通用的API CreateProcess() 去创建进程。遗憾的是,当一个程序试图使用CreateProcess() 去创建一个进程的时候,在Windows Vista 下会受到Token的影响,导致进程创建的失败。
下图是一张使用ShellExecute() API创建进程的流程图,这张图能够很好的解释ShellExecute()创建进程时的整个流程。

在Windows Vista 里面使用 ShellExecute() 启动一个进程的流程可以这样描述:
1. 当使用ShellExecute() 创建一个进程的时候,ShellExecute() 会调用CreateProcess() 函数。
2. CreateProcess() 通过查询应用程序manifest信息、Windows Vista AppCompat 数据库和使用 System installer 技术来判断该应用程序是否需要提升权限。3. 如果应用程序需要提升权限,那么 CreateProcess() 会返回一个特定的错误值给 ShellExecute()。
4. ShellExecute() 接收到这个错误值以后,ShellExecute() 会调用 Application Information Service (AIS) 来尝试权限提升。
5. Application Information Service (AIS) 会弹出 Consent User Interface 对话框来提示用户。
6. 如果 AIS 成功验证,那么 Windows 会重新调用 CreateProcess() 并赋予 Full Token 来启动应用程序。
(待续
)