欢迎光临 Enjoy IT (ITECN.NET) 登录 | 注册 | 帮助

内存优化的神话是如何炼成的

4月12日的Webcast ,盆盆介绍了Windows Vista最新的内存管理技术SuperFetch。在Webcast的最后,盆盆推荐了Mark Russinovich的一篇揭穿内存优化工具骗局的文章,并承诺会将它翻译成中文,并且加上盆盆自己做的注释,在ITECN博客上分享给大家。推荐大家一定要阅读一下,不但可以很好地了解这些所谓的内存优化工具是如何欺骗大家的,更重要可以学到很多重要的内存管理机制。

可以访问以下地址,阅读本文:

http://blogs.itecn.net/blogs/ahpeng/archive/2007/04/13/WinMemMgmt.aspx

发表于 作者 ahpeng | 0 评论

深入理解Windows Vista内核三:服务安全改进

盆盆译注:去年5月,盆盆写过一篇原创的技术文章,曾经提到过Windows Vista的服务安全改进,读者朋友可以对照着看,希望能够帮助大家更好地理解本文的内容。

以下是Mark的正文翻译:

Windows服务一向是恶意软件的理想攻击目标。许多服务提供网络访问功能,这可能会带来远程访问的相关漏洞,而且大多数服务可以比标准用户拿到更高的特权,这样一旦受到恶意软件的攻击,就可以有机会在本地系统提升权限。所以,在Windows XP SP2版本中,Windows开始引入一些变化,以降低服务的特权和访问权限,只要能够满足其功能即可。例如,Windows XP SP2新增了Local Service和Network Service这两个帐户,它们所包含的特权只是Local System帐户的子集,而以前,服务都是以Local System的帐户身份运行的。这样就算服务存在漏洞,也可以把受攻击的可能性降到最低。

盆盆译注:整篇文章实际上体现了最小特权使用的思想,这和UAC的思想是一致的。我们一定要建立这个安全概念,才能理解Windows Vista安全。对于Dev来说,更是如此,否则无法实现程序安全和兼容。

前一篇文章里,Mark提到服务运行在自己的会话中,从而和用户的会话隔离开,但是Windows Vista进一步减少服务特权,减少对文件、注册表键值的访问权限,还可以为绝大多数服务分配防火墙端口,更进一步体现了最小特权的原则。Windows Vista引入了一种新的组帐户,叫做服务安全标识符(SID),每个服务都有唯一的SID。服务可以对它的资源设置访问权限,这样只有该服务的SID才有权访问,防止运行在同一用户帐户下的其他服务访问这些资源(如果该服务已经受到攻击)。我们可以用SC ShowSID命令查看指定服务的SID,如附图所示。

盆盆译注:服务SID仅用于控制对服务资源的访问,而并不能用于身份验证,例如不能用于服务的登录。

服务SID可以对特定服务所拥有的资源提供访问保护,但是默认情况下,服务还是可以访问其登录帐户有权访问的所有资源。举个例子,假设以Local Service身份运行的某个服务,用服务SID来对它的资源提供保护,那么同样以Local Service身份、而在另外一个进程中运行的其他服务,就无法访问它所创建的资源。但是,其他服务还是可以访问Local Service帐户得到授权的资源,或者是Local Service帐户所属的组(例如Service组)有权访问的资源。

盆盆译注:还是举个实例看起来比较清晰,例如C:\Windows默认给标准用户提供读取权限,所以,所有服务都可以读取其下的内容。然而只有TrustInstaller帐户才对C:\Windows目录拥有写入权限,所以“Windows Modules Installer”服务有权写入该目录(因为该服务拥有TrustInstaller这个服务SID)。

为了解决这个问题,Windows Vista引入了一个新的受限服务类型,叫做“写入限制服务”,这样只有在对象明确地给服务SID、Everyone组或者分配给登录会话的SID(盆盆译注:Logon SID)提供写入权限,服务才能有权限修改该对象。为了达到这个目标,该服务使用Restricted(受限)SID,这种类型的SID最初是在Windows 2000中引入的。如果打开对象的某个进程属于“写入限制服务”类型,那么访问检查的算法就会发生变化,只有同时给具有两种形式(受限和不受限)的服务SID提供写入权限,该进程才真正具有写入权限。我们可以用“SC QSIDType ServiceName”命令查看某个服务是否属于“写入限制服务”类型,如附图所示。

盆盆译注:默认情况,BFE、DPS等服务属于“写入限制服务”,其宿主进程svchost的访问令牌中,只有服务SID、Everyone组和登录会话SID打上“Restricted”(受限)的标志,如附图所示。这说明,只有对象明确地给服务SID、Everyone或者登录会话SID赋予写入权限,才能确保服务具有写入该对象的权限。如果对象只给服务的登录帐户(Local Service)或者Service组授予写入权限,服务还是没有写入权限。这是因为在进程的访问令牌中,服务的登录帐户和Service组,并没有“Restricted”标志,所以无法通过第二次的访问检查。

 还有一个改进,Windows服务现在更容易防止同一帐户下运行的其他服务访问它所创建的对象。在旧版本的Windows中,对象的创建者同时也是对象的所有者,所有者可以读取并且修改对象的权限,以获取对象的完全控制权限。Windows Vista引入了全新的Owner Rights这个SID,如果对象的访问控制列表中有Owner Rights这个SID,就可以限制所有者的访问权限,甚至没有权利去设置和查询权限。

