透明加密系统设计及实现-WINDOWS内核分析及编程方法

damone大约 51 分钟工作总结透明加密

本文主要介绍 Windows 内核的基本结构,了解 Windows 的基本结构是进行内核编程的必不可少的内容。透明文件加密系统最为核心的单元是采用 Windwos 内核过滤驱动进行设计和实现的,故而必须准确认识和理解 Windwos 内核驱动模型的原理才能设计出合理高效的透明加密的驱动程序。过滤驱动位于文件系统驱动及 I/O 管理器之间,进行透明解密、文件控制及用户控制时需要和操作系统内核的其他关键的部件进行交互,同时必须对操作系统的存储结构、缓存结构及 I/O 流程有比较深入的了解,才能设计和实现出一款效率高、稳定性好的透明加密系统。内核编程难度大,不易把握,为了更好地理解系统的实现,本章简要地介绍了内核编程的一些基本方法,包括内核模式下字符的管理、内存的分配及的进程的同步互斥的控制方法。要开发一款软件,特别是系统软件,没有有效的构建和调试环境,一切都是纸上谈兵,为此,本章最后给出了构建编译环境及调试驱动环境的基本方法,以供参考。

1 WINDOWS 内核结构

从 1993 年起始,微软公司开始采用其耗时五年研究的新内核框架 NT3.0,NT 内核采用了混合式的内核设计方法,充分结合了聚内核及微内核的设计思想进行开发,扩展性及效率都得到了很好的保证。图 1 显示的 Windows 的基本结构。

图 1 Windoows NT 内核结构图

Windows 操作可以划分为两种模式,内核模式(kernel mode)及用户模式 (usermode)。全部的应用程序都是工作在用户模式下的,包括操作系统子系统、系统和服务进程以及各种应用程序。用户态的应用程序主要通过系统调用与操作系统内核进行交互,部分的系统和服务进程直接与内核交互,而子系统则通过子系统 DLL 及系统调用与系统内核进行交互。

在内核模式下,主要运行的是操作系统的核心构件。包括执行体、内核(微内核)、硬件抽象层等关键组件,还有文件系统、网络和各种驱动程序,以及在后期移入内核空间中的窗口管理与 windows 子系统,这些都是操作系统的组成部件,和整个操作系统密切相关,任何模块崩溃都会导致整个系统的瘫痪。

1.1 系统模式的区分

Windows 采用了双模式(dual mode)结构来保护操作系统本身,避免被其他的进程修改操作系统本身,保证系统的安全性。同时避免了操作系统被其他的进程的崩溃所殃及。操作系统核心工作在内核模式(kernel mode)下,应用程序代码工作在用户模式 (user mode) 下。内核模式需要用到系统内核或者内核的驱动程序时,采用硬件指令切换到内核模式,完成用户的请求后,从内核模式恢复用户模式,这样保证了用户到内核的的相互切换,不至于破坏操作系统的结构。图 2 简要地描述了用户模式及内核模式的关系。

图 2 内核模式与用户模式

1、用户模式
        当启动一个用户模式的程序时,Windows 为其创建这个程序创建与其对应的进程。进程为程序的运行提供了运行的环境,包括私有的虚拟地址空间(virtualaddress apace)及一张私有的句柄表 (handle table)。一个进程的虚拟地址空间是私有的,一个进程不能修改属于其他进程的数据,程序间的运行都是隔离的,当一个程序崩溃时,仅仅影响到当前的程序,和其他的进程及操作系统内核都不会受到当前进程崩溃的影响。

用 户模式的程序的私有的虚拟地址空间是受限制的,一个运行在用户模式的进程是不能访问保留给操作系统的虚拟地址空间的。限制用户模式的程序的虚拟地址空间是 为了防止用户模式的程序修改或破坏核心的操作系统的数据,保证系统的安全性。所有的应用程序以及部分用户模式驱动工作在用户模式,它们的虚拟地址空间是相 互隔离的。

2、内核模式

