Windows Sysinternals实战指南

978-7-115-46365-4
作者: 【美】Mark Russinovich(马克·拉西诺维) Aaron Margosis(艾伦·马格西斯)
译者: 刘晖
编辑: 王峰松

图书目录:

详情

本书汇集了微软CTO多年实战经验的总结,全面透彻剖析了Windows系统工具Sysinternals套件的使用方法以及难点、疑点,无论是对广大Windows系统管理员,还是普通用户,如果掌握了本书中的技巧,就能事半功倍的解决日常电脑故障和出现的各种问题。

图书摘要

版权信息

书名:Windows Sysinternals实战指南

ISBN:978-7-115-46365-4

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。


• 著    [美]Mark Russinovich Aaron Margosis

  译    刘 晖

  责任编辑  王峰松

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


Authorized translation from the English language edition, entitled TROUBLESHOOTING WITH THE WINDOWS SYSINTERNALS TOOLS, 2nd Edition, 9780735684447 by RUSSINOVICH, MARK E.; MARGOSIS, AARON, published by Pearson Education, Inc, publishing as Microsoft Press, Copyright © 2016 by Mark Russinovich and Aaron Margosis.

All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc. CHINESE SIMPLIFIED language edition published by POSTS AND TELECOMMUNICATIONS PRESS, Copyright © 2017.

本书中文简体字版由美国Pearson Education 授权人民邮电出版社出版。未经出版者书面许可,不得以任何方式复制或发行本书任何部分。

版权所有,侵权必究。


Windows Sysinternals工具已被很多IT专家和高级用户用作在Windows平台上进行问题诊断和排错,以及深入理解Windows系统的全功能“瑞士军刀”。这本由Sysinternals创始人Mark Russinovich与Windows专家Aaron Margosis联手编著的实战指南图书详细介绍了Sysinternals每款工具的独到功能,并用较多篇幅深入介绍了如何通过几款重量级工具优化Windows系统的可靠性、执行效率、性能以及安全性。最后,还通过大量现实案例介绍了通过这些工具解决程序出错、停止响应、卡顿、恶意软件感染等问题的思路、方法以及完整过程。


新版《Windows Sysinternals实战指南》的到来让人惊喜,我在苏格兰乡村庄园收到这本书的同时正在筹划一次骑行活动,当时的激动之情无疑于首次体验飞行。现在我已经意识到,对于没有魔法的人(我们将其称之为Sysintuggle [1]),无论领悟能力如何,作者正在试图解决“人们为什么不再读说明书了?”这样的问题,而结论实在让人无言,“因为那些小册子根本没什么用”(他们在解决问题的过程中也获得了更多经验和收获,足以应对哪怕最严重的问题)。但其实他们根本没有意识到这本书所蕴含的价值。

我静下心来开始阅读本书。轻抚书脊,平静地翻开,开始浏览。这是一本很有魅力的书,有着最高的质量,仿佛每一页都在彰显着实用的魔法。通过与《Windows Internals》中的理论遥相呼应,读者可以从中获得最全面的知识和神奇的魔力。通过充分利用本书中介绍的技术和思路,可以帮助读者顺利应对各种问题。本书可以帮助读者更好地领悟Windows,预防恶意软件。本书可以告诉读者如何获得见解,更顺利地完成排错,甚至轻松解决蓝屏死机问题。我开始一边读一边做笔记,重点页面开始折角,留白处写满了心得体会,就这样给自己准备了一个不可或缺的参考工具。这本书会在我的书架上占据最醒目的位置。

对于希望将“不可能”变为“可能”的读者,本书提供了巨大的参考价值。如果你在公司中担任系统管理员,那么无论公司规模或大或小,都能从本书中有所收获。Russinovich教授无疑是这个年龄段中最耀眼的天才,他和同事联手合作给我们带来了如此不可或缺的宝藏。

一个著名的人

2016年5月

[1] 译注:此处的“Sysintuggle”是一个自造词。在《哈利·波特》系列电影中,使用麻瓜(Muggle)称呼没有魔法能力的普通人,其中的“M”是魔法(Magic)的首字母,因此这里使用“Sysintuggle”称呼没有“Sysint”能力,即System Internal(系统原理)能力的人。


Sysinternals Suite工具套件包含超过70种适用于Windows平台的高级诊断和排错工具,这些工具由我——Mark Russinovich和Bryce Cogswell开发而来。微软于2006年收购Sysinternals后,这些工具开始通过微软(TechNet旗下)Windows Sysinternals网站免费提供下载和使用。

本书目标在于帮助读者熟悉Sysinternals工具,了解如何更充分地利用这些工具。本书还将介绍一些我和他人使用这些工具解决Windows系统现实问题的范例。

虽然本书是我与Aaron Margosis合著的,但完全表达了我的观点。Aaron也对本书做出了巨大的贡献,这本书的顺利出版离不开他的辛苦工作。

 

注意 有关本书出版过程中的内容改动,请参阅前言“后期改动”一节。