盆盆译注:总算知道Owner Rights这个SID的作用了,在Beta 2的中文内测版Windows Vista中,这个SID居然被翻译成“所有者全县”(“全县”显系“权限”之误)。要了解更多有关Owner Rights的意义,可以参考以下的微软官方网站:

http://technet2.microsoft.com/WindowsVista/en/library/ea557e82-e51c-484f-be3a-b9ab45c0ea871033.mspx?mfr=true

在Windows Vista的服务安全模型中,更进一步的改进是服务的开发人员可以明确指定服务可以拥有的特权。例如,如果服务需要产生审核事件日志,则可以给服务指定审核特权。 

当服务控制管理器(SCM)启动包含一个或者多个服务的进程时,会为该进程创建一个访问令牌(访问令牌是内核对象,列出进程的用户帐户身份、组成员,还有特权), 访问令牌里仅仅包含(进程里的)服务所必须拥有的特权。如果服务指定了某个特权,而其启动帐户却不包含该特权,服务启动就会失败。如果以Local Service身份运行的进程,其中包含的所有服务,都不需要“调试程序”特权,服务控制管理器(SCM)就会把该特权从进程的访问令牌中剔除。因此,如果服务进程遭受攻击,恶意代码无法利用这些危险的特权,因为进程里的服务并没有明确声明需要这些高危险的特权。可以用“SC QPrives”命令查看服务所需的特权。

查看“写入限制服务”

盆盆译注:这部分内容和前面的译注有些重叠,这是因为盆盆并没有注意到Mark把这部分补充内容放在全文的最后,所以盆盆有点画蛇添足,自己添加了相关背景介绍。不过盆盆不准备删除这部分译注,读者朋友可以参考一下。

在Windows Vista中,只有一个服务宿主进程(svchost)包含受限服务,我们可以借助Process Explorer这样的进程查看工具,查看具有以下“Command Line”(命令行)的进程:

svchost -k LocalServiceNoNetwork

盆盆译注:需要事先在Process Explorer里单击View、Select Columns,在打开的对话框里勾选“Command Line”复选框。 

该进程包含Base Filtering Engine、Diagnostic Policy Service、Windows Firewall、Performance Logs and Alerts和Windows Media Center Service Starter这几个服务。

附图所示的是“Base Filtering Engine”服务的服务SID(显示为文本格式),叫做NT Service\BFE,一共有两个,其中一个带有Restricted的标志,另一个则没有(标记为Owner),所以如果对象给该服务SID赋予访问权限,则进程就有权限访问该对象。然而,如果某些对象通常只有Local Service帐户可以访问,则服务进程并没有什么必要对这些对象进行访问。例如,在进程的访问令牌中,“NT AUTHORITY\SERVICE”帐户并没有Restricted的标志,如果某个对象仅给“NT AUTHORITY\SERVICE”帐户授予访问权限,而没有给其他带Restricted标志的帐户分配权限(例如服务SID、登录会话SID或者Everyone),则服务进程无法对该对象进行写入操作。

该进程中的服务只拥有受限的特权,因为图片底部所列出的特权只是Local Service帐户特权的一个子集。

盆盆译注:在Mark的文章里,提到会话(Session)隔离和登录会话SID(Logon Session)。一个是会话,还一个是登录会话,应该属于不同的概念。但是盆盆目前还不能很好地理解这两个概念各自的使用场景。
用Process Explorer很容易看出,在用户登录后,系统中存在两个会话,服务和一些系统级的进程运行在会话0,而用户进程运行在会话1。
同样用Process Explorer很容易看出,系统中同时存在多个登录会话,多个用户进程共享一个登录会话(runas启动的进程也一样),但是每个服务进程都有独立的登录会话。每个登录会话都有一个相应的SID,可以在进程的访问令牌里看到Logon Session SID。
盆盆最近在看Keith Brown所著的《Programming Windows Security》,觉得这本书很好,可以帮助理解很多原来不知道的底层安全原理,虽然是为Dev所写,但是不懂开发的盆盆照样觉得这书很好。

深入理解Windows Vista内核三:改进的故障处理

由于设备驱动存在错误、或者硬件存在问题,抑或是操作系统本身的原因,当系统遇到无法恢复的内核模式错误时,Windows会显示臭名卓著的“蓝屏死机”,随后强行中止系统,以防止磁盘出现数据冲突,同时根据系统配置的情况,还会把部分或者全部的物理内存写入到一个故障转储文件(crash dump file)。内存转储文件很有用,因为当我们死机后重启系统时,微软的在线故障分析服务(OCA)可以对其进行分析,以便找到问题的根源。如果我们愿意,还可以自己用Microsoft Debugging Tools for Windows自己进行故障分析。

盆盆评注:有关如何用Debug工具分析系统故障的知识,可以参考张银魁老师的Webcast