所 有的运行在内核模式的的代码共享一个单独的虚拟地址空间,这意味着一个内核模式的驱动和其他的驱动和操作系统本身是不分离的。如果一个内存模式的驱动偶然 间向一个错误的虚拟地址写入数据,属于操作系统或另外的驱动的数据就可能会被破坏。如果一个内核模式的驱动崩溃了那么整个操作系统同样会一起崩溃,导致整 个系统的瘫痪。

运行在内核 模式的除了操作系统的核心内核之外,包括支持例程扩展驱动、文件系统驱动及其他驱动,还有和硬件关联紧密的硬件抽象层及硬件本身。当然并不是所有的驱动都 工作在内核模式下,有一些被称为用户模式驱动的驱动程序工作在用户模式下,常见的打印机驱动就属于此类。

1.2 WINDOWS 的关键组件

1、内核

这是大内核中的小内核,又称为微内核,其在操作系统中是最为核心的构建,是其它的构件的基础,保证执行体构件。在内核模块 ntoskrnl.exe, 内核位于下层,和 HALc 层最为接近。负责线程调度和中断、异常的处理,在多处理器中,还承担着同步处理器之间的行为,起到了优化系统的性能的作用。主要采用 C 语言开发也包括部分汇编代码。

2、执行体

执行体位于内核模块 ntoskrnl.exe 的上层,以内核为基础,是内核的扩展。主要包括进程及线程管理器、内存管理器、安全应用监视器、I/O 管理器、缓存管理器、配置管理器、即插即用管理器、电源管理器及对象管理器等。其中内存管理器,安全应用监视器 I/O 管理器、缓存管理器和透明加密驱动的开发有着紧密的关联。内存管理实现了虚拟内存管理,负责系统地址空间的内存管理,是缓存管理器的底层支持。安全应用监视器(SRM), 实施系统的安全审计,守护系统的资源、执行对象的保护及审计。缓存管理器为文件系统提供统一的数据缓存支持,运行文件系统驱动将磁盘中的数据映射到内存中来,并通过内存管理器来协调内存的分配。

3、设备驱动程序

驱动程序是内核扩展的最为主要的方式,Windwos 操作系统中的驱动程序并不一定对应相应的物理设备,可能是一个虚拟设备,也可能无任何一个设备无关,仅仅作为内核的扩展模块。驱动程序可以动态加载到操作系统中称为系统的模块,由于其工作内核模式下,除了通过 HAL 访问硬件以外,也可以直接访问硬件。透明加密就属于驱动程序,存在相应的虚拟设备,位于文件系统驱动设备之上。

4、文件系统

在操作系统中,文件系统是外部存储设备的统一接口,它为应用程序访问这些设备的数据提供了统一的接口,在 Windows,文件系统的接口部分由 I/O 管理器定义和实现,但其专门的驱动则在一些被称为文件系统驱动的程序中。文件系统驱动定义了外部存储设备数据中数据的逻辑结构,从而使得数据在操作系统可以进行统一的操作,由操作系统提供统一的接口进行访问。

2 WINDOWS 的存储结构

从应用程序的角度来看,通常会看到两种最为常见的数据存储的介质:系统主存和外存(包括磁盘、光盘和移动存储介质)。这是由于操作系统为用户提供了统一的操 作数据的抽象接口,从而简化了上层用户对外存的操作步骤。降低了编程的难度,提高了系统的性能和稳定性。但是要做好驱动层的透明加解密,停留在这一层次是 远远不够的,必须清楚计算机硬件存储结构的组成模式,同时还要掌握文件 I/O 操作的基础流程,以及缓存管理与文件系统驱动的联系,熟悉文件缓存为文件系统提供的操作缓存的基础接口。掌握文件 I/O 的基本方式,对不同的 I/O 方式采取合理的处理措施。

2.1 硬件存储体系