本书介绍了Windows Sysinternals网站(http://technet.microsoft.com/en-us/sysinternals/ default.aspx)提供的所有Sysinternals工具在撰写本文时(2016年初夏)包含的全部功能。然而Sysinternals工具的开发进度非常快,现有工具会不断获得新增功能,此外时不时还会引入新的工具(为及时了解最新进展,请订阅“Sysinternals网站讨论”博客的RSS信息源:http://blogs.technet.microsoft.com/sysinternals/)。在你阅读本书的时候,其中一些内容可能已经过时了,不过你依然应该尽量使用最新版Sysinternals工具,以便获得新增功能以及各种瑕疵修复。

本书并未涉及已弃用并不再通过Sysinternals网站提供的工具。如果你依然在使用RegMon(注册表监视器)或FileMon(文件监视器),可以考虑使用第5章介绍的Process Monitor取代这些工具。计算机行业首个Rootkit检测工具Rootkit Revealer(正是这个工具发现了“Sony rootkit”)也已完成使命顺利退役。此外还有其他几个提供了独特价值的工具(例如Newsid和EfsDump)也已经由于不再需要或Windows已包含类似的功能而退役。

我开发的首个Sysinternals工具是Ctrl2cap,它的诞生有一定的必然性。我从1995年开始使用Windows NT,之前主要使用UNIX,该系统的键位设置在标准PC键盘上Caps Lock键的位置是Ctrl键。我不想适应新的键位布局,于是开始研究Windows NT设备驱动的开发,并写了一个能将Caps Lock键的按压转换为Ctrl键的按压结果并传递至Windows NT输入系统的驱动。Ctrl2cap目前依然放在Sysinternals网站上,我还在自己的所有系统中使用着。

Ctrl2cap是我所开发的深入至Windows NT底层技术,同时提供了实用功能的众多工具中的第一个成员。在这之后我与Bryce Cogswell联手开发了NTFSDOS。我和Bryce最初在卡内基梅隆大学(Carnegie Mellon University)研究生院相识,我们一起完成了多篇学术论文,并发起了一个为Windows 3.1开发软件的初创项目。当时我产生了一个念头,想要写一个能够让用户通过无处不在的DOS软盘访问NTFS分区的工具。Bryce觉得这个工具在编程方面会遇到一些有趣的挑战,大概一个月后我们完成了该工具的开发并发布了第一个版本。

随后我还与Bryce合作开发了另外两个工具:Filemon和Regmon。NTFSDOS、Filemon以及Regmon这3个工具奠定了Sysinternals的基础。当时我们发布的Filemon和Regmon可运行于Windows 95和Windows NT系统上,可用来查看文件系统和注册表活动,这样的功能在当时是独一无二的,很快成为我们排错过程中必不可少的帮手。

随后Bryce和我决定将这些工具共享给其他人,但当时我们并没有自己的网站,所以最初我们将这些工具放在了另一位友人——Andrew Schulman的网站上。我最初认识他时,他也在研究DOS和Windows 95的内部运作。由于当时需要通过中间人来发布这些工具,因此我们无法根据进度及时更新这些工具并修复瑕疵,因此Bryce和我在1996年9月创建了NTInternals.com网站,通过这个网站发布我们的工具,以及我们撰写的有关Windows 95和Windows NT内部运作的文章。后来我们觉得可以通过销售自己开发的工具赚点零花钱,所以在网站上线的同一个月,我们成立了商用软件公司Winternals Software,并通过NTInternals.com上放置的一个横幅广告为新公司吸引流量。我们以Winternals Software公司身份发布的第一个工具是NTRecover,这个工具可以帮助用户将无法启动的Windows NT系统的磁盘挂载到其他可以使用的计算机上,然后像访问本地磁盘一样访问故障计算机中的文件。

NTInternals.com的使命是分发免费的工具软件,我们利用对Windows操作系统的深入理解开发了一系列功能强大的诊断、监视和管理工具。经过几个月的发展,该网站终于在1996年12月发展成图0-1的样子(这还要感谢Internet Archive的Wayback Machine功能可以让我们随时回顾历史),当时该网站的每天访客数已经达到1500人,逐渐成为互联网革命开始前的“上古时代”最受欢迎的Windows工具网站。1998年,在微软公司律师的“启发”下,我们将网站改名为Sysinternals.com。

图0-1 NTInternals.com网站

过去多年来,我们开发的工具一直在不断完善。我们根据自己的实际需要,根据大量早期用户的反馈和建议,并根据我们所设想的有关Windows内部各类信息的呈现方式开发了更多工具。

Sysinternals工具主要可分为3个基本类别:针对程序开发工作的,针对系统排错工作的,以及针对系统管理工作的。可以获取并显示程序调试语句的DebugView工具是我所开发的第一个面向开发者的工具,该工具主要用来帮我开发设备驱动。显示进程所加载DLL信息的DLLView,以及可以显示进程所打开句柄的进程列表GUI工具HandleEx,这两个工具是最早开发出来的排错工具(我在2001年将DLLView和HandleEx的工具合并在一起开发了Process Explorer)。本书第7章将要介绍的PsTools则是最受欢迎的管理工具,为了方便大家下载,我把它们捆绑成了一个工具套件。PSTools系列首个工具PsList最初的灵感来源于UNIX中用于查看进程列表的PS命令。这些工具的数量和功能不断增加,很快形成了一个工具套件,可以帮助用户更轻松地针对远程系统执行各种任务,而无须事先在远程系统上安装任何特殊软件。

到了1996年,我开始为《Windows IT Pro》杂志撰文,我的文章主要介绍Windows内部原理和Sysinternals工具,此外我还写了介绍其他功能的文章,例如1996年撰写的一篇引起广泛争议的文章让我在微软内部正式扬名,尽管大部分意见并非正面的。当时我在“Inside the Difference Between Windows NT Workstation and Windows NT Server”这篇文章中指出,Windows NT Workstation和Windows NT Server操作系统之间的差异仅仅是微软出于产品营销角度的考虑而产生的。

随后我发布的Ntcrash和Ntcrash2工具进一步恶化了微软与我的关系,这两个现在被称之为“Fuzzer”[1]的工具会使用随机生成的垃圾数据阻塞Windows NT系统调用接口。这些工具可检测出大量使用弱参数验证(Weak parameter validation),进而可能由于非特权用户模式进程造成内存出错和蓝屏崩溃的系统调用(在20世纪90年代的系统安全大环境下,这种问题被简单地视作可靠性方面的小瑕疵,不像现在会被视作“重要”的安全瑕疵)。

随着这些工具的继续完善和增加,我开始考虑专门撰写一本有关Windows内部原理的图书。当时市面上已经有了类似的图书:《Inside Windows NT》(Microsoft Press,1992年出版),本书的第一版由Helen Custer撰写,并伴随Windows NT 3.1一起出版。本书第二版由操作系统领域的知名专家、讲师和作者,当时就职于DEC公司的David Solomon围绕Windows NT 4.1重写并进行了完善。我并没有从头开始写一本类似的书,而是联系他并建议与他联手撰写主要面向Windows 2000的第三版。在1996年那篇文章余波渐平后,随着我直接向Windows开发人员提交Windows瑕疵报告,我与微软的关系正在逐渐回温,但David依然需要获得微软的允许,好在微软也同意了。

随后David Solomon和我联手撰写了本书的第三、第四、第五以及第六版。从第四版开始,本书改名为《Windows Internals》。从第五版开始,我们选择了Alex Ionescu作为合著者。到第六版,书中包含的内容实在太多,于是我们决定将该书分为上下两部。就在我们完成《Inside Windows 2000》(Microsoft Press,2000年出版)后不久,我开始与David合作讲授他的Windows内部原理研讨会课程,并加入了我所撰写的内容。这一由微软向全球Windows开发者提供的课程大量借助Sysinternals工具向学生介绍有关Windows内部运作的深入信息,当这些学生返回自己的开发者和IT专业人员工作岗位后,也陆续开始使用我们开发的这些工具。

到了2006年,我与微软的关系已经好转并维持了多年,Winternals也逐渐开发出一整套企业管理软件,经过多年的发展已经有了100多名员工,同时Sysinternals工具的每月下载量达到了2百万次。2006年7月18日,微软收购了Winternals和Sysinternals。不久之后Bryce和我(图0-2是我们在2006年的合影)加入了Windows团队并搬家到雷德蒙。目前我担任Microsoft Azure首席技术官的职务,主要负责领导Azure云计算平台的技术战略和架构。

图0-2 Mark Russinovich和Bryce Cogswell的合影

当时的收购,主要目标在于确保Bryce和我开发的工具能继续免费提供,并且我们构建的社区能够继续发展,这两个目标都实现了。目前,托管在technet.microsoft.com上的Windows Sysinternals网站已成为整个TechNet访问量最大的网站之一,平均每月下载量高达450万次。Sysinternals的高级用户会时不时访问该网站获取最新版工具以及新发布的工具,例如最近我们发布的Sysmon和PsPing,与此同时他们也会积极参与Sysinternals社区,在撰写本文时,这个飞速成长的社区已经有超过42000名注册用户。我还会继续对现有工具进行完善,并增加新的工具。

很多人曾建议如果能针对这些工具写一本书就太好了,但直到David Solomon也提出类似的建议,这个项目才开始提上日程。我在微软承担的工作使得我没有足够的时间另外写一本书,但David觉得可以找人来帮忙。最终Aaron Margosis同意与我合作,为此我感到很高兴。Aaron是Microsoft Cybersecurity Services部门的首席顾问,他对Windows安全性和应用程序兼容性有着极为深入的理解。我与Aaron相识多年,他卓越的写作技能,对Windows内部原理的熟悉程度,以及对Sysinternals工具的娴熟掌握使得他成为理想的合著者。

本书适合Windows IT专家、高级用户,以及希望更充分利用Sysinternals工具的开发者阅读。无论你对这些工具有怎样的了解,无论你管理着大企业或小公司的系统,或者只是维护着家人或朋友的计算机,本书中涉及的工具、技巧,以及经验都可以帮助你更高效地对Windows故障进行排错,让系统管理运维和监控工作变得更简单。

本书会假设你已经熟悉并了解Windows操作系统。如果能对进程、线程、虚拟内存,以及Windows命令行等概念有基本了解,则将对阅读本书起到更大的帮助,本书第2章“Windows核心概念”对上述部分概念也有所涉及。

本书分为3部分。第1部分“入门”概括介绍了Sysinternals工具和Sysinternals网站,并介绍了所有工具中通用的功能,会告诉你如何获得帮助,同时还介绍了可以帮你更好地理解整个平台及这些工具所呈现信息应了解的一些Windows核心概念。

第2部分“使用指导”详细介绍了所有Sysinternals工具的功能、命令行选项、系统要求,以及注意事项。在大量屏幕截图和用例的帮助下,这部分内容可以回答你关于这些工具可能产生的各种问题。对于一些重要的工具,例如Process Explorer和Process Monitor,会用专门的章节进行介绍,后续章节则会按照类别介绍不同的工具,例如安全工具、Active Directory工具,以及文件工具。

第3部分“排错——‘难解之谜’”通过真实案例介绍了Aaron和我,以及全球各地管理员和高级用户使用Sysinternals工具解决实际问题的过程。

为了让相关信息更易读,更益于参照,本书中内容的呈现使用了下列约定。

procdump
    [-ma | -mp | -d callback_DLL] [-64] [-r [1..5] [-a] [-o]
    [-n count] [-s secs]
    [-c|-cl percent [-u]] [-m|-ml commit] [-p|-pl counter_threshold]
    [-e [1 [-g] [-b]]] [-h] [-l] [-t] [-f filter,...]
    {
      {{[-w] process_name}|service_name|PID } [dump_file | dump_folder] } |
      {-x dump_folder image_file [arguments]}
    }

上述代码意味着-ma-mp-d是可选使用的;如果使用-d,必须为callback_DLL赋值。此外还可选择使用-f选项,如果使用,则必须提供一个或多个filter值。最后四行的分组意味着必须指定一个process_nameservice_namePID,或使用-x选项并提供dump_folderimage_file

除非特别注明,Sysinternals工具可在下列受支持的Windows版本,包括64位版中运行:

一些工具运行时需要管理权利,其他工具中部分功能可能需要管理权利。

在本书即将完工的过程中,为了对Windows Server 2016新增的Nano Server模式提供支持,本书涉及的很多工具均发布了新版本。Nano Server是一种小痕迹、无头式(Headless)Windows Server 2016安装选项,仅包含最少量的功能和服务。对Sysinternals用户来说,最值得关注的地方在于Nano Server不包含32位子系统和GUI组件。正如在本书“第1章:Sysinternals工具入门”中所述,每款Sysinternals工具均会和其他必要的文件,例如64位库文件一起打包成一个32位可执行文件,这些嵌入的资源可按需提取并执行。当然,所有这些32位映像均无法在Nano Server上运行,于是我为控制台模式的工具创建了原生的64位版本,并在文件名末尾附加了“64.exe”字样。例如64位版SigCheck.exe变成SigCheck64.exe。此外我还创建了控制台版本的LoadOrd(加载顺序)工具:LoadOrdC.exe,以及一个原生的64位版LoadOrdC64.exe。

Nano Server的管理严重依赖PowerShell Remoting。PowerShell会将标准错误(stderr)流的所有输出视作对错误的陈述。控制台模式的Sysinternals工具会始终将Banner和语法信息写入Stderr。为改善这些工具对PowerShell,尤其是Nano Server的支持,现在这些工具已可将Banner和语法信息写入标准输出(stdout)流,并会使用新增的-nobanner命令行选项忽略Banner输出。然而要注意,该选项取代了以往很多工具用来实现类似功能的-q选项。

首先Aaron和我要感谢Sysinternals的共同创始人Bryce Cogswell,他对Sysinternals工具的开发做出了卓越贡献。借助我们之间的良好合作,Bryce和我才有机会联手发布各种实用的Sysinternals工具。Bryce已于2010年10月从微软退休,无论他今后的目标是什么,我们希望他好运。

此外也要感谢David Solomon鼓励Mark撰写这本书,负责对本书很多章节的审阅,并为第一版作序。多年来,Dave都是最热心的Sysinternals“布道师”之一,针对不同新功能提供了宝贵的建议。

感谢Luke Kim在本项目升级到最新版Microsoft Visual Studio,为开发工作提供Visual Studio Team Services(VSTS)源代码控制系统,优化构建和发布流程,管理Sysinternals.com网站和live.sysinternals.com基础架构服务器(现已运行在Azure之上)过程中提供的大量帮助。同时还要感谢Kent Sharkey发布的Sysinternals.com网站更新。

几年前,只有Bryce和我负责这些工具的开发,但我也开始逐渐接受其他开发者的贡献。Ken Johnson、Andrew Richards、Thomas Garnier、David Magnotti、Dmitry Davydok、Daniel Pearson、Justin Jiang和Nano Server团队的其他成员、Giulia Biagini、Pavel Yosifovich,以及Aaron Margosis均对一些功能的开发做出了自己的贡献。

此外还要感谢John Sheehan对以往未曾公开过的AppContainers工作原理进行的深入介绍;Alex Ionescu提供了有关受保护进程的技术细节;感谢Ned Pyle、Marty Lichtel和Carl Harrison允许将他们以前发布的案例纳入本书。

本书的技术审阅和修订过程中,得到了来自下列人员提供的宝贵见解和建议,我们也要向他们表示感谢:Andrew Richards、Bhaskar Rastogi、Bruno Aleixo、Burt Harris、Chris Jackson、Crispin Cowan、Greg Cottingham、Ken Johnson(即Skywing)、Luke Kim、Mario Raccagni、Steve Thomas,以及Yong Rhee。

Aaron和我对于邀请那个著名的人为这本书作序本来并没有抱太大希望,他竟然同意了,至今我们依然难以置信。万分感谢N.P.(Noted Person)[3]

我们还要感谢Microsoft Press的Devon Musgrave(策划编辑兼开发编辑)和Carol Dillingham(项目编辑)在本书出版过程中付出的辛苦工作,尤其要感谢他们在本来规定好的交稿日期“无限”延后的过程中表现出的耐心。感谢Waypoint Press的Steve Sagman在项目管理和排版方面提供的支持。同时要感谢负责技术加工的Christophe Nasarre和负责文案编辑的Roger LeBlanc。Aaron还想向自己的妻子Elise和孩子Elana、Jonah和Gabriel表示感谢,谢谢他们的爱和支持。另外Aaron还要感谢Brenda Schrier拍摄的作者照片,并要感谢华盛顿国家棒球俱乐部和西汉姆联队。

Mark也希望对他的妻子Daryl和女儿Maria表示感谢,感谢她们对自己工作的支持。

我们已经尽了最大努力确保本书内容精确无误。你可以访问http://aka.ms/Troubleshoot Sysint/errata查看本书的最新勘误列表和相应的修订。

如果发现勘误中未列出的错误,也可通过上述页面提交给我们。

如果需要进一步支持,可向Microsoft Press图书支持部门发送电子邮件:mspinput@ microsoft.com。

然而请注意,上述邮件地址并不提供有关微软软件的产品支持。若要获得有关微软软件或硬件产品的支持,请访问http://support.microsoft.com。

从技术概述到针对特定话题的深入信息,Microsoft Press针对种类丰富的不同话题提供了免费电子书。这些电子书分为PDF、EPUB,以及适用于Kindle的Mobi格式,可随时通过下列地址下载:

http://aka.ms/mspressfree

你也可以经常访问上述地址下载最新发布的电子书!

对于Microsoft Press来说,读者的满意是我们的头等要务,读者的反馈是我们最珍视的资产。请通过下列地址告诉我们你对这本书的想法:

http://aka.ms/tellpress

这个调查非常简短,我们会仔细阅读每位读者的意见和建议。提前感谢大家的反馈!

书读完了联系也不能中断,你可以关注Microsoft Press的Twitter账号:http://twitter.com/ MicrosoftPress。

[1] 译注:此处的Fuzzer是指用于Fuzz testing(模糊测试)的工具,这是现在比较常见的一种测试方法,其核心思想是以自动或半自动方式生成随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(Assertion)失败,以发现可能的程序错误,如内存泄漏。这种模糊测试常用于检测软件或计算机系统的安全漏洞,详见:https://en.wikipedia.org/ wiki/Fuzz_testing。

[2] 所有Sysinternals工具均为Win32应用,仅支持x86和x64架构系统,不兼容Windows 10 Mobile、IoT、Xbox等。

[3] 那个“著名的人”,他的秘密身份其实是Chris Jackson,即The App Compat Guy,亦即Captain Inappropriate。


Mark Russinovich是Microsoft Azure首席技术官,主要负责微软云计算平台的技术战略和架构。他是分布式系统、操作系统内部原理以及网络安全方面公认的专家。他撰写了Jeff Aiken系列网络惊险小说《Zero Day》《Trojan Horse》以及《Rogue Code》,同时也是Microsoft Press出版的《Windows Internals》多版图书的合著者。Russinovich在1996年创立了Winternals Software公司,该公司2006年被微软收购,同时Russinovich也加入了微软。此外Russinovich还建立了Sysinternals网站,并通过该网站创作和发布了数十款广受欢迎的Windows管理和诊断工具。他还是业内各大技术会议,包括Microsoft Ignite、Microsoft//build、RSA Conference等活动的特邀演讲嘉宾。

你可以通过markruss@microsoft.com联系Mark,或关注他的Twitter账号:https:// www.twitter.com/markrussinovich。

Aaron Margosis是微软Global Cybersecurity Practice部门首席顾问,从1999年起开始与安全意识极强的客户打交道。Aaron专精于Windows安全、最小特权、应用程序兼容性,以及锁定环境的配置。他是微软各大会议的主要发言人,开发了很多帮助组织实现高安全环境的常用工具,包括LUA Buglight、Policy Analyzer、IE Zone Analyzer、LGPO.exe(本地组策略对象工具)以及MakeMe Admin,这些工具均可从他的个人博客(https://blogs.msdn. microsoft.com/aaron_margosis),以及他作为主要作者的两个团队博客(https://blogs.technet.microsoft.com/fdcc和https://blogs.technet. microsoft.com/SecGuide)下载。

你可以通过aaronmar@microsoft.com联系Aaron,或关注他的Twitter账号:https:// www.twitter.com/AaronMargosis。

刘晖,IT技术和Windows操作系统爱好者,热衷于研究Windows客户端和服务器技术,多次当选微软最有价值专家(MVP)称号,曾出版过多本有关微软技术的原创和翻译图书。



Sysinternals工具是一套用于微软Windows平台,免费的高级管理、诊断和排错工具,由Sysinternals的创始人我本人(Mark Russinovich)和Bryce Cogswell[1]共同开发而来。2006年7月被微软收购后,这些工具已可通过微软TechNet网站下载。

为数众多的Sysinternals工具可以:

虽然Sysinternals经费有限无法成立正规的产品组,但我依然会快速发布新的功能、工具以及瑕疵修复。某些情况下我可以在一周内根据用户建议提供某些实用,并且易于实现的功能。

然而由于不具备完善的产品组以及正规的测试部门,这些工具只能“依原样”提供,无法得到微软产品支持部门的官方支持。Sysinternals团队在自己的网站上维护了一个专用的社区支持论坛,下文将介绍这个论坛,我会尽可能及时地修复用户汇报的各种问题。

Sysinternals工具针对Windows操作系统的不同领域提供了各种类型的功能。虽然有一些涵盖各类操作、功能极为全面的工具,例如Process Explorer和Process Monitor,但也有一些只专注于特定某个领域的工具,例如“进程工具”以及“文件工具”。很多工具包含图形用户界面(GUI),但也有一些只提供各类命令行接口的控制台工具,这些工具主要是为了实现自动化操作或方便用户在命令行下使用。

本书将重点介绍4个重要工具(Process Explorer、Autoruns、Process Monitor以及ProcDump),每个工具将用一章专门介绍。后续章节将各用一章介绍同属于一个类型的其他工具。表1-1列出了这些章节的内容,并简要介绍了每一章将会涉及的工具。

表1-1 章节主题

工具

描述

第3章,Process Explorer

Process Explorer

任务管理器的代替品,可显示有关进程和线程的详细信息,包括父子关系、加载的DLL以及打开的对象句柄,例如使用中的文件

第4章,Autoruns

Autoruns

通过分组的方式显示会在系统启动时、用户登录时以及运行Internet Explorer时自动运行的软件,并可供用户启用或禁用这些内容

第5章,Process Monitor

Process Monitor

实时记录有关文件系统、注册表、网络、进程、线程以及映像加载活动的细节信息

第6章,ProcDump

ProcDump

在满足特定条件,例如呈现CPU使用尖峰或窗口不响应的情况下为进程创建内存转储

第7章,PsTools

PsExec

远程执行进程,或以Local System身份执行进程并对结果输出进行重定向

PsFile

远程列出或关闭打开的文件

PsGetSid

显示计算机、用户、组,或服务等安全主体的安全标识符(SID)

PsInfo

列出有关系统的信息

PsKill

按照名称或进程ID(PID)终止进程

PsList

列出有关进程和线程的详细信息

PsLoggedOn

列出本地登录或通过远程连接登录的账户

PsLogList

转储事件日志记录

PsPasswd

为用户账户设置密码

PsService

列出并控制Windows服务

PsShutdown

关闭、注销本地或远程系统,或更改其电源状态

PsSuspend

挂起并恢复进程

第8章,进程和诊断工具

VMMap

显示有关进程虚拟和物理内存使用情况的细节信息

DebugView

监视本地或远程计算机生成的,用户模式和内核模式的调试输出信息

LiveKd

在无需重启动至调试模式的前提下,针对运行中的本地系统或Hyper-V来宾系统快照运行标准的内核调试器,并可用于对运行中的系统创建内存转储

ListDLLs

在控制台窗口中显示已载入系统的DLL的详细信息

Handle

在控制台窗口中显示被系统中进程打开的对象句柄的详细信息

第9章,安全工具

SigCheck

验证文件签名,显示版本和与映像有关的其他信息,通过VirusTotal.com查询反恶意软件引擎

AccessChk

搜索为特定用户或组授予权限的对象,提供有关所授权限的详细信息

Sysmon

监视并报告系统活动,借此发现攻击行为

AccessEnum

搜索文件或注册表层次结构,找出权限可能有变化的位置

ShareEnum

枚举网络中的文件和打印机共享,并显示可访问这些共享的人

ShellRunAs

重新提供类似于Windows Vista中以不同用户身份运行程序的能力

Autologon

配置用户账户在系统启动后自动登录

LogonSessions

枚举计算机上活跃的本地安全机构(Local Security Authority,LSA)登录会话

SDelete

安全地删除文件或目录结构,对硬盘上所有未分配区域执行数据擦除操作

第10章,Active Directory工具

AdExplorer

显示Active Directory对象并启用对这些对象的编辑

AdInsight

追踪Active Directory轻型目录访问协议(LDAP)API调用

AdRestore

枚举并还原已删除的Active Directory对象

第11章,桌面工具

BgInfo

在桌面墙纸上显示计算机配置信息

Desktops

在单独的虚拟桌面上运行应用程序

ZoomIt

放大屏幕上显示的内容,并提供屏幕画面标注功能

第12章,文件工具

Strings

在文件中搜索嵌入的ASCII或Unicode文本

Streams

找出包含可选数据流的文件系统对象,并删除这些数据流

Junction

列出并删除NTFS目录交接点

FindLinks

列出NTFS硬链接

DU

列出目录层次结构的逻辑大小和磁盘空间占用大小

PendMoves

查看计划在下一次系统重启动时执行的文件操作

MoveFile

安排在下一次重启动系统时所要执行的文件操作

第13章,磁盘工具

Disk2Vhd

针对物理磁盘创建虚拟硬盘(VHD)映像

Sync

将磁盘缓存中未写入的改动写入至物理磁盘

DiskView

以图形化方式显示卷中每个簇的映射信息,帮助用户查看每个簇保存了哪个文件,以及特定文件使用了哪些簇

Contig

对特定文件执行碎片整理,或显示特定文件的碎片化程度

DiskExt

显示有关磁盘范围的信息

LDMDump

显示逻辑磁盘管理器(LDM)数据库中有关动态磁盘的详细信息

VolumeID

更改卷ID(也叫做卷序列号)

第14章,网络和通信工具

PsPing

测量TCP或UDP数据包的单向和轮循时间、延迟以及带宽

TCPView

列出活跃的TCP和UDP端点

Whois

查看互联网域名注册信息或执行反向DNS查找

第15章,系统信息工具

RAMMap

提供有关物理内存使用情况的详细视图

RU

列出所选注册表键的注册表空间使用情况

CoreInfo

查看处理器和Windows系统是否可以支持各种功能,例如“不可执行”内存页,并可显示逻辑处理器与核心、处理器插槽、非一致内存访问(NUMA)节点以及处理器组之间的映射关系

WinObj

显示Windows的对象管理器名称空间

LoadOrder

显示Windows加载各类设备驱动并启动不同服务的大致顺序

PipeList

列出正在侦听的命名管道

ClockRes

显示系统时钟的当前、最大和最小精度

第16章,其他工具

RegJump

启动注册表编辑器并直接定位至指定的注册表路径

Hex2Dec

在十六进制和十进制之间进行双向转换

RegDelNull

搜索并删除名称中包含嵌入式NUL字符的注册表键

Bluescreen Screen Saver

可以逼真模仿“蓝屏死机”界面的屏幕保护程序

Ctrl2Cap

将Caps Lock键击键事件转换为Control键击键事件

若要访问Sysinternals网站(如图1-1所示),最简单的方法是浏览http://www. sysinternals.com,随后将自动重定向至微软TechNet网站Sysinternals首页,目前该首页的地址是http://technet. microsoft.com/sysinternals。除了所有Sysinternals工具,该网站还提供了很多相关资源与链接,包括培训、图书、博客、文章、网络广播、即将举办的活动以及Sysinternals社区论坛。

图1-1 Windows Sysinternals网站

用户可以只下载自己需要的Sysinternals工具,或下载名为Sysinternals Suite,包含所有工具的压缩(.Zip)文件。Sysinternals首页上的链接可以直接打开特定工具的下载页面。工具索引页列出了所有工具的清单,并包含到每个类别的链接,例如文件和磁盘工具,或网络工具,单击后即可查看该类别下包含的所有工具。

下载的每个工具都被打包为压缩(.Zip)文件,其中包含了一个或多个可执行文件以及最终用户许可协议(EULA)文本文件,此外部分工具可能还包含联机帮助文件。

 

注意 每个PsTool工具只能以PsTools工具套件或Sysinternals Suite套件的形式打包下载。

本书的合著者Aaron习惯于创建一个“C:\Program Files\Sysinternals”目录,将整个Sysinternals Suite套件内容提取到这个文件夹中,这样其他非管理员用户就无法修改其中的内容了。随后他会将这个位置加入Path系统环境变量中,这样即可从任何位置,包括从Windows 7开始菜单的搜索框,以及从Windows 8.1开始界面的搜索框随时启动所需的工具,如图1-2所示。

图1-2 在Windows 7开始菜单(左)或Windows 8.1开始界面(右)的
搜索框中,通过路径搜索启动Procmon

提取文件前取消对.Zip文件的“锁定”

 

在从下载的.Zip文件中提取内容之前,首先应移除会让Windows将该内容视为不可信,并显示类似图1-3和图1-4所示警告和错误信息的标记。Windows附件执行服务会为.Zip文件增加一条代表该文件来自互联网的可替换数据流(ADS),通过Windows资源管理器从中提取文件时,这样的ADS会被附加至提取的所有文件中。

图1-3 打开互联网上下载的文件时Windows会显示警告信息

图1-4 如果被标记为来自互联网,编译后的HTML帮助(CHM)文件将无法正确显示内容

移除ADS的方法之一是在Windows资源管理器中打开该.zip文件的属性对话框,单击常规选项卡底部的【解锁】按钮,如图1-5所示。另一种方法是使用本书第12章“文件工具”中介绍的Sysinternals Streams工具。

图1-5 对于下载的文件,其属性对话框的底部会显示【解锁】按钮

Sysinternals Live是一个可以帮助用户无需事先查找、下载并提取,即可直接从网络上运行Sysinternals工具的服务。Sysinternals Live的另一个优势在于可以确保用户始终能够运行最新版的工具。

要在Internet Explorer中通过Sysinternals Live运行工具,请在地址栏输入http://live.sysinternals.com/工具名.exe(例如http://live.sysinternals.com/procmon.exe)。或者使用UNC形式的Sysinternals Live路径,例如\live.sysinternals.com\tools\工具名.exe(请注意UNC格式中增加了一个“Tools”子目录,直接在浏览器中输入URL时无需输入该子目录)。例如运行\live.sysinternals.com\tools\procmon.exe可启动最新版Process Monitor。

 

注意 使用Sysinternals Live启动工具所用的UNC语法要求系统中运行了WebClient服务。在新版Windows中,该服务可能并未配置为自动启动。直接启动该服务(例如运行net start webclient)要求用户具备管理员权限。用户可以在不具备管理员权限的情况下间接启动该服务,为此只需要在命令行中运行net use \live.sysinternals.com或在Windows资源管理器中浏览\live.sysinternals.com 即可。

用户还可以为\live.sysinternals.com\tools 添加盘符,或在Windows资源管理器中以远程共享的形式打开该目录,如图1-6所示。同理,用户也可以在浏览器中访问http://live. sysinternals.com 以查看整个Sysinternals Live目录。

图1-6 Windows资源管理器中显示的Sysinternals Live

为了在无需安装的情况下更简单地进行打包、分发和转移,所有Sysinternals工具都是一个可直接启动的32位可执行映像。程序运行中所需的全部资源均已嵌入映像中,可在运行时自动提取至文件所在目录,如果该目录不可写(例如文件位于只读介质上),则会保存在当前用户的%TEMP%目录中。当不再需要时,程序会自动删除提取出的文件。

通过这种技术Sysinternals工具可以更方便地使用,例如可同时支持32位和64位系统。对于在64位Windows上需要64位版本才能正确运行的工具,32位主程序可识别CPU体系结构,提取相应的x64或IA64库文件并启动。例如在x64系统中运行Process Explorer时,会看到一个Procexp64.exe以子进程的形式运行在Procexp.exe进程下面。

 

注意 如果程序文件提取至%TEMP%,在禁止从%TEMP%目录执行的情况下,程序将无法运行。例如AppLocker规则可能进行此类限制,或%TEMP%目录的权限通过修改取消了执行权限。

大部分使用内核模式驱动的Sysinternals工具会将驱动文件提取至%SystemRoot%\ System32\Drivers,随后加载所需驱动并删除驱动文件。在系统关机前,驱动映像会始终保持在内存中。当运行了包含新版驱动的新版工具后,可能需要重启动系统才能加载新版驱动。

Windows Sysinternals论坛地址为http://forum.sysinternals.com(如图1-7所示),如果在使用Sysinternals工具过程中遇到疑问或希望报告问题,这里是首选,也是最适合的地方。用户可以在这里使用关键字搜索帖子和话题,查看他人是否遇到过类似情况。论坛中为每个主要的Sysinternals工具都设立了子论坛,此外还有用于提交想法和功能/工具更新建议的板块。用户还可以在论坛中讨论有关Windows内部原理、开发、排错以及恶意软件等问题。

图1-7 Windows Sysinternals论坛

论坛发帖前需要注册并登录,注册只需要提供最少量的信息。注册完毕后即可在特定板块中订阅话题回复或新帖子的通知,同时可通过私信与其他成员联系。

订阅Sysinternals网站讨论博客是在发布新工具,现有工具有更新,或Sysinternals网站新发布其他内容后获得通知的最佳方式。强烈建议大家尽量使用最新版工具,工具中存在的很多Bug都可以通过版本更新的方式解决。网站博客地址为http://blogs.technet.com/ b/sysinternals。虽然博客首页只列出了重要工具的更新,但其实所有更新,无论大小都会发布到这个博客中。

我在自己的博客上探讨Windows内部原理、安全以及排错等话题的内容。这个博客上与Sysinternals有关的两个系列文章非常受欢迎:“案例”系列文章介绍了如何使用Sysinternals工具解决日常工作中遇到的问题,“挑战极限”系列文章介绍了Windows中的资源局限、监视方法,以及可能对用户产生的影响。我的个人博客的地址为:

http://blogs.technet.com/b/markrussinovich

在Sysinternals首页单击“Mark的博客”链接可以看到我发布的所有博客文章完整列表。

本书的合著者Aaron也通过自己的博客讨论Sysinternals、安全、应用程序兼容性,以及其他技术话题,他也会通过这些博客网站发布各种工具:

http://blogs.msdn.com/b/aaron_margosis

http://blogs.technet.com/b/fdcc

http://blogs.technet.com/b/secguide

在Sysinternals首页单击“Mark的网络广播”可以看到一个列表,其中列出了我在TechEd和其他技术大会上做过的演讲,所有内容均可免费点播,内容涵盖“最受欢迎的‘无解案例’讲座”、Sysinternals排错方法讲座、Channel 9访谈以及我主持过的Springboard虚拟圆桌讨论会。

Sysinternals工具是免费提供的。用户可以在自己的计算机以及公司计算机上安装并使用任意数量的软件副本。然而这些软件的使用需要遵守第一次启动工具时显示的许可条款,以及链接到Sysinternals首页的软件许可页面中所列出条款的要求。

用户在系统上运行每个工具前必须接受最终用户许可协议(EULA)。首次在一台计算机上运行某个特定工具时,哪怕运行的是控制台工具,都会看到如图1-8所示的EULA对话框。用户必须单击【同意】按钮该工具才能启动。

图1-8 PsGetSid的最终用户许可协议

由于该对话框的显示会对自动化操作或其他非交互式使用场景产生干扰,大部分Sysinternals工具可接受命令行参数/accepteula,使用该参数意味着用户同意许可条款。例如下列命令可以在非交互式上下文中使用PsExec(将在第7章介绍)在server1上运行LogonSessions.exe(将在第9章中介绍),其中LogonSessions.exe命令行的/accepteula参数可以防止执行该命令过程中因为等着按下同意按钮而陷入无尽的等待中:

PsExec \\server1 logonsessions.exe /AcceptEula

但要注意,某些Sysinternals工具由于尚未更新,还不能支持/accepteula参数。对于这些工具,用户可能需要手工设置标记以代表接受协议。为此可在命令行中执行下列操作,该操作可在server1注册表的HKEY_CURRENT_USER\Software\Sysinternals分支下为每个工具创建EulaAccepted注册表键:

psexec \\server1 reg add hkcu\software\sysinternals\pendmove /v eulaaccepted /t reg_dword /d 1 /f

对于你所拥有的,或由你提供支持的设备,可安装和使用的软件数量无限制。

不可以。微软并未提供任何分发许可,因此第三方哪怕免费分发也是不允许的。微软鼓励大家从微软下载中心获取这些工具,或可直接通过网络运行,这样即可始终用上最新版的工具。

Sysinternals源代码已经不再提供下载或许可了。

是的。微软目前并不准备撤销这些工具或对其收费。

所有Sysinternals工具完全“依原样”提供,不提供微软的官方支持。不过微软提供了专门的Sysinternals社区支持论坛(http://forum.sysinternals.com),用户可以在这里汇报问题或提交新功能建议。

[1]  Bryce于2010年从微软退休,已经不再承担有关Sysinternals工具的相关工作。


对Windows的工作原理了解越深入,从Sysinternals工具中获得的价值就越多。为了帮助大家更好地理解一些常被误解的话题,本章将概括介绍几个与各种Sysinternals工具密切相关的Windows概念。《Windows Internals》(Microsoft Press,2012年出版)[1]是目前对Windows核心操作系统组件介绍得最为完善和全面的图书。你正在阅读的这本书只是对Windows内存管理等复杂概念进行了最为浅显的介绍,毕竟本书的主题是Sysinternals工具而非Windows,在深度和详细程度上无法比拟《Windows Internals》。另外本书也没有详细介绍Windows架构或其他基本概念,本书会假设你已经了解这些内容,例如“注册表是什么”,或“TCP和UDP有什么区别”。

本书涵盖的话题以及这些话题适用的工具包括:

为保护敏感系统资源防止修改或披露给未经授权的实体,Windows NT始终提供了丰富的访问控制模型。在这个模型中,用户账户通常可获得管理权利或用户权利。管理员可以完整不受限制地访问计算机以及所包含的全部资源,而用户则会受到限制而无法更改操作系统配置,也无法访问属于其他用户的数据。然而由于一些历史原因,直到最近,Windows计算机上的最终用户依然会经常获得管理访问权利,因此很多用户并不清楚这两种权利之间存在差别(时至今日,就算Windows 10计算机上创建的第一个本地用户账户依然是Administrators组的成员)。

注意

 

就算没有明确包含在Administrators组中,如果能够配置或控制在更高权限上下文中运行的软件,那么用户依然等同于对计算机有了管理控制权。例如允许用户控制被管理员或服务使用的系统级文件或注册表位置(类似于Windows Vista之前系统中的Power Users组);为用户提供等价于管理员的特权,如调试、获取所有权、还原,或加载驱动等特权;或启用Windows Installer的AlwaysInstallElevated策略,让任何用户运行的任何MSI文件都使用System账户运行。

过去多年来,希望提高安全性并降低风险的组织都已开始将最终用户全面转换为“非管理员”模式。随着Windows Vista中开始引入用户账户控制(UAC),包括Administrators组成员在内的用户运行的大部分程序都在以普通用户的权利运行,不再使用管理权利。然而有时候又必须使用管理员权利运行某些程序。

很多Sysinternals工具需要具备管理权利,但大部分工具在用户权利下也可以正常使用所有功能。同时还有一些工具可以在标准用户权利下正常运行,但某些功能需要具备管理权利,因此其在使用标准用户权利时会运行在一种部分降级模式下。

如果使用Administrators组成员账户(对于未加入域的计算机,默认情况下只有创建的第一个账户属于Administrators组成员),Backup Operators等高特权组成员账户,或分配了“管理员等价”特权的账户登录运行Windows Vista或更新版系统的计算机,则本地安全机构(LSA)会为该用户创建两个登录会话,每个会话具备一个不同的访问令牌(本书第9章中介绍的LogonSessions工具可以枚举这些会话)。其中一个令牌代表用户的完整权利,以及所有组关系和特权;另一个是经过筛选的令牌,基本上等价于标准用户的权利,其中会禁用所有高特权组并删除高级特权。系统会使用这个筛选后的令牌创建该用户的初始进程,例如Userinit.exe和Explorer.exe,同时该令牌会被所有子进程继承。使用用户的完整令牌启动进程需要首先进行UAC提升,这一过程是由应用程序信息(Appinfo)服务进行协调的。虽然系统中依然提供了Runas.exe命令,但无法调用Appinfo服务,因此其效果与Windows XP中有所不同。如果使用Runas.exe启动一个程序并指定了管理账户,则目标程序将在该账户的“标准用户”版本下运行[3]

可通过下列任何一种方式对新进程触发UAC提升。

如果已经使用管理令牌运行了父进程,子进程会直接从父进程继承该令牌,无需进行UAC提升。按照惯例,需要管理权利的控制台工具(例如Sysinternals LogonSessions)无需UAC提升,但用户必须从提升后的命令行窗口或Windows PowerShell控制台中运行这样的工具。

一旦触发后,UAC提升的过程可通过3种方式完成。

请注意,可以通过安全策略禁用标准用户的UAC提升。在配置该策略后,用户需要提升时将收到错误信息。

禁用用户账户控制后,Windows会恢复为类似Windows XP的运行模式。此时LSA不再创建筛选的令牌,Administrators组成员运行的程序将始终具备管理权利。此外系统将不再显示提升提示,但可以通过Runas.exe以管理权利启动程序。这里需要注意的是,禁用UAC的同时会禁用Internet Explorer保护模式,此时Internet Explorer将使用已登录用户的完整权利运行。禁用UAC还会关闭文件和注册表虚拟化,这个功能使得很多在Windows XP上要求具备管理权利的应用程序能够使用标准用户权利运行。对于Windows 8以及更新的系统,禁用UAC后将无法运行“商店”应用[5]

图2-1 Windows 7“要求得到同意”的提升

图2-2 Windows 7“要求提供凭据”的提升

虽然表面上看程序和进程非常类似,但其实它们有着本质不同。程序是一种静态的指令序列,而进程则是执行程序所需资源所在的容器。从最高的抽象程度来看,一个Windows进程可以包含下列内容。

每个进程还保存了父进程的PID记录,然而如果父进程退出,这些信息并不能更新,因此进程有可能引用已不存在的父进程,或引用被分配了原始父进程PID的另一个进程。不过进程记录父进程的PID只是为了参考。

Windows为这种进程模型提供了一个名为“作业”的扩展。作业对象的主要职责是让一组进程能够作为整体进行统一管理和操作。例如可以使用作业批量终止一组进程,而无须一次终止一个,同时这种做法中发出调用的进程无需知道组中包含了哪些进程。作业对象还可用于对某些属性进行控制,或对进程以及作业相关联的其他进程进行限制。例如作业可以在每处理器或作业范围内,针对用户模式的运行时间和已提交的虚拟内存强制执行限制。Windows Management Instrumentation(WMI)会将自己的提供程序载入到一个由作业控制的单独的主机进程中,借此对内存的消耗和同一时间可运行的WMI提供程序主机进程的总数进行限制。

如上文所述,进程只是一种容器。从技术上来说,实际运行的并非进程而是线程。线程是进程内部Windows安排执行的实体,其中包含下列基本组件。

虽然线程会有自己的执行上下文,但(除了属于该进程的其他资源)进程中的每个线程会共享该进程的虚拟地址空间,这意味着进程中一个线程使用的数据结构无法确保其不被同一进程中的其他线程读取或修改。然而线程无法引用其他进程的地址空间,除非其他进程将自己的部分专用地址空间设置为共享内存部分(在Windows API中这叫做文件映射对象),或除非一个进程有权打开另一个进程以使用跨进程内存功能。

默认情况下线程没有自己的访问令牌,但需要时可以获取令牌,这样每个线程即可在不影响进程中其他线程的前提下模拟不同的安全上下文,包括模拟远程Windows系统中运行的进程。

为了防止用户应用程序访问或修改重要的操作系统数据,Windows使用了两种处理器访问模式:用户模式和内核模式。System进程之外的其他所有进程都运行在用户模式下(即Intel x86和x64体系结构的Ring 3),而设备驱动和操作系统组件,如执行体(Executive)和内核只能运行在内核模式下。内核模式代表处理器的一种执行模式(x86和x64架构下的Ring 0),可用于访问所有系统内存和CPU指令。通过为底层操作系统软件提供高于用户模式进程的特权,进程可为操作系统的设计者提供必要的基础,确保执行恶意行为的应用程序无法影响系统整体的稳定性。

注意

 

不要将用户模式和内核模式之间的差别与用户权利和管理权利的差别混淆。这里的“用户模式”并不意味着“只具备标准的用户特权”。

虽然每个Windows进程有自己的私有内存空间,但内核模式的操作系统和设备驱动代码将共享同一个虚拟地址空间,该空间也包含在每个进程的地址空间中。操作系统会用处理器读写页面时必须所处的访问模式为每个虚拟内存页面添加标记。系统空间中的页面只能从内核模式访问,用户地址空间的所有页面均可从用户模式访问。

用户模式进程的线程可在调用系统服务时从用户模式切换为内核模式。例如对Windows ReadFile API的调用最终将调用Windows中实际负责处理从文件中读取数据操作的内部例程(Routine)。由于该例程将访问内部系统数据结构,因此必须运行在内核模式下。从用户模式到内核模式的转换是使用一个特殊的处理器指令实现的,该指令会让处理器切换至内核模式的系统服务调度函数。操作系统会执行相应的内部函数,对于ReadFile需要执行的是NtReadFile内核函数。内核服务函数会验证参数并使用安全引用监视器(Security Reference Monitor)执行相应的访问检查,随后才执行所请求的操作。函数执行完成后,操作系统会将处理器重新切换为用户模式。

因此用户模式进程的线程在执行过程中部分时间处于用户模式下,部分时间处于内核模式下,这是一种正常情况。实际上因为大部分图形和窗口系统也运行在内核模式下,承载图形密集型应用程序的进程可能大部分时间都处于内核模式而非用户模式。我们可以在Process Explorer的CPU用量图表中看到这两种模式:图表中的红色部分代表处于内核模式的时间,绿色部分代表处于用户模式的时间。

内核模式的Windows系统核心是通过Ntoskrnl.exe实现的,其中包含各种子系统,例如内存管理器、进程管理器、I/O管理器以及配置管理器(注册表),这些都属于执行体的一部分。这些子系统中的每一个都需要通过对象管理器定义一个或多个类型(Type),以代表暴露给应用程序的资源。例如配置管理器定义的Key对象可代表打开的注册表键;内存管理器定义的Section对象可代表共享内存;执行体可定义Semaphore、Mutant(互斥(Mutex)的内部名称,可用于互相排斥)以及Event同步对象(这种对象可对操作系统内核子系统定义的基本数据结构进行封装);I/O管理器定义的File对象代表打开的设备驱动资源实例以及文件系统文件;进程管理器可创建Thread和Process对象。每一版Windows都会引入新的对象类型,Windows 7共定义了42个,Windows 8.1定义了46个,Windows 10定义了53个对象类型。若要查看特定版本Windows定义的所有对象类型,可用管理权利运行(第15章中介绍的)WinObj工具,并在Object Manager名称空间中进入ObjectTypes目录。

当应用程序需要使用上述某类资源时,必须首先调用相应的API以创建或打开该资源。例如CreateFile函数可以打开或创建文件,RegOpenKeyEx函数可以打开注册表键,CreateSemaphoreEx函数可以打开或创建信号灯。如果函数操作成功,Windows会在进程的句柄表中为该对象分配一个引用,句柄表由执行体负责维持,并会将新增句柄表项的索引返回给应用程序。

应用程序将使用该句柄值针对资源执行后续操作。为了查询或操作资源,应用程序会将句柄值传递给API函数,例如ReadFile、SetEvent、SetThreadPriority以及MapViewOfFile。通过为句柄表创建索引,系统可以查找句柄引用的对象,并定位相应句柄项,句柄项中包含了到对象的指针。句柄项还存储了进程在打开对象的时刻所具备的访问权,这样即可确保不会让进程针对对象执行无权限的操作。举例来说,如果进程成功打开了一个文件并进行读取访问,但尝试使用该句柄写入文件,则此时函数将失败。

当进程不再需要访问某个对象时,即可释放到该对象的句柄,此时通常会将句柄值传递给CloseHandle API(请注意,某些资源管理器需要使用不同API释放资源)。当进程退出时,所有依然在处理的句柄都将关闭。

在Windows Vista之前的Windows系统中,以特定用户身份运行的任何进程可以全面控制以同一个用户身份运行的其他所有进程。Windows Vista引入了一种名为强制完整性控制(MIC)的机制,可根据相对可信度将用户的不同进程区别对待。除了保护提升后的进程,MIC还提供了Internet Explorer、Microsoft Office、Google Chrome,以及Adobe Reader等程序所用的“沙箱”技术的底层基础。

进程的分配和运行需要在某一完整性级别(IL)下进行,完整性级别是一个代表进程可信度的数值。提升后的应用会在高完整性下运行,普通的用户应用在中等完整性下运行,保护模式下的Internet Explorer等低权利进程在低完整性下运行。相应地,每个对象的安全描述符都包含一个完整性标签,其中包含了完整性级别和策略。策略定义了是否允许或拒绝来自完整性更低的进程的“读取”“写入”或“执行”访问请求。如果某个对象不包含该标签,则被视为默认的中等完整性,不允许从完整性更低的进程执行“写入”操作。Windows会为所有进程对象分配一条策略,禁止来自任何完整性更低的进程发起的“读取”和“写入”请求。这样可以保护完整性更高的进程的内存空间不被低完整性进程查看或修改。

若要查看每个进程的完整性级别,可使用本书第3章介绍的Process Explorer,若要查看对象的完整性标签,可以使用本书第9章介绍的AccessChk。

MIC,尤其是低完整性的沙箱无疑可以保护用户防范很多来自互联网的攻击,但这种技术也有局限。尤其是“完整性”是一维的。运行在某一完整性级别下的进程,在面对相同或更高完整性级别的其他进程时无法获得保护。换句话说,在进程A面对进程B可获得保护的同时,进程B面对进程A无法获得保护。

微软在Windows 8中提供了一种全新的应用程序模型,这种模型彻底改变了应用程序安全性的处理方式。该模型的目标在于保护用户的数据和隐私,保护企业网络,进一步保护系统完整性,让应用通过一种受控的方式获得完成工作所需的特权。为了实现这些目标,需要在应用程序之间进行保护,这就必须通过强大的应用程序标识和容器机制对应用程序访问系统资源的能力进行限制,同时保护应用程序自己的资源不被其他应用程序访问。这种全新的机制必须足够轻巧,因为用户有可能同时运行成百上千个应用程序。这种想法催生了应用容器这一概念。

应用容器是对Windows安全模型的一种扩展,可以将某一应用相关联的所有进程作为整体进行保护。每个应用会包含绝对唯一的标识,应用的标识会被纳入使用一种全新安全标识符(SID)创建的访问令牌。当一个应用容器内的一个进程请求访问资源时,Windows安全访问检查机制会应用比传统非应用容器进程更严格的规则,只有在资源明确允许访问的情况下才允许访问。

为了对应用添加标识,这种应用模型引入了一种名为AppX的全新打包机制,可将应用的所有资产封装为一个包,并通过发行商的证书进行数字签名。应用的标识可包含应用发行商设置的应用名称,后跟一个下划线,以及发行商标识的哈希。例如Microsoft Office OneNote的标识是Microsoft.Office. OneNote_8wekyb3d8bbwe。借此便可将程序包的标识与发行商的代码签名证书紧密捆绑在一起。Windows使用这样的标识控制对系统中资源的访问。此外Windows会在一种名为应用容器(App Container)的容器中运行该应用相关的进程。

应用容器可包含下列内容。

Process Explorer可以通过进程属性对话框的安全选项卡显示运行中应用的应用容器和功能SID。在图2-3所示的界面中可以看到,Microsoft Office OneNote有一个应用容器SID和6个功能SID。

图2-3 应用容器中运行的Microsoft Office OneNote所具备的安全上下文

功能

应用容器内运行的应用对系统的访问极为有限。这种应用处于前端时可以接受输入,可以在屏幕上绘制像素,可以将数据存储在自己的私有数据存储中,除此之外几乎什么都不能做。为了提供更多功能,应用必须能对系统进行更广泛的访问,例如确定用户位置或将文档存储到用户的“文档”文件夹。但大部分应用只需要访问计算机上的部分功能。例如一个简单的秒表应用,就没必要使用计算机的摄像头或与家庭/工作网络上的其他计算机通信。应用模型通过两种方式让应用可以对系统进行更广泛的访问:功能(Capability)和代理(Broker)。

应用模型定义了应用可能需要的多个功能,例如互联网客户端、定位、摄像头。应用需要在自己的AppX包中通过清单文件声明自己需要的功能,这样用户在安装应用前就可以知道这个应用需要访问哪些功能。应用运行过程中,这些功能是通过进程令牌以功能SID的方式代表的。例如除非访问令牌中包含与麦克风有关的功能SID,否则应用容器内运行的应用将无法访问计算机的麦克风。诸如定位等敏感功能不仅要求在清单中声明,同时当首次运行该应用,并且应用尝试访问这样的功能时,还会通过交互式的方法要求用户进行确认。

一些功能是由众所周知的SID代表的,并能通过(本书第7章中介绍的)PsGetSid直接转换为人工易读的名称,但其他很多功能SID无法使用公开提供的接口进行转换。例如在图2-3中,令牌中有四个功能SID已经转换为易读的名称,但另外两个无法转换。访问软件和硬件证书或智能卡的功能通常由SID S-1-15-3-9代表。在上述截图中,最后一个功能SID(以“9977”结尾)对应了摄像头功能。

应用可以使用代理作为声明所需功能的备选方法。代理是一种在应用容器之外运行的进程,通常运行在中等完整性级别下。应用可以调用Windows运行时(WinRT)API以通过代理请求访问受保护的资源,代理将决定是否允许访问并代表应用执行访问。代理决定是否允许访问的最常用方法是使用Authentic User Gesture(AUG)。例如应用可以调用WinRT API以向用户显示File Open选择器,借此让用户选择文件。因为该用户界面运行在应用容器之外,并处于更高完整性级别,应用无法修改其中的内容。如果用户选择了文件,代理会打开文件并将其返回给应用,随后应用即可访问该文件。这种访问的实现并不需要更改文件权限(更改权限会导致文件永远能被访问),而是在应用的进程中为代理打开的文件句柄创建副本。应用关闭这个对象句柄后,除非再次通过代理,否则将无法重新访问这个对象。

应用容器资源

大部分应用需要保存状态和用到的其他数据。因此Windows会在文件系统中为每个应用容器分配专用的目录结构,并分配一个只在应用运行时加载的注册表根键和一个单独的对象管理器名称空间。这些内容配置的权限使得应用容器能够恰当地访问所需内容,且无法访问其他所有应用容器。

Windows会在%LOCALAPPDATA%\Packages下为每个应用容器创建每用户目录结构。例如OneNote的AppData目录位于%LOCALAPPDATA%\Packages\Microsoft.Office.One Note_8wekyb3d8bbwe。图2-4显示了允许OneNote的应用容器SID、用户、Administrators以及System账户访问的容器子目录。其他子目录则包含了该应用的Web缓存、本地状态以及漫游配置。

图2-4 为OneNote的应用容器提供的目录安全描述符为用户和应用容器提供了完整控制权限

AppData目录的Settings子目录包含一个Settings.dat文件,这是该应用的私有注册表根键。图2-5显示了OneNote加载该根键并访问其中所存储注册表数据的过程。这些私有根键的根键名称为\REGISTRY\A{guid},其中GUID是在每次加载根键时动态生成的。下一次启动应用时,注册表根键将使用不同的名称加载。

图2-5 OneNote加载并使用存储在应用容器目录结构中的注册表根键

在对象管理器中,应用容器还有自己专用的Named Objects容器。该容器会在应用启动时创建,并仅在应用运行过程中存在。与其他应用容器资源类似,该容器的权限使得应用容器能够进行必要的访问且无法访问其他应用容器进程。当应用创建诸如互斥等对象时,会创建到自己的Named Objects容器中。借此可防范蹲点(Squatting)攻击,这种攻击中一个进程会使用通常属于其他进程的名称创建对象,意在模拟其他进程进而窃取信息或攻击调用方。

图2-6显示了OneNote的Named Objects容器。如图所示,容器路径为\Sessions\n\App ContainerNamedObjects\SID,其中n是远程桌面服务的会话ID[6],SID为应用容器SID。

图2-6 远程桌面服务会话1中OneNote应用容器的私有对象名称空间

应用容器的访问检查

当应用容器内的进程请求访问一个对象时,除了“传统”非应用容器访问检查序列[7]之外,Windows安全引用监视器还会执行一组稍作修改的检查。不仅调用方必须通过强制完整性检查和酌情进行的访问检查,资源也必须显式允许调用方令牌中的应用容器SID、调用方令牌中的一个或多个功能SID,或所有应用容器访问。就算资源允许Everyone访问,或资源的DACL为空,如果对象的DACL没有同时对上述至少一种内容提供显式访问许可,则访问请求依然会被拒绝。如果调用方未能通过强制完整性检查和“传统的”酌情访问检查,访问一样会被拒绝并且不再执行额外的检查(应用容器的强制完整性检查放宽了一个规则:尽管应用容器在低完整性级别下运行,但依然可以获准访问包含中等完整性标签的对象)。

图2-7 AccessChk显示所有应用容器对Ntdll.dll具备“读取”访问的权限

很多系统级的资源需要允许所有应用容器访问。例如每个进程需要能加载Ntdll.dll。Windows定义了一个全新的常用SID:S-1-15-2-1,该SID代表“APPLICATION PACKAGE AUTHO RITY\ALLAPPLICATION PACKAGES”。图2-7显示了Ntdll.dll允许所有应用容器执行“读取”访问,此外Users、Administrators以及System也可以读取访问。这样应用容器内的进程就可以加载Ntdll.dll,但前提是进程以Users或Administrators成员,以及System或Trusted Installer账户的身份运行。

按照设计,强制完整性控制主要是为了保护应用和用户数据防范低可信度应用的威胁。应用容器按照设计是为了在沙箱应用之间提供保护。这两项机制在设计上均不是为了保护用户进程或数据防范通常以中等完整性级别运行的交互式用户桌面进程。受保护进程按照设计提供了一种截然不同的用途:通过创建壁垒保护进程防范其他用户进程和管理员。

受保护进程最早出现在Windows Vista中。最开始该机制唯一的用途在于,通过对负责处理内容的进程(如Audiodg.exe)可执行的操作进行限制,增加对有版权内容(如高质量音视频媒体内容)进行盗版的技术难度。Windows 8.1大幅增强并完善了受保护进程这一技术。现在该技术的主要目的为保护关键系统进程,例如反恶意软件进程或管理用户凭据等敏感信息的进程。

通常来说,任何具备Debug Programs特权的进程都可以请求对其他任何进程进行任何访问,哪怕目标进程的安全描述符并不允许所请求的访问。例如,调用方可以读取或修改目标进程的内存,注入代码,挂起并恢复线程,并可终止进程[8]。获得管理权利的敌人可以轻松地破坏反恶意软件系统,使用通过Lsass.exe盗取的凭据开展“哈希传递(Pass the Hash)”攻击[9]。受保护的进程改变了这样的访问规则,就算System账户和其他管理员也无法对这些敏感进程执行几乎任何控制或访问。

Windows会根据进程映像文件中的特殊数字签名将某些进程指定为受保护的。一些进程将始终受到保护,例如System进程、Smss.exe、Wininit.exe以及Services.exe。通过确保每个受保护进程的所有祖先(Ancestor)进程同样获得保护,Windows为这种保护创建了信任链。如果映像文件包含特殊签名,则通过配置设置也可以对其他进程,例如Lsass.exe以及反恶意软件进程等其他服务提供这样的保护。

当调用方试图访问被Windows保护的进程时,除非调用方本身也是受保护进程且具备更高保护级别,否则Windows内核最多只能允许少量受限制的权利,调用方无法通过这些权利读写内存或向进程中注入代码。类似的限制也适用于访问受保护进程的线程时发起的请求。此外进程将只加载包含特殊签名的DLL,这样不可信的代码就无法在进程中执行。该技术还可以防止应用程序兼容性Shim引擎将Shim DLL载入进程。

Windows定义了多种类型的受保护进程:

上述每一类进程应用了不同的代码签名限制,包括哪些签名者有权为进程映像文件签名,哪些签名者有权为DLL签名,以及签名所需的哈希算法。每一类进程还会对所允许的访问权利强制应用略有差异的限制。举例来说,假设某进程应用了PsProtectedSigner Authenticode保护,可以为调用方提供PROCESS_TERMINATE权利,但使用PsProtected SignerAntimalware保护的进程无法提供这种权利。

每类保护可被标记为“受保护进程”或“受保护进程轻型(Protected process light)”。相比非轻型,“轻型”变体的保护级别略低,主要用在当一个受保护进程试图访问另一个受保护进程时。我们可以使用本书第3章介绍的Process Explorer工具查看哪些进程受到了保护以及具体的保护类型。

有关受保护进程的详细信息请参阅《Windows Internals》(第6版)合著者Alex Ionescu的下列博客文章:

http://www.alex-ionescu.com/?p=97

http://www.alex-ionescu.com/?p=116

http://www.alex-ionescu.com/?p=146

http://www.nosuchcon.org/talks/2014/D3_05_Alex_ionescu_Breaking_protected_processes.pdf

包括Process Explorer、Process Monitor,以及VMMap在内的很多Sysinternals工具会在特定操作中显示所执行代码路径的详细信息,这种信息也叫做调用栈(Call stack)。通过将符号(Symbol)与进程地址空间内的模块结合在一起,可以针对代码路径,尤其是Windows操作系统中的代码获得更有意义的上下文信息。了解调用栈和符号,以及在Sysinternals工具中配置这些内容的方法,将能帮助我们针对进程行为获得更深入的见解,进而更准确地判断各种问题的根源。

进程中的可执行代码通常会被组织为一系列离散函数的集合。为了执行自己的任务,一个函数可以调用另一个函数(子函数)。运行完毕的函数会将控制权交回给调用自己的函数。

图2-8是为了演示这一过程虚构的例子。MyApp.exe中包含一个名为HelperFunctions.dll的DLL,该DLL中包含一个名为EncryptThisText的函数,可对传递过来的文本进行加密。

图2-8 函数调用序列范例

在执行完一定的前序操作后,EncryptThisText调用Crypt32.dll中的Windows API Crypt EncryptMessage。某些时候CryptEncryptMessage需要分配一些内存并调用Msvcrt.dll中的内存分配函数malloc。当malloc完成自己的工作分配了所请求的内存后,执行过程会从CryptEncryptMessage停止的位置恢复。当CryptEncryptMessage完成自己的任务后,控制权会交回给EncryptThisText调用CryptEncryptMessage的位置。

调用栈是一种可以让系统知道如何将控制权返回给一系列调用方,在函数之间传递参数,以及存储本地函数变量的构造。该构造遵循了“后进先出(Last in, first out)”的原则,按照与加入时完全相反的顺序移除项。当一个函数即将调用子函数时,会将从子函数返回后下一个待执行指令的内存地址(即“返回地址”)置于栈最顶层。当子函数调用另一个函数时,会将自己的返回地址添加至栈。在从函数返回时,系统会获取位于栈最顶层的任何地址,并开始从这个位置执行代码。

按照惯例,调用栈中返回地址将显示为module!function+offset的形式,其中module是包含该函数的可执行映像文件名称,offset是从函数开始位置经过的字节数(以十六进制形式表示)。如果函数名不可用,地址将直接显示为“module+offset”。在上文虚构的例子中执行的malloc,其调用栈应该是这样的:

msvcrt!malloc+0x2a
crypt32!CryptEncryptMessage+0x9f
HelperFunctions!EncryptThisText+0x43
MyApp.exe+0x25d8

如上所示,调用栈不仅可以告诉我们所执行的代码,而且可以告诉我们程序是如何运行到这一位置的。

检查线程在调用栈中的开始地址或返回地址时,通过检查已加载模块列表及其地址范围,调试器可以很轻松地知道线程所属的模块。然而在用编译器将开发者的源代码转换为计算机指令时,并不能保留原始函数名,不过有一个例外,包含导出表的DLL可以列出函数的名称和偏移量并供其他模块使用。然而导出表无法包含库的内部函数名,也无法包含按照设计需要在运行时发现的COM入口点名称。

注意

 

载入用户模式进程的可执行文件通常可能是可由新进程启动的EXE文件,或可载入现有进程的DLL文件。然而EXE和DLL文件并非只能使用这两种文件扩展名。使用COM或SCR扩展的通常也是EXE文件,使用ACM、AX、CPL、DRV以及OCX扩展的通常也是DLL文件。安装程序通常会提取并运行使用TMP扩展的EXE文件。

在创建可执行文件时,编译器和链接器也可以创建相应的符号文件(默认扩展名为PDB)。符号文件包含的各种数据,例如模块中函数的名称和入口点偏移量,这些并非运行可执行代码所必须的,但其能在调试过程中提供极大的帮助。借助这些信息,调试器可以接受各种内存地址并轻松地确定前序地址最接近的函数。如果没有符号,调试器将只能使用导出的函数(如果存在的话),但这些函数可能与所执行的代码没有任何关系。一般来说,返回地址的偏移量越大,所报告函数名称的准确性就越低。

注意

 

在报告调用栈时,Sysinternals工具只能使用原生(非托管)符号文件,无法报告JIT编译的.NET程序集中的函数名。

符号文件必须与相应的可执行文件同时生成,否则内容将不够准确,调试引擎可能会拒绝使用。使用老版本Microsoft Visual C++创建的符号文件只能用于Debug构建,除非开发者明确更改构建配置。新版本现在已经可以为Release构建创建符号文件,并可将符号文件写入可执行文件所在目录。Microsoft Visual Basic 6也可以创建符号文件,但默认无法执行该操作。

符号文件可以包含不同级别的细节信息。完整符号文件(有时候也叫做私有符号文件)通常包含公开符号文件不具备的细节,例如所定义符号在原文件中的路径和行数,函数参数名和类型,以及变量名和类型。对外发布符号文件的软件公司通常发布的只是公开的符号文件,完整符号文件一般只供公司内部使用。

Windows调试工具可以根据需要从符号服务器(Symbol server)下载恰当的符号文件。这些服务器可以存储特定可执行文件多个不同构建对应的符号文件,调试工具会下载与所调试映像相匹配的符号文件(调试工具会使用每个可执行文件的文件头中存储的时间戳和校验信息作为唯一标识符)。

微软提供了可以通过网络访问的符号服务器,并通过该服务器免费提供了适用于Windows的公开符号文件。通过安装Windows调试工具并配置Sysinternals工具使用微软的符号服务器,即可轻松地看到我们的进程所调用的Windows函数。

图2-9显示了Process Monitor捕获的一个事件的调用栈。栈中显示的MSVBVM60.DLL(帧15以及17~21)意味着这是一个Visual Basic 6程序,因为MSVBVM60.DLL是Visual Basic 6的运行时DLL。MSVBVM60帧较大的偏移量意味着该模块的符号不可用,因此这里显示的名称可能并非实际调用函数的名称。帧14显示了在主执行文件(LuaBugs_VB6.exe)中调用了一个名为Form1::cmdCreate_Click的函数。这个帧还显示了源文件路径,意味着这个第三方模块具备完整的符号信息。随后该函数调用了Wshom.ocx中的CWshShell::RegWrite(帧13),意味着这个Visual Basic 6程序使用了一个Windows Script Host ActiveX写入注册表。CWshShell::Reg Write调用了同一模块中的一个内部函数(帧12),随后调用了Kernel32.dll中公开的Reg CreateKeyExA Windows API(帧11)。执行过程通过Kernel32内部函数(帧8~10)传递给Ntdll.dll中的ZwCreateKey原生API(帧7)。至此所有这些函数都在用户模式下执行,这一点可以通过帧列中显示的“U”图标确定,但是从帧6开始程序切换至内核模式,这里显示了“K”图标。内核函数(帧0~6)两个字母的前缀代表函数所属的执行组件,例如“Cm”代表负责注册表的配置管理器(Configuration Manager),“Ob”代表对象管理器(Object Manager)。这个栈跟踪是在处理CmpCallCallBacks(帧0)时捕获的。请注意帧0~13显示的符号信息全部来自Process Monitor按需从微软符号服务器下载的Windows公开符号。

图2-9 Process Monitor调用栈以及来自符号文件的信息

使用符号的Sysinternals工具需要两个信息,如图2-10所示:要使用的Dbghelp.dll位置,以及符号路径。使用完整符号信息显示源文件的Sysinternals工具还需要配置源代码路径。

图2-10 Process Explorer的配置符号对话框

Dbghelp.dll是微软的调试引擎DLL之一,提供了处理调用栈、加载符号文件以及将进程内存地址解析为名称所需的功能。仅Windows调试工具中包含的Dbghelp.dll版本可以支持从符号服务器下载文件。Windows中自带的,位于%SystemRoot%\ System32目录下的Dbghelp.dll文件只能使用本地存储的符号文件。在首次运行时,Sysinternals工具会检测调试工具的默认安装位置,并使用在这个位置找到的Dbghelp.dll,如果没找到则会使用位于%SystemRoot%\System32的默认版本。

Windows调试工具可从http://www.microsoft.com/whdc/devtools/debugging/default.mspx下载。我们可以下载独立版本的调试工具安装程序,或通过Windows SDK安装。为了获得该调试工具,必须运行SDK安装程序,并选择所需的调试工具选项。对于再发行版的调试工具,可以分别针对x86、x64,以及IA64体系结构下载独立版的调试工具。通过再发行版安装程序可以很方便地在没有安装完整SDK的计算机上安装调试器。

符号路径可以告诉调试引擎,如果没有在默认位置找到符号文件,该去哪里寻找这些文件。调试引擎首先会在可执行文件的目录以及符号文件最初的创建位置(如果可执行文件包含这些信息的话)这两个默认位置查找,如果没找到则会检查我们指定的符号路径。

符号路径可以包含文件系统路径和符号服务器位置。首次运行时Sysinternals工具会将自己的符号路径设置为_NT_SYMBOL_PATH环境变量的值。如果未定义该变量,工具会将自己的符号路径设置为srv*https://msdl.microsoft.com/download/symbols,这样即可使用微软公开的符号服务器,但不会将下载的符号文件保存在本地缓存中。

文件系统目录和符号服务器位置可同时包含在符号路径中,并使用分号进行分隔。工具将按照在路径中出现的顺序依次搜索每个路径。上文曾经提过,符号服务器位置使用了srvDownstreamStoreSymbolServer这样的形式,例如对于下面这样的符号路径:

C:\MySyms;srv*C:\MSSymbols*https://msdl.microsoft.com/download/symbols

调试引擎会首先搜索默认位置,随后搜索C:\MySyms,通常建议将我们自己应用程序的私有符号文件保存在这里。如果都没找到所需符号文件,引擎会搜索C:\MSSymbols,如果依然没找到,最后将查询符号服务器。如果符号服务器上提供了所需文件,调试引擎会将其下载至C:\MSSymbols。

有关符号路径、符号服务器、源代码路径以及调试引擎所用环境变量的详细信息请参阅调试工具的文档。

 

窍门 如果只需要微软提供的公开符号,可将符号路径设置为: srvc:\symbolshttps://msdl.microsoft.com/download/symbols 这样调试引擎就可以优先搜索C:\Symbols下的缓存,并在需要时从微软的公开符号服务器下载符号文件,下载的内容可保存在缓存中,下次使用无需重新下载。如果目录不存在,调试引擎会自动创建C:\Symbols。

Process Explorer、Process Monitor、PsExec、AdInsight、Desktops以及LogonSessions等Sysinternals工具的描述中都提到了会话、会话ID、控制台会话、会话0、交互式和非交互式窗口站(Window station)以及“同一桌面”上运行的其他程序。虽然这些概念并不那么广为人知,但对Windows平台各种问题的解决非常关键。

先来概括看看图2-11所示的层次结构,随后本节将定义并解释这些内容。最外层是远程桌面服务(RDS)会话,也叫做终端服务(TS)会话。每个对话包含一个或多个窗口站,窗口站中包含了桌面。这些安全对象每个都分配了专用的资源,同时这些桌面与LSA创建的登录会话之间存在松散的关系。虽然很多有关Windows的文档并未清晰界定LSA登录会话和RDS会话之间的差别,但它们实际上是截然不同的实体。

图2-11 会话、窗口站以及桌面之间的关系

远程桌面服务可以让一台计算机支持多个交互式用户会话。该技术最早出现在Windows NT 4.0 Terminal Server Edition中,但直到Windows XP开始才包含在Windows客户端操作系统内。该技术支持的功能包括快速用户切换、远程桌面、远程协助、远程应用程序本地集成(RAIL,即RemoteApps)以及虚拟机集成功能。Windows客户端系统(Windows XP、Windows Vista、Windows 7、Windows 8.x以及Windows 10)中的这个技术有个重要局限,即同一时间只允许使用一个交互式会话。也就是说,在同时打开的多个已断开会话中,进程依然可以继续运行,但只有一个会话可以更新显示设备上显示的内容并处理键盘和鼠标的输入操作。此外这个局限还进一步体现在:加入域的Windows XP计算机最多只能支持一个交互式会话。举例来说,如果用户登录到控制台,你可以使用同一个账户通过远程桌面登录到该计算机并继续运行该会话,但除非第一个用户先注销,否则无法使用其他用户账户登录。

远程桌面服务会话可通过一个始于会话0,数值持续增加的会话ID加以识别。为了在会话之间实现隔离,对于编号为1以及大于1的会话,Windows会在对象管理器中为每个会话定义一个全局名称空间,以及一个会话专用的“本地”名称空间。这个全局名称空间承担了会话0中进程的本地名称空间(WinObj可以通过图形化视图显示对象管理器名称空间,本书第15章将详细介绍该功能)。

系统进程和Windows服务始终运行在远程桌面服务会话0中。在Windows XP和Windows Server 2003中,登录到计算机的第一个交互式用户也将使用会话0,因此可以使用与服务相同的本地名称空间。Windows XP和Windows Server 2003只在需要时创建会话1以及后续会话,如果在第二个用户登录前第一个用户已注销,则第二个用户也将使用会话0。因此在加入域的Windows XP系统中只存在会话0。

在Windows Vista以及更新的系统中,服务将运行在会话0中,但出于安全原因所有交互式用户会话都运行在会话1以及后续会话中。这种对用户进程和系统进程进行的进一步分隔机制也叫做会话0隔离。

 

注意 “控制台会话”这个称呼有时会被误解为会话0的同义词。控制台会话是指与本地连接的键盘、显卡以及鼠标相关联的远程桌面服务会话。如果一台计算机上的所有活跃会话都是远程桌面会话,那么控制台会话将保持连接并显示登录界面。在Windows XP/Windows Server 2003上这个会话可能是,也可能不是会话0,但在Windows Vista以及更新的系统中绝对不是会话0。

每个远程桌面服务会话包含一个或多个命名窗口站。窗口站是一种安全对象,其中包含一个剪贴板、一个原子表(Atom table)[10]以及一个或多个桌面。每个进程都需要关联至一个窗口站。在会话内部,仅名为WinSta0的窗口站可以显示用户界面或接收用户输入。在会话1和后续会话中,Windows仅创建一个WinSta0窗口站(如图2-12所示)。在会话0中,除WinSta0之外Windows还会为关联了服务的每个LSA登录会话创建一个单独的窗口站,并将登录会话的本地唯一标识符(LUID)包含在窗口站的名称中。例如以System身份运行的服务进程位于Service-0x0-3e7$窗口站中,以Network Service身份运行的服务进程位于Service-0x0-3e4$窗口站中。这些窗口站无法显示用户界面或接收用户输入。

图2-12 WinObj显示了会话2的私有名称空间中包含的交互式窗口站

PsExec -s cmd.exe可在Service-0x0-3e7$窗口站中运行命令行界面并将其控制台I/O重定向至PsExec。PsExec的-i选项可供我们指定远程桌面服务会话,并在其WinSta0窗口站中运行目标进程。本书第7章将介绍PsExec。

配置为以System身份运行的服务也可以配置为允许服务与桌面交互。这样配置后的服务将在会话0的WinSta0窗口站,而非Service-0x0-3e7$窗口站中运行。如果交互式用户也位于会话0中,那么通过这种方式即可让服务通过界面显示和键盘鼠标等输入操作与最终用户直接进行交互。现在看来这并不是一种好做法,下面将介绍原因。微软也意识到这样做的问题,因此在使用会话0隔离后这种做法完全不可行了(Interactive Services Detection服务,即UI0Detect提供了一种不完整的缓解措施)。

每个窗口站可包含一个或多个桌面。桌面是一种提供了逻辑显示界面的安全对象,应用程序可以用窗口的形式在桌面上渲染自己的界面。

 

注意 此处提到的“桌面”与Windows资源管理器外壳名称空间的桌面抽象没有任何关系。此外Windows 10的多桌面功能无法为这里所讨论的“桌面”类型创建新实例,但Sysinternals Desktops工具可以做到这一点。

多个桌面均可包含UI,但同一时间只能显示一个桌面。交互式窗口站中通常有3个桌面:Default、Screen-saver以及Winlogon。Default桌面是用户应用程序默认运行的桌面(Sysinternals Desktops工具最多可以额外创建3个运行应用程序的桌面,本书第11章将详细介绍该工具)。Screen-saver桌面供Windows在启用密码保护的情况下运行屏幕保护。Winlogon桌面也叫做安全桌面,按下Ctrl+Alt+Del后Windows会将控制权交给这个桌面,此外默认情况下UAC提升对话框也会显示在这个桌面上。Winlogon桌面通过权限保护仅限以System身份运行的程序访问,借此可保护涉及密码输入操作的操作安全。

随着将进程关联给窗口站,进程中的每个线程也会关联给该窗口站内的桌面。虽然一个进程中的特定线程也可关联给不同桌面,但通常都会关联到同一个桌面。

Process Explorer(将在本书第3章介绍)和Process Monitor(将在本书第5章介绍)等多个Sysinternals工具可以识别进程所属的会话ID。虽然没有哪个工具可以直接识别进程相关联的窗口站或桌面,但可通过Process Explorer的Handle视图,通过打开的到窗口站或桌面对象的句柄这种方式了解此类信息。例如在图2-13中,Process Explorer显示了一个以System身份在会话0中运行的进程,该进程打开了到\Default桌面以及\Windows\ WindowStations\Service-0x0-3e7$窗口站的句柄。

图2-13 会话0中的一个进程打开了到桌面和窗口站对象的句柄

与控制台应用程序不同,Windows应用程序是事件驱动的。每个创建有窗口对象的线程包含一个可接收消息的队列。这些GUI线程会等待窗口消息的抵达,随后将处理这些消息。这些消息可以告诉窗口需要做什么或发生了什么。例如可以通过消息告诉窗口“自行重绘”“移动到屏幕坐标(x,y)”“自行关闭”“回车键被按下了”“鼠标右键在坐标(x,y)位置被按下了”或“用户正在注销”。

窗口管理器负责协调窗口消息。消息可从同一桌面下运行的任何线程发送至任何窗口,但窗口管理器不允许程序将窗口消息发送给不同桌面上的窗口。Process Monitor的/Terminate/WaitForIdle命令必须从运行目标Procmon实例的同一个桌面上调用,因为它们需要使用窗口消息告诉现有实例自行关闭,并需要通过这种方式确定目标实例已经准备好以窗口消息的形式处理命令。

窗口消息可用于模拟鼠标或键盘操作。RegJump以及Process Monitor和Autoruns的“跳转到”功能就是通过这种方式在注册表中定位到特定键的。由于物理击键操作和GUI程序收到的窗口消息均是某种级别的抽象,因此实际上目标程序无法绝对区分到底是真正按下了键盘上的按键,或是其他程序通过发送窗口消息的方式模拟了这样的操作(不仅仅是Windows,所有窗口化系统均是如此)。

除了32位Windows系统引入了对多线程的支持外,窗口消息的这种架构甚至可以追溯至Windows 1.0时代,因此其中遗留了很多古老的设计思路。尤其是窗口对象不具备安全描述符或访问控制列表。因此让服务在用户的桌面上显示窗口是一种很糟糕的做法,用户程序将可以向以System身份运行的进程所拥有的窗口发送畸形的或特别构造的消息,若能成功利用这种机制将能直接控制这些进程(这种做法通常也叫做粉碎窗口攻击(Shatter attack))。如果用户还不是管理员,此时将能非常容易地提升自己的特权。这也是交互式用户不再登录到会话0的主要原因。

对于Windows Vista以及更新版系统默认模式下的“标准用户”,可以通过UAC提升让使用管理员权利运行的应用程序与非管理员进程在同一个桌面上运行,因此需要通过额外的保护措施降低针对提升后进程所拥有的窗口进行粉碎窗口攻击的风险,这样的机制叫做用户界面特权隔离(UIPI)。

使用UIPI的情况下,窗口管理器在对窗口消息进行协调时将能更改目标的状态(例如按钮点选消息),窗口管理器会对发送该消息的进程与接收该消息的窗口所属进程的完整性级别(IL)[11]进行对比。如果发送方的IL低于接收方,则UIPI会阻止这样的消息。因此RegJump工具和类似的Jump To功能必须至少与注册表编辑器使用同样高的IL执行。此外如果发送方位于应用容器中,那么UIPI只允许这样的信息发送给同一应用容器内的其他窗口。

有关MIC和UIPI的详细信息请参阅Windows Vista完整性机制技术参考资料:http://msdn.microsoft.com/library/bb625964.aspx。

[1] 在撰写本文时,此书的最新版本是《Windows Internals》(第6版),分为上下两部,作者Mark E. Russinovich、David A. Solomon,以及Alex Ionescu(Microsoft Press,2012年出版)。

[2] 译注:按照微软的官方译法,Stack这个词在很多情况下都译作“堆栈”:https://www.microsoft.com/language/zh- cn/Search.aspx?sString=stack&langID=zh-cn,然而“堆”这个字容易被误理解为“Heap”,因此本书统一将Stack译作“栈”。

[3] 在启用UAC的情况下,这一规则存在一个例外情况。除非启用“用户账户控制:用于内置管理员账户的管理员批准模式”这个安全选项,否则UAC令牌的筛选和“管理员批准模式”将不适用于系统内置的Administrator账户。该账户运行的任何程序始终可以获得完整的管理权利。该安全选项默认并未启用,不过内置的Administrator账户默认处于禁用状态。

[4] 译注:Shim是一种小型函数库,用于透明地拦截API调用,修改传递的参数、自身处理操作、或把操作重定向到其他地方。Shim主要用于解决遗留应用程序在新版Windows系统上的兼容性问题。详细介绍可参考:http://www.freebuf.com/news/48878.html。

[5] 译注:“商店”应用是指在Windows 8以上系统中,通过系统中的应用商店安装的所有“Modern”应用。

[6] 有关会话的详细信息请参阅本章“会话、窗口站、桌面和窗口消息”一节。

[7] 针对非应用容器程序执行的访问检查步骤在《Windows Internals》(第6版)上篇(Microsoft Press,2012年出版)第6章“安全性”中有详细介绍。

[8] Debug Programs无疑是一种强大的特权,只能分配给Administrators。一些安全指南建议就算对Administrators也不要指派该特权。但这个建议有些问题,因为这会干扰到合法的管理任务,同时攻击者其实可以很容易地绕过。

[9] 除非启用了Windows 10的凭据保护(Credential Guard)功能。

[10] 有关原子表的详细信息请参阅:https://msdn.microsoft.com/library/windows/desktop/ms649053(v=vs.85).aspx。

[11] 完整性级别在本章上文“应用程序隔离”一节已进行了介绍。


相关图书

物联网全栈开发原理与实战
物联网全栈开发原理与实战
区块链技术本质与应用
区块链技术本质与应用
网络调研技术与实战
网络调研技术与实战
区块链架构与实现:Cosmos详解
区块链架构与实现:Cosmos详解
TongWeb中间件实用教程
TongWeb中间件实用教程
2020区块链漫游指南
2020区块链漫游指南

相关文章

相关课程