然而旧版本的Windows,直到会话管理器进程(%Systemroot%\Sys­tem32\Smss.exe)对页面文件进行初始化以后,才可以启用故障转储文件的支持。也就是说,在这以前,如果发生了严重的系统故障而导致系统蓝屏,并不会生成转储文件。而大量设备驱动程序是在Smss.exe进程启动之前进行初始化,所以早期的系统故障并不会触发转储文件的创建,所以对这些故障进行排错就非常困难。

盆盆评注:有关Windows 2000/XP启动过程的介绍,可以参考张银魁老师的Webcast

而Windows Vista则大大提前了可以创建转储文件的时间。现在,在所有启动类型为“boot”的驱动程序启动以后,而在所有启动类型为“system”的驱动程序启动以前,就可以初始化转储文件的支持。有了这个改进,当我们在系统引导阶段遇到死机崩溃的故障,微软OCA服务就可以帮助诊断这个问题。而且,Windows Vista以64KB的块级别往转储文件里填充数据,而老版本的Windows则是以4KB为单位。这样大容量的内存转储文件,就能够以十倍的速度生成。

盆盆评注:启动类型为“boot”,是指由ntldr或者引导管理器加载的驱动程序。这些驱动程序比较重要,如果没有启动的话,Windows将无法继续引导。启动类型为“system”,是指内核初始化过程中启动的驱动程序。

在Windows Vista中,应用程序的故障处理也得到了很好的改进。在旧版本的Windows中,当应用程序发生故障时,会执行一个专门的处理程序(unhandled exception handler),以对这种无法正常处理的例外进行处理。例外处理程序会加载微软的应用程序错误报告(AER)进程(%Systemroot%\System32\Dwwin.exe),并且显示对话框,提示该程序出错,并询问是否需要把错误报告发送给微软。然而,如果该进程在崩溃时,主线程的堆栈被破坏,例外处理程序会在执行时崩溃,导致其进程被内核终止,结果是程序窗口一闪而过,根本没有显示任何错误报告对话框。

Windows Vista则将错误处理从崩溃进程的上下文中移走,而交由一个新的服务来处理,就是Windows Error Reporting(WER)服务。该服务运行在服务宿主进程中,是以DLL文件的形式实现的(%Sys­temroot%\System32\Wersvc.dll)。当应用程序发生故障时,它还是会执行例外处理程序,但是例外处理程序会给WER服务发送一个消息,而由WER服务加载WER错误报告进程(%Systemroot%\System32\Werfault.exe),以显示错误报告对话框。如果因为主线程的堆栈被破坏而导致例外处理程序崩溃,例外处理程序就会反复地执行崩溃、崩溃执行,最终把线程所有堆栈空间消耗干净,当内核处于这个状态的时候,就会给WER服务发送故障通知消息。

盆盆评注:服务宿主进程,就是指svchost进程。

我们可以在以下四张图片中看到两种实现方法的对比。这些图片显示Accvio.exe进程和错误报告进程之间的关系,Accvio.exe进程是一个故障测试程序,可以触发一个应用程序崩溃。Windows Vista中新的错误处理机制意味着应用程序不再会悄无声息地中止,而妨碍我们向微软发送错误报告,以便帮助软件开发商改进他们的产品。

Windows XP的应用程序错误处理

Windows XP的错误报告对话框



Windows Vista的应用程序错误处理

Windows Vista的错误报告对话框

盆盆评注:从图1中可以看出,Windows XP的错误报告进程dwwin是由发生错误的应用程序所启动,如果该应用程序的主线程堆栈被破坏,会导致无法弹出错误报告。而图3显示Windows Vista的错误报告进程WerFault是由svchost进程启动的(实际上是由svchost进程里的WER服务所加载),这样的相对独立机制,可以确保应用程序的错误都能被系统所捕获。

发表于 作者 ahpeng | 4 评论

深入理解Windows Vista内核三:BitLocker

Windows Vista是目前最安全的Windows操作系统。除了包含Windows Defender防间谍软件引擎,Windows Vista还引入了很多安全和深度防御特性,包括BitLocker全卷加密特性,内核模式代码的代码签名,受保护的进程、地址空间随机加载(ASLR),还有Windows服务的安全改进和用户帐户控制(UAC)。

只有在运行的时候,操作系统才能强制执行其安全策略,所以为了防止系统的物理安全受到攻击,防止绕过操作系统访问数据,我们必须采用额外的方法来保护数据。BIOS密码和加密这样的基于硬件的机制,是我们常用的两种方法,可以阻止未经授权的访问,尤其是笔记本电脑(更容易被窃或者丢失)。

Windows 2000引入了EFS加密,而在Windows Vista中,EFS具有许多新的改进,包括性能的提升、支持页面文件加密、可以在智能卡里存储用户的EFS密钥。但是我们无法借助EFS来保护系统的某些敏感区域,例如注册表配置单元文件。举个例子,如果组策略允许我们不在域环境时登录到笔记本电脑,验证所用的域凭据就会缓存在注册表中,这样攻击者就可以使用工具获取域帐户密码的散列值,然后借助密码破解工具来破解域帐户的密码。然后攻击者就可以访问我们的帐户,并且偷获我们的EFS加密文件(假设我们没有把EFS加密密钥保存在智能卡里)。