从体系结构的方面来考虑,计算机的存储体系是分级的,采用多级存储体系结构,可以降低 CPU 访问低速设备的时间,从而提高 CPU 的运行效率。但是分层必须合理,分层太少,不能满足性能的要求,分层太多,划分的成本就会上升,甚至可能导致性能的下降。下图给出了典型的 intel x86 处理器支持的存储结构,总体而言越是靠近 CPU, 其访问耗费的时间就越少,但是其价格就越高,由于成本的限制相应的大小就会受到很大的影响。从图中可以看出,访问主存的速度是远远大于外部存储的速度,如 果做好缓存的优化,可以极大地提高操作系统的性能。所以在进行透明加解密的时候,必须充分考虑缓存的作用,减少对操作系统缓存的破坏,保证操作系统的性 能。

图 3 Intel x86 处理器支持的存储体系结构

2.2 WINDOWS 的存储管理结构

在 Windows 的存储管理的体系结构中,存储管理和文件系统是必不可少的,二者缺少其中的任何一个,操作系统都将无法运行。Windows 的所有的设备都是通过文件对象的形式被应用程序访问的,文件的重要性可想而知。主内存的管理工作主要由操作系统来负责的,当然外存也不例外,外存都是操作系统通过驱动程序进程访问和管理。系统和应用程序通过 I/O 管理器来与这些设备的驱动程序进行交互,从而完成数据存储。图 4 详细地描述了一个磁盘文件读写请求的在操作系统中路径。从中我们可以看出文件的读写与 I/O 管理器、内存管理器、缓存管理器及文件系统驱动程序是密不可分的。

图 4 Windows 的存储管理结构

1、Windows 内存管理

当一个处理器读写内存中某一位置的的数据时,其使用的是虚拟地址空间。在读写的过程中,处理器将虚拟地址转换为相应的物理地址,然后再进行数据的访问。采用虚拟地址空间可以让不同进程共享同一虚拟地址空间,同时可以防止进程间相互的数据破坏。如图 5 所示,在所有的进程中,它们有各自的私有的地址空间,其他程序不能访问。但是它们共享同一个系统虚拟地址空间,在用户模式下,进程是没有权利访问系统虚拟地址空间的。

图 5 进程的虚拟地址空间

在用户空间(users space)下,所有的进程的物理页面都能在需要时被换出到磁盘文件(disk file)中。但是在系统空间(systemspace), 并不是所有物理页都能被换出到磁盘文件中,一些物理页是不能被换出到磁盘文件中的。如图 6 所示,在系统空间有两种区域的内存区域是为内存的动态分配准备的:换页内存池和非换页内存池。

图 6 换页内存池与非换页内存池

从换页内存池中分配的内存中分配的内存是可以换出到磁盘文件中的。而从非换页中分配的内存将永远不会被换出到磁盘文件中。在硬件中断的运行环境下不能使用非换页内存池,因为系统本身位于中断环境中,不能处理页缺少中断,导致系统死机。

2、Windows 缓存管理

Windows 的文件缓存管理位于内存管理器与文件系统驱动程序之间,缓存管理器使用了系统空间中预留中的一段地址范围,并控制好那些文件的那些部分可以使用这些地址和相应的物理内存,以满足大文件存取和系统有限内存之间的一种平衡。通过文件缓存可以极大地提高文件的读取效率。

在文件的读写操作时,可以将文件的读写方式分为两大类,一类是有缓存的,另一类是没有缓存的。一般打开文件时,都是以有缓冲的方式打开的。为了更好理解缓存在系统的作用,图 7 给出了 I/O 请求经过缓存管理器的路径。

图 7 I/O 请求经过缓存管理器的路径

当文件以非缓冲方式打开文件后,对该文件的读写都是直接从磁盘中读取文件内容或者是直接将内容写到磁盘文件当中,中间没有任何的缓冲处理。如果未指明文件的 打开为非缓冲的方式打开文件,则系统默认以缓冲的方式打开文件,当读取或写入文件时,并不是直接从文件中读取或写入,而是先通过缓存管理器中的接口函数 CcCopyRead、CcFastCopyRead 从缓存中读取,通过 CcCopyWrite、CcFastCopyWrite 将 内容写入缓存中。如果缓存中没有,内存管理器将会产生缺页中断,由文件系统驱动将文件的内容读取到缓存中,然后再从缓存中读取。为了提高操作系统读取文件 的性能,缓存管理器提供预读及延迟写机制,就是提前将文件的内容先按一定的算法预读取到缓存中,当读取文件时,直接从缓存中获取,这样极大地提高操作系统 的性能,而写入时,将写入的内容写入缓存中,当操作系统空闲时或需要时写入文件中。

