微信扫一扫 分享朋友圈

已有 7713 人浏览分享

开启左侧

Windows内核安全编程 前言

[复制链接]
7713 1
本书是一本专门介绍实时扫描的防毒软件、虚拟磁盘、硬盘还原、硬盘加密、文件系统保护、文件透明加密、防火墙、密码输入保护等软件的Windows内核模块的具体实现方法的编程技术书。本书的目的是使读者能够用C语言编写这些核心模块。  大学的时候,在Windows平台上我最初学的是VB,然后是Delphi。我的感觉是,无论想实现任何功能,都早已有工具的开发者给我们准备了良好的接口和文档,让我们学习和使用都非常的方便。因此觉得自己已经学到了终点。如果仅从"能实现功能"的角度讲,我没有必要再学习了,剩下的事情,只是去很舒适地使用那些接口就可以了。那又何必再学习Windows编程呢?
  工作之后遇到了障碍。我的第一个任务是实现一个网络的虚拟磁盘。我虽然自以为无所不能,但是也找不到在Windows系统里增加一个虚拟磁盘的API在哪里。我每天都在使用虚拟光驱、杀毒软件、防火墙,但是我从未想过它们如何实现。不是因为我懂,而是因为我自以为任何功能的实现一定是简单而舒适的,等需要的时候再去研究,绝不会有什么困难。
  但是实际编码的时候才明白:良好的接口、舒适的编码过程,绝对不是天生之道。天地万物自混沌而起,那些美好的表面,不过是在残酷的现实上重重包裹的包装纸罢了。
  一辆新车的表面自然光彩照人,操作接口也人性而美好。但是一旦需要打开车身去修理内部某根漏油的管子,就没有那么容易和舒适了。造成这种情况,绝不是Windows的底层开发者们天生没有美学观念。那些多年积累和维护着并不断改进的无数行代码,已经是人类工程史上的奇迹了。如今要打开它的外壳去肆意修理,当然不是一件轻松的事情。
  但这正是Windows内核编程的魅力所在。
  只有极少的程序员会需要参与微软的Windows内核开发,也只有极少的读者会自己试图从头开发一个类Windows的操作系统内核(有这方面兴趣的读者,建议参考开源项目ReactOS)。单纯地讲解Windows内核编程对大多数读者都没有意义。但是,信息安全类的软件是内核编程的极好的应用实例。病毒实时监控、防火墙、入侵检测、数据保护还原、数据即时备份、数据加密、数据防止泄密、反外挂等,都不同程度地涉及到内核编程;或者,内核编程可以让它们工作得更好。这些就是本书的内容,因此本书的副标题为"Windows内核安全编程"。"寒江独钓"则表明了这个领域的寒冷与寂寥。
  本书和《天书夜读--从汇编语言到Windows内核编程》的不同之处在于:《天书夜读》一书介绍的是自己调试Windows内核、获取知识、解决问题的技巧。因此《天书夜读》一书介绍的内容大部分是没有文档可循的,容易走火入魔。
  本书则基本上介绍的是正统的内核编程技术,是微软在内核编程中给信息安全软件开发者提供的相关接口的大集合,是名门正派的技术,不沾邪气。一个好的内核程序员,"正邪兼修"是有必要的。
  本书既适合于有志于成为软件程序员的学生使用,也适合于希望加强自己的技术实力的Windows程序员阅读,同时更适合于从事信息安全行业的Windows软件的开发者作为手头参考。
  本书对改善病毒横行的网络现状也有一定益处。虽然无助于劝说那些孜孜不倦的病毒开发者们弃恶从善,但是至少有助于他们提高技术素养,学会更认真地编写程序,以免总是写出导致程序崩溃和系统蓝屏的代码,影响无辜者的正常工作。
  本书假定读者了解C语言,能理解C语言的基本语法,并且学习过操作系统、计算机网络和数据结构的基础知识。一般来说,如果读者听说过"进程"、"文件系统"、"中断"、"TCP协议"、"以太网包"、"链表"、"哈希表"、"加密算法"这些名词,则足够阅读此书了。
  有些读者可能会关心作为一个程序员的就业前景。这也是我非常关心的一个问题。我曾经在杭州的核新软件公司为证券营业部开发防火墙和虚拟磁盘,一共3年的时间;后来在日电卓越软件(北京)的上海分公司开发部信息安全开发课工作了3年。我认识的业界朋友们,大多在赛门铁克、趋势、瑞星、EMC、华赛这样的公司就职。现在是我工作的第7个年头了,我在Intel在上海的紫竹中心参与动态二进制翻译项目。最有价值的是,我参与的每一个项目都让我学习到更多的知识,面对许多前所未有的考验,每一步都让人充满了精神上的成就感。
  本书的读者未来很可能会从事底层编码的工作,而不是一个上层的设计和管理人员。从事底层编码的程序员,常常被同事称为"牛人"。这个牛人不是"牛皮哄哄的人"的意思,而是"像牛一样辛苦工作的人"的意思。想从事这个行业的读者,我抄我的前同事钱铮最喜欢的一首古诗《代牛言》献给您:
  渴饮颍水流,饿喘吴门月。黄金如可种,我力终不竭。
  谭 文
  2009年1月1日
  阅读注意
  如何阅读本书
  请注意,本书基本上不可以跳读。虽然书中的内容是按照应用的领域进行划分,但是并没有采用一种分类介绍所有基础知识,然后分各个领域介绍的模式。而是从简单的应用到复杂的应用依次进行的。
  本书首先最简单地介绍了串口的过滤,然后是键盘的过滤(用于密码保护)。先介绍这些内容是因为它们在驱动中最简单。但是并不是意味着只关心网络过滤的读者,可以跳过它们,直接翻到NDIS中间层驱动的章节进行阅读。
  本书所有的章节内容,采用的都是基于WDK的C语言编程。在编程方法上是统一而且一脉相承的。对于所有的内核API函数的介绍、特殊名词、基础概念的说明,本书都是在具体范例中,第一次出现时做详细的介绍,并举出例子。而以后再出现时,就直接使用而不做介绍了。因此,要对后面介绍的复杂的内核模块的章节能顺利地阅读,必须以前面的简单的章节为基础。
  书中的代码
  书中及附带光盘中的代码,仅供学习与研究使用。这些代码有一部分是笔者所写,有一部分是修改或者直接引用了业内公开的、可供研究使用的代码。这些代码在笔者的测试环境下都可以正常运行。但是笔者并不保证这些代码都有相应的授权可以应用于商业开发中,也不保证这些代码在所有版本的Windows、与其他任何软件并存都能可靠运行。商业级的内核代码需要经过详尽的测试,本书中的示例代码并不具备这个过程。
  读者在运行这些代码时,应该自己使用合理的安全手段(保存未保存的文件、使用虚拟机,或者在运行之前准备硬盘还原映像),以便万一系统损坏时可以恢复。至于具体的操作方法,请读者参考本书第1章"内核上机指导"。笔者对读者因为运行这些代码时发生的意外而导致的损失不负责任。
  如果本书的读者将这些代码应用到商业软件开发中,由此所引发的一切后果(如版权上的侵犯和技术上的问题,以及相应造成的损失),本书的作者都不承担任何责任。
  如果读者发现测试时某个示例程序无法运行,请做以下的事:
  (1)在虚拟机上安装一个干净的Windows XP;不要安装任何其他软件。
  (2)确保虚拟机模拟的是单核的CPU。
  如果程序依然崩溃,请保留dump文件,并用E-mail联系本书的作者。
  阅读前的准备
  读者必须先准备编译和调试环境。内核编程的环境不像应用编程只需要安装一个软件那么简单。具体的方法在本书第1章有详细的介绍。
  随书光盘上并没有提供运行、调试本书示例代码的完整工具集。这是因为有一部分软件的授权要求为"不得拷贝分发",所以需要读者自己在网上下载。但是幸运的是,本书涉及的所有必要工具软件都是免费的,第1章中提供了相应的说明和下载的网址,下载的网址可能有时效性。同时由于工具软件版本的升级,这些说明可能和实际的情况有所不同,读者应该在网上搜索最新的信息。
  关于本书读者所需要的基础知识,笔者认为应该精通C语言(汇编与C++是不必要的,本书只使用C语言编程),至少熟悉Windows下C语言的一种应用编程方式(比如使用过VC或者C++Builder)。如果从事过驱动开发,那是非常好的基础。但是本书尽量面向没有从事过驱动开发的读者。
  操作系统、计算机网络、数据结构与算法的基础知识对于理解本书的内容很有帮助,完全没有学习过这方面知识的读者会难以理解书中的一些细节。
  技术细节的说明
  本书是由实际从业的程序员所写,总体而言,是实践而不是理论之书。所以和一些常见的编程技术类书籍不同,本书对一些具体的技术细节的描述可能不详细,比如对内核函数的参数使用的说明。一般来说,Windows的应用层API函数和内核API函数的参数都非常复杂,详细地说明它们需要较大的篇幅。但是更重要的是,在绝大多数情况下,使用的参数组合仅仅是常见的几种。本书以笔者实际的编程经验,详细介绍在开发中实际使用的参数配置;而对于笔者从未使用或者极少使用的情况,则往往以"笔者也从未使用过"进行说明。因为笔者认为,知道哪些细节有用,远比了解有哪些细节更加重要。所以读者应该理解这一点:本书提到的情况,往往是必须掌握的;而本书未提及的情况,则往往是很不常用的。如果需要用到的细节本书没有提供,大部分都可以在帮助文档中查到。
  与应用编程不同,内核编程(尤其是信息安全软件涉及的内核编程)总有部分技术点没有文档可循,有时虽然有文档,也语焉不详。有些问题,笔者也并没有搞清其原因,但是在实际开发中却是必须解决的,因此很有可能是通过经验解决。为此,书中虽然说"请务必这样做",或者说"笔者是这样做的",但是并不能详尽地说出原因。如果有读者对某个问题有更深入的了解,敬请与笔者联络,以便在重印或再版时加入更明确的说明。
  词汇的翻译
  在这个行业中有太多词汇来源于英文文档,因此如何翻译为中文是一个难题。一般地说,应当沿用业界最常用的翻译方式。但是由于笔者所读过的翻译书籍毕竟有限,不大可能使各个词汇都符合业界最标准的翻译方式。为了稳妥起见,那些重要的、可能引起疑惑的词汇在本书正文第一次出现时,都使用"中文(英文)"的方式。
  有少数词汇是笔者在阅读前人的书籍时,曾经深感疑惑的。为了浅显起见,有意地使用了本人自认为更浅显的翻译方式。最典型的就是"SystemRoutine",所有在WDK中提供的开发者可以调用的函数(类似于SDK中提供的API函数)都称为"SystemRoutine"。笔者见过以前的书中翻译为"系统例程"。既然它就是一个函数,笔者倒是觉得翻译为"内核API"或者"内核函数",对于习惯应用程序编程的读者会更好理解。同理,"DispatchRoutine"也被笔者翻译成了"分发函数"。读者如果认为有不妥或者错误的地方,敬请批评指正,以便在重印或再版时修改。
  驱动开发模型的选择
  WDF是Windows驱动编程模型的发展趋势,但是传统的NT式驱动、WDM模型依然是理解驱动开发的基础。目前,完全抛弃传统是不可能的。一方面,传统的模型编写的驱动程序依然有效,而且有大量现成的例子可以参考;另一方面,WDF虽然已经出来很久了,但是有许多的基础例子找不到WDF的范本。很多无处不用的驱动程序是人类经过多久都不愿意去重新开发的,虽然微软把大部分旧的驱动程序的例子改为了WDF模型,并在WDK中和旧例子一起提供给开发者参考,全面取代WDM的时代依然没有到来。这个过程还有赖于WDF自身的进一步完善。
  如何区分驱动模型?下面是本书第2章中的一段:
  "Windows的模型概念,本来是就驱动程序的行为而言的。比如WDM驱动,必须要满足提供n种被要求的特性(如电源管理、即插即用)才被称为WDM驱动。但是如果不提供这些功能,那么统一称为NT式驱动。
  本书采用简单的区分方法。将一切在Windows2000~WindowsVista下能正常运作且未调用WDF相关的内核API函数的驱动都称为传统型驱动(包括NT式和WDM)。如果调用了WDF相关的内核API则称为WDF驱动。
  从目前笔者的理解来看,WDF的编程方式是对已有的在WDM中广泛使用的内核API函数的一次封装,尤其是对以Io开头的系列函数,包括驱动对象(Drivert)、设备对象(Devicet)、和请求(IRP)相关的API进行了封装,而且旧的API完全可以调用。已经有太多的内核程序依赖于旧的接口,微软在很长一段时间内都不可能要求只能使用WDF编程。
  因此本书采用二者并重的方式。大部分例子用传统型驱动方式编码,另一些例子则使用WDF的方式编码(虚拟磁盘与虚拟网卡)。读者会发现这二者之间一脉相承,只要熟练掌握传统型的编程方法,了解WDF会是非常轻松和愉快的过程。
  本书的习题
  有些读者不喜欢用习题来练习的方式,他们认为"这只是一些知识性的东西,记下来是浪费大脑的空间"或者"这些东西在需要的时候再去查阅资料就可以了"等。确实,有许多细节是不需要去记忆的。对一个程序员来说,最重要的就是在需求产生、得到问题时,明白应该从哪里入手去解决这个问题。这就要有一些在大脑中已经建立的概念。如果是处在完全蒙昧无知的状态下,那么就算把整个图书馆都摆在面前,也完全没有意义。
  本书每章后都附有少量的习题,这些习题的目的在于让读者自我检查,读完一章后是否已经建立了正确的概念。此外,还有一些常识性的习题(比如指令int3的意义是什么),是会对读者在进行实际工作时有很大帮助的,建议读者不要忽略。

评论 1

要的就是X61  V3+  发表于 2009-5-31 13:37 | 显示全部楼层
看起来不错。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

关注

21

粉丝

151

主题
精彩推荐
热门资讯
网友晒图
图文推荐
  • 微信公众平台

  • 扫描访问手机版

Archiver|手机版|小黑屋|水窝ibm

GMT+8, 2025-7-18 06:50 , Processed in 0.074396 second(s), 24 queries .

Powered by Discuz! X3.5

© 2001-2022 Comsenz Inc.