为了方便加密整个启动卷(包含Windows安装目录的卷),包括所有系统文件和数据,Windows Vista引入了一个称为BitLocker的全卷加密特性。EFS通过NTFS文件系统驱动程序来实现,并在文件的级别上进行操作;而BitLocker则有所不同,它使用全卷加密驱动程序(FVE)(%Systemroot%\Sys­tem32\Drivers\Fve­vol.sys),在整个卷的级别上进行加密,如图1所示。

FVE是一个筛选级驱动程序,所以它能看到NTFS文件系统发送给卷的所有的I/O请求,写入的时候自动进行加密,而读取的时候自动进行解密,加密和解密过程是通过全卷加密密钥(FVEK)而进行的,初始化配置使用BitLocker时,会给Windows卷分配FVEK。默认情况下,会用一个128位的AES密钥和一个128位的Diffuser密钥对卷进行加密。因为加密和解密过程发生在NTFS I/O系统的下方,所以对NTFS来说,卷好像没有加密过,NTFS甚至根本不知道BitLocker的存在。但是如果在Windows系统的外面访问卷中的数据,则看上去像没有格式化过。

卷主密钥(VMK)对FVEK进行加密,并将其存放在卷的特殊元数据区域。根据系统硬件配置的不同,设置BitLocker时,我们有多个选项用来保护VMK。如果系统具有符合V1.2规范的TPM芯片,并且具有相应的BIOS支持,我们可以用TPM来加密VMK,既可以用TPM芯片里存储的密钥和USB闪盘里的密钥联合对VMK进行加密,也可以用TPM芯片里的密钥和开机时输入的PIN联合对VMK进行加密。如果系统没有TPM芯片,我们还可以用USB闪盘里的密钥对VMK进行加密。无论采用什么加密选项,我们都必须要准备一个至少1.5GB大小的NTFS卷作为引导扇区(不能进行加密),以便存放引导管理器(bootmgr)和引导配置数据库(BCD)。

盆盆评注:由此可见,VMK是所有加密选项的中转站,可以用不同的加密方法对VMK进行加密,这样如果一种加密方法失败(例如TPM芯片损坏),还可以通过另外一种方法(例如恢复模式)重新生成密钥链。

使用TPM的好处是,BitLocker可以借助TPM芯片来确保只有BIOS或者系统启动文件发生变动,系统就不会解密VMK,从而不会解锁Windows卷。第一次加密Windows卷,或者要更新前面提到的组件时,BitLocker会为每个组件自动计算出一个SHA-1散列值,并且在TPM设备驱动程序(%Systemroot%\Sys­tem32\Drivers\Tpm.sys)的帮助下,把每个散列值(称作度量值,measurement)存放在TPM芯片里相应的PCR寄存器中。然后TPM对VMK进行封装,封装的操作需要用到存放在TPM芯片里的私钥(对VMK进行加密),还有存放在PCR寄存器里的值和BitLocker传递给TPM的其他数据。然后BitLocker会把封装后的VMK,还有加密后的FVEK,保存在加密卷的元数据区域。

盆盆评注:本以为BitLocker会把加密后的VMK和FVEK存放在不加密的引导卷中,而不会存放在加密卷中(否则相当于把钥匙忘在房间里)。但实际上确实保存在加密卷的元数据区域。

当系统启动时,会把自己的散列值和PCR加载代码进行比较,并把该散列值写入到TPM芯片的第一个PCR寄存器中。然后会计算BIOS的散列值(度量值),并将该度量值存放在合适的PCR寄存器中。接下来BIOS会给启动序列中的下一个组件(引导扇区的主引导记录)计算散列值,然后该过程会一直持续,直到操作系统加载程序也已经计算出度量值并进行比较。其后运行的每段代码都需要负责对其加载的代码计算度量值,并负责把度量值存储到TPM芯片里相应的PCR寄存器中。最后,当用户选择引导的操作系统,引导管理器(bootmgr)会从该卷中读取加密的VMK,并请求TPM对其进行解密。只有当所有的度量值都和VMK封装时的结果一样,包括可选的PIN,TPM才能成功解密VMK。

盆盆评注:由于引导卷上的文件,包括bootmgr和bcd都不能被加密,所以TPM芯片可以提供一个比较好的方法,通过计算其散列值来确保这些文件没有被篡改。

我们可以把这种机制想象为信任链,在这个信任链中,启动序列里的每一个组件都要向TPM描述其后的组件。只有全部的描述都和原始的组件相匹配,TPM才能成功进行解密。这样的话,就算把磁盘拆卸下来,放在另外一个系统上,并用另外一个操作系统引导该系统,或者引导卷上的未加密文件已经受到攻击时,BitLocker依然可以对加密数据提供保护。

盆盆评注:BitLocker可以很好地保证系统的启动安全,就算TPM芯片和整个磁盘都被攻击者获取,虽然系统已经释放出VMK,但是由于帐户密码的存在,攻击者还是无法获取加密数据,因为攻击者无法采用常规方法破解帐户密码。