3 WINDOWS 内核驱动模型

3.1 驱动程序分类

1、根据用途分类

在 Windwos 驱动程序不仅仅是为各种设备提供 I/O 的能力,也是 Windows 操 作系统进行扩展的基础,通过动态地加载和卸载驱动模块,系统可以进行动态的扩展和精简,内核模式的驱动程序采用统一的接口,这些接口在所有的内核模式的驱 动上均是统一的。根据功能的不同我们将驱动程序分为三类,包括即插即用驱动程序、内核扩展驱动程序和文件系统驱动程序。即插即用驱动程序称为 WDM 驱动程序,用于支持常见的存储设备,视频适配器和网络设备等等。内核扩展驱动程序是非即插即用类驱动程序,是内核的扩展功能。文件系统驱动程序设专门针对文件 I/O 请求的,然后将这些请求定位到具体的网络设备或存储设备,将文件的 I/O 请求下发到具体的媒介中。

2、根据层次结构分类

根 据驱动位于系统的位置,不同位置的驱动的作用往往区别也是巨大的。为了便于区分和比较,将其分为三大类,分别是总线型驱动程序、功型型驱动程序及过滤驱动 程序。总线是最底层的驱动程序,用户管理一个总线设备,负责检测总线上附载的所有设备。功能型驱动设备位于总线设备驱动之上,管理具体的设备,功能驱动程 序是实际管理真实设备的功能模块。位于功能设备驱动之上的或之下的用于监视某一设备的 I/O 情况以及这些请求的处理情况,或者增加或者改变另一个驱动或另一个设备的行为的驱动。系统中开发透明加解密驱动就是属于此类。

3.2 驱动程序的代码结构

驱动程序在操作系统相当于操作系统的一个扩展模块,为了识别驱动程序,操作系统为每一驱动程序提供一个唯一的驱动对象与之对应,该对象是有对象管理器创建的。如图 8,驱动对象包括大量的派遣例程,包括初始化例程、增加设备例程、各种分发例程、卸载例程和各种可选例程。驱动程序的各个派遣函数例程都由操作系统进行管理和调度,其中初始化例程主要完成驱动的初始化工作,增加设备例程完成设备的即插即用的管理,而各种分发例程则完成相应的 I/O 请求的处理,可选例程用于完成各种辅助功能。凡是内核模式下的驱动程序,都采用如图代码结构进行安排,由操作系统进行统一的管理。

在驱动程序对应的驱动对象中还有一个成员是比较关键的,就是设备对象成员,它指向了一个单链表,链表中的每一个成员都是由该驱动程序创建的设备对象,设备对 象代表了驱动程序的一个实例,每一个驱动程序都会创建一个和多个设备对象,每一个设备对象都会有一个指针指向下一个对象,形成设备链。设备对象指明设备的 类型及其对应的具体物理设备或者虚拟设备,多层次结构的设备对象可以组成设备栈结构。

图 8 驱动程序的代码结构

3.3 I/O 请求包及缓冲区管理

在 Windows 有一种数据结构被称为 I/O 请求包(I/O Request Package), 也被称为输入输出请求包,简称 IRP。它是 Windwos 操作系统中进行 I/O 交互的重要的数据结构,相当于消息结构中的消息包。起到传递数据的作用。

在驱动程序的派遣例程中,I/O 请求包将会作为大多数的例程的必要的输入及输出参数,无论是数据的下发,还是结果的返回都跟 I/O 请求包是密切相关的。在 IRP 中指定了 I/O 请求的主功能号和此功能号,决定了 I/O 请求的功能,操作系统根据功能号将 IRP 派遣到不同的派遣例程当中。IRP 有几十种功能号,其中比较常用的有 IRP_MJ_CREATE、IRP_MG_CLOSE、IRP_MJ_READ、IRP_MJ_WRITE 等。在 IRP 中还包括大量的其他的信息,如 I/O 请求对象对应的设备对象及文件对象,以及缓冲区地址等。

