写在前面的话
之前学的Windows编程都是界面啊、网络编程啊之类的纯应用层面的东西,总是感觉而自己没有达到自己期望中的水平。什么水平呢?如果让你编写监控系统资源的工具,或者DLL注入相关软件,或者底层安全软件,可以胜任吗?我的答案是,并不会。所以,离目标还很远,得继续学。
此阶段学习的是Windows高级编程,期间也了解了点内核驱动开发。后者是更深层次的研究,主要研究编写运行在ring0层的内核程序,难度更高,是达到我期望的技术水平的努力方向。现阶段还是先攻克Windows高级编程,步步为营,读书,练习,做笔记,打好基本功。
主要的参考书是:
- 《Windows高级编程指南(第三版)》, [美] Jeffrey Richter.
好,开始今天的学习。
因为第一章说的是win32与操作系统版本之间的相关事项,所以这里略过。
第二章 内核对象
1、概念
不愧是高级编程,上来就谈内核。
这一章中主要说了,一些重要的系统资源,是通过内核对象来管理的。比如进程。进程也是通过内核对象来管理的,但是进程的数据、代码是放在用户态内存里面的。注意突出理解两个字:管理。
根据我的理解,画出了下面的简单的关系示意图。主要需要明白句柄表的工作原理,系统是怎么通过句柄表来管理系统的内核对象的。这里只说学习方向,不详细解析了,书上都有。
2、使用
只能通过API来创建、释放内核对象。
内核对象通过内核句柄表来管理。应用程序中的句柄是内核对象在内核句柄表中的索引(书上说在NT中是字节数,这个没有被文档化,所以仅做理解,实际情况大差不差)。
每个内核对象有一个使用计数,也叫引用计数。多个进程使用同一个内核对象的话,每多一个使用者,使用计数+1。当进程结束时,操作系统为进程清理相关资源,挨个释放内核句柄表中的对象。很显然,这样的机制能够保证内核对象能被正确地创建、销毁,很好地对内核对象进行了管理。
如果需要进程间共享内核对象的话,有几种特定的方法。内核对象被设计成只能通过特定的方法访问,这样做是为了安全性考虑。第一章中介绍了进程间共享内核对象的几种方法:
- 使用继承,需要向子进程传递句柄值(进程间通信),特点是句柄值是相同的。
- 使用命名的对象。特点是句柄值是独立的。
- 使用duplicateHandle,有特定的使用情景(需要多种已知条件),并不是更简单的方法。
先大致了解原理,用到的时候,知道找什么代码就行了。
另外需要提到的是安全描述符。刚开始看到这个东西,不知道它是用来干嘛的,看起来很烦(不知道你面对一串不知含义的参数还有没有看下去的欲望)。看了其他的书籍后,消化了一段时间,现在是明白了它的用处。前面提到,内核对象的访问是很注重安全性的。使用安全描述符就是内核对象的创建者用来告诉操作系统,我创建的这个东西谁能用,能怎么用(读写等)。原理就是这么简单。
本章末尾那个实例说明了,duplicateHandle可以用于进程自己给自己复制句柄,这两个不同的句柄指向同一个内核对象。使用情景是多线程中需要使用同一个内核对象,如何正确关闭句柄。