发表于 作者 ahpeng | 4 评论

深入理解Windows Vista内核三:内核事务管理

说在前面:Mark Russinovich共为《TechNet Magazine》写了三篇有关《深入了解Windows Vista内核》的系列文章,这是本系列中的最后一篇。尽管在微软网站上,前两篇文章有汉语的译文,但是有些地方似乎并不到位。乘第三篇英文原稿刚刚发布,盆盆抢先一步翻译,先让ITECN的读者朋友尝尝鲜,翻译得也不能说好,但是盆盆已经用心了。以下就是正文部分。

到目前为止,这个系列文章涵盖了Windows Vista内核的增强,包括进程、I/O、内存管理、系统启动、关机和电源管理。在第三、也是最后一个部分里,我们将讨论有关可靠性、恢复和安全方面的增强特性。

在这个系列文章中,并没有讲述有关用户帐户控制(UAC)的原理,UAC实际上由一系列不同的技术组成,包括为旧版应用程序而准备的文件系统和注册表虚拟重定向、访问管理特权的提升权限提示、还有Windows完整性级别(用于将高特权进程和同一帐户下运行的低特权进程隔离开)。还将会在《TechNet Magazine》上发表一篇有关UAC内部原理的文章,届时大家可以阅读。

Windows Vista提供许多最新特性和改进,帮助提升系统的稳定性,并且方便我们对系统和应用程序的问题进行排错。例如,Windows内核事件跟踪记录程序(ETW)会持续工作,以便把文件、注册表、中断和其他类型的活动事件记录到一个循环缓存中。如果出现问题,新的Windows诊断基础结构(WDI)特性就会从该循环缓存里捕获一个快照,并在本地进行分析,或者上传到微软的相关故障诊断站点。

新的可靠性和性能监视器可以帮助我们进行故障排错,例如系统崩溃或者挂起,还有对系统配置所进行的修改。如果要对无法启动的系统进行离线排错,我们现在可以使用强大的系统恢复工具(SRT),而不再需要借助故障恢复控制台。

有三大部分和系统内核级别的改变有关,所以应该深入了解一下文章里以下三大部分:内核事务管理器(KTM)、更好的故障处理,以及“以前的版本”特性。

盆盆评注:“以前的版本”特性,基于系统的卷影副本和系统还原的功能。可以方便地把文件或者目录恢复到先前所备份的版本。

内核事务管理器

对软件开发来说,其中一个最让人头痛的地方就是错误处理的条件判断。在以下情况中,显得尤其正确:例如在执行高级操作的过程中,应用程序已经完成了一个或者多个子任务,可能导致文件系统或者注册表的修改。举个例子,应用程序的软件更新服务可能会修改某些注册表键值、替换应用程序的其中一个可执行文件,但是当试图替换第二个可执行文件时拒绝访问。为了确保该应用程序的一致性,软件更新服务必须能够跟踪所有的修改,以便可以撤销这些修改。对错误恢复代码进行测试,是非常困难的,而且通常会忽略,所以恢复代码里的错误会抹杀其功效。

在内核事务管理器的帮助下,Windows Vista应用程序只需要付出很小的努力,就可以使用NTFS文件系统和注册表的最新事务支持特性,获得自动错误恢复的能力。当应用程序要进行大量相关修改时,它既可以创建DTC事务和KTM事务句柄,也可以直接创建KTM句柄,然后把文件和注册表键值的修改和该事务相关联。如果所有的修改能够顺利完成,应用程序就会递交该事务,这样修改就能最终生效,但是只要还没有达到这一点,应用程序都可以撤销该事务,从而丢弃所做的任何修改,以确保应用程序的一致性。

还有一个好处是,除非已经递交某个事务,否则其他应用程序无法看到该事务中所作的修改。在Windows Vista和今后发布的Windows Server Longhorn中,如果应用程序使用DTC,则可以把它们的事务和SQL Server、MSMQ等数据库进行交互协调。因此,使用KTM事务的更新服务可以确保应用程序始终处于一致的状态。这就是为什么Windows Update和系统还原使用KTM事务的原因。

作为事务支持的核心,KTM允许NTFS和注册表这样的事务资源管理器,与应用程序所做的一组特定修改之间进行协调。在Windows Vista中,NTFS使用一个称作TxF的扩展功能来支持事务。注册表则使用一个名为TxR的类似扩展功能。这些内核模式的资源管理器和KTM一起工作,以协调事务状态;就好像用户模式下的资源管理器使用DTC,在多个用户模式资源管理器之间协调事务状态。第三方也可以使用KTM来实现自己的事务资源管理器。

TxF和TxR都定义了一组新的文件系统和注册表API,和已有的API类似,只是增加了事务相关的参数。如果应用程序需要用事务来创建文件,则它首先需要使用KTM创建事务,然后把所得的事务句柄传递给新的文件创建API。