在 I/O 请求包中还包括了缓冲的方式及缓冲区,指定了信息交换的缓冲区地址。操作系统为驱动程序提供了统一的缓冲管理的机制,数据在各个设备对象间传递时,数据的交互得到了有效的保障。在透明加密中需要截取文件 I/O 的请求包,然后对它们进行过滤操作,完成透明加解密的功能。在 Windwos 中,按缓冲进行分类,I/O 可以分为四类,分别是缓冲的 I/O、直接输入 I/O、直接输出 I/O 及两者皆非 I/O。缓冲 I/O 采用系统中非换页内存作为输入输出缓冲区,直接进行操作。直接输入 I/O,对于从设备读取数据的操作,驱动程序需要为其建立内存描述符链表,将分配的缓冲区物理页面构造为一个 MDL , 如此、驱动便可采用 DMA 方式传输数据了。直接输出 I/O 与直接输入 I/O 为指定的缓冲构造号 MDL 后便可采用 DMA 方式进行数据的传输。两者皆非 I/O 的缓冲方式不由 I/O 管理器或者 I/O 请求的发起者完成缓冲区的管理工作,而是由驱动程序完成缓冲区的使用和管理功能。

3.4 驱动程序的设备栈

前文已经提到,在 Windows 操作系统中驱动是按功能进行了分层的,有 I/O 管理器统一进行管理。如图 9 所示,位于底层总线设备驱动管理挂载在总线上的设备,在其之上可以加载总线过滤驱动,用户扩展或监控总线设备。在之上的是对应设备的具体的功能设备对象,功能设备对象之上或之下都可以加载过滤驱动对功能驱动进行过滤。当 I/O 请 求下发时,会从上层设备对象依次向下传递,上层的驱动有权利阻止或修改传递的请求,从而达到过滤和监视的功能。而设备驱动则是由相应的驱动程序动态创建 的,由操作系统统一管理。从图中可以发现,总线设备对象只能在其之上加载过滤驱动对象,而功能设备对象可以在其上层或者下层加载过滤设备对象。

图 9 驱动程序的设备栈

4 文件系统的 I/O 过滤

当 I/O 管理器将 I/O 请求发送到文件系统的设备上时,由于系统可能加载了其他的文件系统过滤驱动,故而 I/O 请求需要经过这些过滤驱动程序才能能够到达文件系统驱动设备,由文件系统驱动进行处理。在 Windows 中引入了两类文件系统过滤驱动,分别是文件系统过滤程序和文件系统小过滤驱动程序。对于这两种过滤驱动程序,由于他们都工作在文件系统驱动之上,所以他们会比文件系统驱动程序先得到文件 I/O 的请求,事先得到文件 I/O 的处理权,对文件 I/O 实现过滤操作,完成相应的过滤操作,实现具体的过滤功能。

4.1 文件系统过滤驱动程序

文件系统过滤驱动程序能够能够过滤文件系统或卷的 I/O 操作,可以监视(monitor),记录 (log) 阻止和修改这些 I/O 操作。典型的包括病毒监测、加密和数据压缩等。文件系统过驱动采用了与设备栈的中的其他驱动程序类似的工作方式,进行 IRP 的处理来完成附加的功能服务。图 10 显示了加载一个文件系统驱动 filespy 之后的文件设备驱动栈的前后变化情况。在加载之前,系统中在文件系统设备对象之上仅仅包含一个 fltMgr 设备对象 (用于小过滤驱动程序的管理),而在加载之后,安装加载的顺序在 fltMgr 之上。

 

(a)filespy 加载之前         (b)filespy 加载之后

图 10 filespy 加载前后 ntfs 卷的设备栈

4.2 文件系统 Minifilter 驱动程序

在 Windows 操作系统中,跟随系统一起安装一款过滤驱动管理器程序 fltMgr.sys,当系统加载任何一个小过滤驱动时,该过滤驱动管理器就会被激活并加载到文件系统驱动设备栈中的文件系统驱动之上。fltMgr 提供了一套过滤驱动开发框架,被称为 Minifilter 过滤驱动,也称小过滤驱动。一个小过滤驱动程序可以向 fltMgr 注册它感兴趣的 I/O 操作,并为其指定相应的预操作回调例程(preoperation callback routine)和后操作回调例程(postoperation call back routine),也可以仅仅指定其中的一个。当 fltMgr 进行 I/O 处理时,在 I/O 请求完成之前或之后,它调用每一个小过滤驱动程序的向其注册的操作回调函数进行 I/O 的处理。在小过滤驱动程序中,可以对 IRP 请求进行过滤操作。

当系统存在多个小过滤驱动程序时,fltMgr 根据小过滤驱动的高度值(altitude)进行回调的顺序安排高度值从高到低依次调用。微软为常用的小过滤驱动指定了合适高度值。如图 11 显 示了不同的高度的小过滤驱动在文件设备驱动栈的位置分布,可以看出在小过滤驱动的框架模型中,各种文件过滤驱动能得到很好的兼容,甚至连传统的的文件过滤 驱动都能得到好的支持,为了实现跨文件过滤驱动的多个小过滤驱动的管理,系统支持多帧的小过滤驱动管理器,分别在文件过滤驱动程序之上和之下创建文件系统 管理器对象。

图 11 过滤管理器与小过滤驱动程序

在 Minifilter 的编程框架中,Minifilter 提供了用户模式应用程序的支持,也提供了用户模式与内核模式的通信的基本方法。此外 Minifilter 提供了大量的运行函数支持,可以解决在驱动中的重入问题,降低开发的代价。Miniflter 开发框架和第四代透明加密技术的 LayerBSD 的设计思想完全吻合,提高透明加密驱动驱动和其他类型的文件系统过滤驱动的兼容性。降低了内核中文件系统设备栈的深度,提高了系统的性能,此外,Minifiler 开发框架具有良好的扩展性,可以随时添加感兴趣的过滤操作,而对其他的操作不会造成任何的影响。

5 WINDOWS 内核编程的基本方法

5.1 内存分配

在内核模式下,动态内存的分配分为两种类型,一种是换页内存池,另一种是非换页内存池,进行内存分配时,必须充分考虑到运行环境的要求,当代码的运行环境处于高优先级(大于等于 DPC LEVEL)的模式下是不能使用内存分配时必须从非换页内存池中分配内存,否则系统将会崩溃,因为高优先级中断的运行环境处于硬件中断级别之上,不能处理物理页缺失中断。

在内核模式下采用 ExAllcatePool 及其类似函数完成内存的分配,在分配时可以指定参数为 NonPagedPool 表示非换页内存,指定 PagedPool 表示换页内存。函数的具体使用方法请参考 MSDN 中 DDK 帮助文档。

5.2 字符集管理

在 Windows 的内核模式下,为了保证系统的数据不丢失,建议使用 UNICODE 字符编码,能够更好地处理第三方编码的字符,提供对中文的支持。在内核模式下的 UNICODE_STRING 数据类型,不具有内存的自动管理及分配的能力,需要程序员自己进行管理。这一点必须要牢记。此外 Windows DDK 提供大量的 UNICODE_STRING 操作的支持例程,包括初始化、字符拼接、字符比较等等。具体的使用可以参考 MSDN 中的 WDK 帮助文档。

5.3 内核态的同步及互斥

在内核态下进行驱动程序的开发必须考虑进程的同步与互斥的问题,因为操作系统之上运行着大量的进程。当这些进行发起 I/O 操作,系统陷入内核模式去执行驱动程序的代码时,其是运行在当前发起进程的进程的环境下的,所以驱动程序的代码是运行在多个进程的环境之下的,必须考虑到进行的资源的共享和竞争,必须考虑到驱动程序代码的可重入性。

在操作系统内核模式下的程序必须充分考虑进程是否处于中断环境中,不同的中断环境下,采用的同步及互斥的控制方式是不同的。为了便于管理,Windows 设计者将中断请求划分为软件中断和硬件中断,并将它们映射到不同的中断请求级别之上,同步机制依赖于具体的中断请求级别。Windows 的中断请求级别被划分为 32 个级别,分别表示不同中断级别,详细参见图 13。

图 12 中断优先级的划分

在不同的中断优先级采用的同步互斥机制是有区别的,在此主要介绍运行在内核模式下的进程间的同步及互斥机制。内核模式下的同步互斥机制远远多于用户模式用户模式的同步互斥机制。常用的有自旋锁(spinlock)、事件 (event)、信号量 (semaphore)、互斥体 (mutes) 及执行体资源 (executive resource) 等等。具体的详细的介绍参见 DDK 帮助文档,如果需要文中会及时补充说明。

5.4 驱动程序的编译及调试

1、驱动构建编译及调试环境

为了满足驱动开发的需要,微软提供一套 Windows 平台的驱动程序开发的编程缓存 WDK, 到链接地址:http://www.microsoft.com/en-us/download/details.aspx?id=11800open in new window 下载 Windows Driver Kit Version 7.1.0,并将其解压安装。安装时需要安装上调试工具,安装完成后即可进行使用。

采用 Vmware 虚拟机创建一台虚拟机并在虚拟机中安装上 Windows7 操作系统,在安装的 Windows7 操作系统中通过 bcdedit 编辑工具设置操作系统的启动模式为调试模式。关闭计算机,然后在 Vmware 中为 Windows7 虚拟机设置管道虚拟串口,命名为 “\.\pipe\com_1”。建立脚本 debug.bat, 加入脚本内容为:

"windbg.exe程序的绝对路径" –kcom:port=\\.\pipe\com_1,baud=115200,pipe &

启动 Windows7 虚拟机,启动模式选择为调试启动模式,然后立即在你的物理主机上以管理员的身份运行 debug.bat 脚本,完成调试器与物理主机的互联。如果操作系统成功启动,并且调试器窗口打印出联机成功的信息则表示表示调试环境搭建成功。

为了更好地跟踪调试和理解操作系统,需要指定 windows 内核的内核符号表,这样在调试时就可以定位操作系统模块及数据结构,不至于手足无措。

2、驱动的编译及调试

编写好驱动程序代码后,需要对其进行编译,安装好 wdk 后,针对不同的目的操作系统平台,需要选择对应的编译构建环境,进入相应构建环境,进入源代码的根目录,运行命令 build 便可以完成驱动的编译及构建,在选择构建环境时如果要进行调试最好选择 debug 的构建环境。

完成驱动的编译后,接下来就是将编译的驱动安装到目标计算机中,然后动态加载它。安装可以采用驱动安装设置文件 inf 文件,该文件详细描述了驱动程序具体情况及配置选项,该文件的编译可以参考 MSDN 相关的资料。安装时将 inf 文件与驱动程序放在同一文件夹下,右键打击选择安装即可完成驱动的安装。

完成驱动的安装,最后就是启动驱动程序,以管理员身份进入 CMD, 然后输入命令,net start yourdriver , 启动驱动程序。为了便于调试,你可以在驱动加载的例程中加入手动中断,当驱动加载启动时就会在此中断,你可以像使用其他的调试器一样使用调试器对驱动程序的代码进行调试。加入手动调试的方法如下,在你想要设置手动中断的地方加上如下的语句:

#if DBG

__ebugbreak();

#endif

在编译时采用调试版本进行编译,这样当目标操作系统处于调试环境下,执行到指定的代码处,程序就会中断。

6 本文小结

本文详细地介绍透明加密驱动程序设计及开发过程中涉及到的操作系统的内核的基础知识,包括 Windows 内 核的基本结构及主要的组成结构,系统模式的划分,操作系统的存储管理及驱动模型。简要地介绍文件系统过滤驱动(包括文件系统过滤驱动和文件系统小过滤驱 动)在操作系统组成位置及工作原理。最后指出了内核编程需要特别关注的要点,并简要地介绍了驱动构建及调试的环境搭建方法及调试技巧。