TxF和TxR都依赖于通用日志文件系统(CLFS)(%Sys­tem­Root%\System32\Clfs.sys)所提供的高速文件系统日志功能,CLFS最初是在Windows Server 2003 R2中引入的。使用CLFS,TxF和TxR就可以在递交事务之前,持续保存事务状态的改变。这样就可以提供事务恢复能力,甚至在掉电时也可以确保。除了CLFS日志,TxR还在%Systemroot%\System32\Config\Txr目录下创建一组相关日志文件,以跟踪系统注册表文件的事务改变,如图1所示,同时还为每个用户的注册表配置单元文件创建一组不同的日志文件。
在每个NTFS卷,TxF把事务数据存储在该NTFS卷下的\$Ex­tend\$RmMetadata目录下,该目录是隐藏的。

盆盆评注:\$Ex­tend\$RmMetadata目录是隐藏的,我们无法在Shell中直接查看,但是可以借助第三方工具进行查看,如图2所示。

发表于 作者 ahpeng | 4 评论

Windows Vista安全原理深入探索

 

本文是对盆盆以前发表过的文章《UAC功能浅析》一文的改写和扩充。一方面老的那篇文章是根据Build 5231而写,内容比较陈旧,所以这次根据Windows Vista正式版本进行改写;另一方面,本文绝非简单的改写,盆盆还特地加入了自己最新探索和学习到的一些知识,希望能够让读者朋友满意。

盆盆评注 笔者在探索和学习Windows Vista安全理论的过程,深受《Windows Internals》一书的启发。该书由Mark Russinovich和David Solomon所著,堪称IT Pro和Dev的圣经。

参考

用户帐户控制(UAC),是Windows Vista新引入的安全机制。管理员登录Windows时,系统会同时创建两个访问令牌,其中一个是完全的管理员访问令牌(Full Token),另一个是经过“过滤”的访问令牌,叫做标准用户访问令牌,如附图所示。当Windows系统启动Shell进程(Explorer.exe)时,LSA会把标准用户访问令牌连接到Shell进程,所以Windows Vista启动的用户进程,默认都只具有标准用户权限。如果某个进程需要管理员权限,则系统会提示权限提升,得到用户亲自确认后,系统会把完全的管理员访问令牌连接到该进程上。
 单击看大图
准备知识

在《Windows Internals》的第八章“安全”部分,介绍了一个实例:当我们在Windows XP里启动“日期和时间”控制面板组件时,实际上启动的是“rundll32”进程,由该进程加载“Timedate.cpl”控制面板组件。用Process Explorer检查该“rundll32”进程的访问令牌,可以发现“SeSystemTimePrivilege”特权处于启用状态,如附图所示。
单击看大图
“SeSystemTimePrivilege”是“更改系统时间”特权的内部名称,所有特权都保存在LSA的策略数据库中,该数据库会加载到HKLM\SECURITY注册表分支,用户登录系统时,LSA会读取这些特权值。

对于Windows XP专业版,我们可以通过“本地安全策略”管理单元查看用户所具有的特权。可以看到,“更改系统时间”特权仅授予管理员组和Power Users组用户,如附图所示,这就是为什么在Windows XP下,标准用户无法修改系统时间和时区的原因。
单击看大图
盆盆评注 笔者曾经写过一个连载,介绍帐户的登录权利所对应的HKLM\SECURITY注册表键值。可以用同样方法得出特权所对应的注册表键值。

实验准备

现在我们已经知道,要修改系统时间,当前帐户必须具备“更改系统时间”特权。但是在Windows Vista下,默认不是只有标准用户权限吗,这时候应该没有“更改系统时间”特权!那么系统是如何获得“更改系统时间”特权的呢?我们用实验来进行验证。

1. 实验工具

本实验在Windows Vista中文旗舰版上进行,测试帐户为Admin,是管理员组成员。为了查看进程的访问令牌,需要采用先前提到的Process Explorer工具,下载地址如下:

http://www.microsoft.com/technet/sysinternals/utilities/ProcessExplorer.mspx

还有一个Process Monitor工具,下载地址如下:

http://www.microsoft.com/technet/sysinternals/utilities/processmonitor.mspx

2. 禁用安全桌面

由于“用户帐户控制”对话框默认运行在“安全桌面”上,这里的安全桌面就是我们按“Ctrl+Alt+Del”组合键所进入的桌面。但是为了改善用户体验,UAC的安全桌面并不是蓝绿色的背景,而是当前用户桌面桌面背景的截图快照(呈暗色显示)。

盆盆评注 参考盆盆翻译自Mark Russinovich的文章,了解如何强制用户必须按“Ctrl+Alt+Del”组合键,才能打开UAC的凭据输入对话框,这样可以确保凭据的安全。

之所以启用“安全桌面”,主要是因为考虑到安全因素,以防其他进程可以对“用户帐户控制”对话框进行操作。但是由于本实验需要用工具对UAC的过程进行全程监控,所以需要临时禁用“安全桌面”功能,方法如下。

运行“secpol.msc”并回车,打开“本地安全策略”对话框,然后在左侧的控制台树里定位到本地策略→安全选项,在右侧详细窗格里双击“用户帐户控制:提示提升时切换到安全桌面”策略项,并选中“已禁用”选项,如附图所示。
单击看大图

实验记录

1.查看rundll32进程访问令牌

单击任务栏通知区域的时钟图标,然后单击底部的“更改日期和时间设置”链接,即可打开“日期和时间”窗口。正如您所预料的,这时候还不能对系统时间进行任何修改。同时可以在Process Explorer窗口中看到新增一个进程rundll32(呈绿色显示)。

双击该rundll32进程,即可打开其属性对话框。在“Image”标签页的“Command Line”文本框里可以看到“timedate.cpl”(“时间和日期”的控制面板扩展文件),如附图所示。这说明该rundll32.exe就是“时间和日期”控制面板组件的宿主进程。
单击看大图

切换到“Security”标签页里,就可以看到该rundll32进程的访问令牌,可以看到在下方的特权列表里,只有少得可怜的五个个特权,而其中并没有SeSystemTimePrivilege特权!这就是为什么在默认情况下,无法在管理员环境下修改系统时间的原因。
 单击看大图

2.提升权限

要能够修改系统时间,只需单击“日期和时间”窗口右下侧的“更改日期和时间”按钮,即可打开 “用户帐户控制”对话框,单击“继续”按钮,如附图所示。现在应该可以修改系统时间了。
 单击看大图
看来这个“用户帐户控制”对话框负责向系统传递消息,以便系统确认用户同意提升操作权限。其本质似乎应该是修改相关进程的访问令牌,就本例来说,应该是在rundll32进程的访问令牌里添加SeSystemTimePrivilege特权。那么果真是这样吗?

结果很让人沮丧,重新打开rundll32进程的属性对话框,并切换到“Security”标签页,发现其访问令牌没有任何改变(并没有新增SeSystemTimePrivilege特权)!

这是为什么呢?

3.查看dllhost进程的访问令牌

反复重新做实验后,终于发现在“用户帐户控制”对话框上单击“继续”按钮后,系统会新增一个dllhost进程,在其进程属性对话框的“Image”标签页的“Command Line”文本框里可以看到“/Processid: {9DF523B0-A6C0-4EA9-B5F1-F4565C3AC8B8}”参数,如附图所示。
单击看大图

搜索注册表得知,{9DF523B0-A6C0-4EA9-B5F1-F4565C3AC8B8}就是timedate.cpl的AppID,如附图所示。
单击看大图

在dllhost进程的属性对话框上,切换到“Security”标签页,不出所料,dllhost进程的访问令牌里果然有SeSystemTimePrivilege特权,而且是启用状态,如附图所示。
单击看大图

现在真相大白了,原来Windows Vista表面上让rundll32进程“明修栈道”,背地里却让dllhost进程“暗渡陈仓”,把完全的管理员令牌赋予该dllhost进程,真正让我们可以修改系统时间的是dllhost进程!

4.系统背后的动作

为了更好地对系统背后的动作进行监测,我们再启动Process Monitor,然后再重复上述的操作。

结果在Process Monitor里监测发现,单击“日期和时间”窗口右下侧的“更改日期和时间”按钮,发现由svchost进程(进程ID为1924)启动consent.exe进程,这个consent.exe进程就是“用户帐户控制”对话框,如附图所示。
单击看大图

盆盆评注 在Windows Vista下,应该用Process Monitor代替Filemon和Regmon,Process Monitor除了可以监控注册表和文件活动外,还可以监控进程的活动,包括其堆栈信息。

双击这条记录,在打开的属性对话框上切换到“stack”标签页。在其堆栈信息中发现一个“appinfo.dll”模块,其描述为“应用程序信息服务”,如附图所示。原来这就是Windows Vista系统的“Application Information”服务,当系统确认进程需要管理员权限时,就会由“Application Information”服务负责启动consent进程,以便打开“用户帐户控制”对话框。
单击看大图
在Process Explorer中打开consent进程的属性对话框,在“Image”标签页也可以发现consent的父进程的进程ID为“1924”(svchost进程),如附图所示。

单击看大图

打开进程ID为1924的svchost进程的属性对话框,并切换到“Services”标签页,可以看到其下有“Application Information”服务,该服务以“appinfo.dll”的形式运行在svchost进程中,如附图所示。
单击看大图

在“用户帐户控制”对话框上单击“继续”按钮后,系统获得来自用户的确认信息,接下来我们可以通过Process Monitor监测到由另一个svchost进程(进程ID为1376)加载dllhost的进程映像文件,如附图所示。
单击看大图

双击这条记录,在打开的属性对话框上切换到“stack”标签页,在堆栈信息中发现一个“rpcss.dll”模块,其描述为“分布式COM服务”,如附图所示。原来这就是Windows Vista系统的“DCOM Server Process Launcher”服务,由该服务负责启动dllhost进程。
单击看大图

在Process Explorer中双击打开进程ID为1376的svchost进程的属性对话框,并切换到“Services”标签页,可以看到其下有“DCOM Server Process Launcher”服务,该服务以“rpcss.dll”的形式运行在svchost进程中,如附图所示。
单击看大图

盆盆评注 “Remote Procedure Call (RPC)”服务也是以“rpcss.dll”的形式运行在另外一个svchost进程中。但是两个并没有服务共享同一个svchost进程,这是因为这两个服务的启动帐户不同。“Remote Procedure Call (RPC)”服务的启动帐户是NETWORK SERVICE,而“DCOM Server Process Launcher”服务的启动帐户是SYSTEM。

接下来在Process Monitor中,我们可以看到dllhost进程检查HKCR\AppID\{9DF523B0-A6C0-4EA9-B5F1-F4565C3AC8B8}注册表键值,如附图所示。以便知道应该加载“Timedate.cpl”注册表组件,并最终允许修改系统时间。

单击看大图
5.比较前后访问令牌的SID列表

仔细观察前后两个进程(rundll32进程和dllhost进程)访问令牌中的SID列表,如附图所示,会发现有以下两个显著的不同。
单击看大图

(1) rundll32进程:Administrators组SID被标记为Deny,这表明该进程实际上不属于管理员组。同时访问令牌里只有五个特权,其中并没有“SeSystemTimePrivilege”特权。

访问令牌里包含一个名为“Mandatory Label\Medium Mandatory Level”的标签SID。

(2)dllhost进程:Administrators组SID被标记为Owner,这表明该进程属于管理员组。同时访问令牌里包含“SeSystemTimePrivilege”特权。

访问令牌里包含一个名为“Mandatory Label\High Mandatory Level” 的标签SID。

6.修改系统时区

大家知道,在Windows XP下,我们无法在标准用户下修改系统时区。但是在Windows Vista却可以,无需提升权限,不知道读者朋友有没有考虑过这个问题。

原来这是因为Windows Vista的标准用户多了一个“SeTimeZonePrivilege”(更改时区)特权,所以无需提升权限,就可以修改系统的时区,这给标准用户带来方便。

进一步研究发现,在打开“日期和时间”对话框时,其宿主进程rundll32的访问令牌中,虽然有“SeTimeZonePrivilege”,但是其状态为“Disabled”(如上图所示)。

而只有在单击“更改时区”按钮时,rundll32进程的“SeTimeZonePrivilege”特权才会被激活,如附图所示。
单击看大图

实验结论

1.UAC的实质

当管理员登录时,Explorer进程会获得一个“缩水”的访问令牌,也叫标准用户(Standard User)访问令牌。由于用户进程大多数都是由Explorer启动,所以这些进程会自动继承这份“缩水”的访问令牌(如本例的rundll32进程)。

凭借缩水的访问令牌,用户可以完成绝大多数工作,同时由于用户权限被大大缩小,这样用户进程就不会有意无意破坏系统的完整性,这样就可以大大减少受攻击面。

如果需要执行管理任务,系统会提醒用户进行确认,一旦认可,将会获得完全版本的管理员访问令牌(如本例的dllhost进程)。

用户帐户控制好比给Windows Vista穿上一件铁布衫,有了它的庇护,Windows系统不再奉行“不抵抗”政策,恶意网页胆敢再来“骚扰”,将被毫不犹豫地阻止。同时最终用户不再需要接受额外的培训,一切都由系统自动完成,只需要做出选择即可,您就没事偷着乐吧!

2.标签SID

至于前后两个进程的访问令牌中新出现的标签SID,其中一个是“Mandatory Label\Medium Mandatory Level”,另一个是“Mandatory Label\High Mandatory Level”。这两个帐户,既不能用来登录,似乎也不能用来,到底用来做什么?

原来这是用来标记访问令牌,这样系统看到访问令牌中包含“Mandatory Label\Medium Mandatory Level”的标签SID,马上就可以知道该令牌属于标准用户访问令牌;同样如果令牌中包含“Mandatory Label\High Mandatory Level”的标签SID,马上就知道其属于完全的管理员访问令牌。

那么为什么不在访问令牌中新增一个标志位?例如等于0时就是标准用户令牌,等于1时就是完全权限令牌?这样的话,就不需要新增标签SID了。也许是为了兼容性,毕竟增加一个标志位,就等于要修改访问令牌的数据结构,这可不是一个好主意,而添加几个SID,则相对简单得多。

标签SID的作用很大,当进程需要管理员权限时,系统会根据其父进程的标签SID,来判定是否需要弹出“用户帐户控制”对话框。如果其父进程的标签SID是“Mandatory Label\Medium Mandatory Level”,系统就会弹出“用户帐户控制”对话框。如果父进程的标签SID是“Mandatory Label\High Mandatory Level”,就不会弹出“用户帐户控制”对话框,而是直接运行该目标进程。

由于绝大多数用户进程的父进程是Explorer,所以会弹出“用户帐户控制”对话框。

除此之外, Windows安全子系统还用标签SID来帮助判断一个进程是否可以访问特定的资源对象,是否可以访问某个特定的进程。

盆盆评注 有关标签SID的详细作用,可以参考盆盆发表在ITECN博客上的文章《Windows Vista有趣的标签SID》:http://blogs.itecn.net/blogs/ahpeng/archive/2007/02/27/labelsid.aspx

写在最后

《Windows Internals》能够帮助我们更好地了解Windows的内部运作原理,不管是IT Pro,还是Dev,都可以从中获取有用的信息。期待由潘爱民老师翻译的中文版《Windows Internals》尽快上市。

发表于 作者 ahpeng | 10 评论
归档在: