引言
我们首先需要了解在windows内核中,为了方便管理一些相关的数据结构,Windows统一把它们称之为对象。在Windows内核代码中大量代码都是用C语言编写的。而我们知道在C语言中,并没有纯粹的面向对象,也没有类这一说。因此我们可以理解在内核中的对象。无非就是我们C语言中最常用的结构体。
理解对象是什么
如果有了解过Windows中进程和线程的表示。应该很清楚知道所谓的_EPROCESS,_ETHREAD,就是用来描述一个进程或者线程的结构体。(可以参考前面的文章Windows三大结构体那一章)。总结一下前面所说,其实就是表达一个意思,在内核中所谓的对象就是结构体。那么回想在我们学习C语言的时候,学到结构体那一章。我们如果想访问一个结构体的成员是不是可以拿到它结构体的指针,然后通过(->)符号来访问结构体中的成员。那么我们再假设一个例子。我们通过malloc函数向操作系统开辟空间,当这个函数成功的时候向我们返回开辟空间的首地址,当开辟失败的时候会像我们返回NULL。类比这个过程,假设现在我们在向操作系统创建一个内核对象。也就是在内核空间创建一个结构体。那么创建成功与否,操作系统都要给我们一个信号,假设成功后操作系统向我们返回这个结构体的首地址,方便我们访问成员。如果Windows操作系统是这么做的,设想一下会有什么问题。
内核对象的地址作为返回值弊端
书接上回,如果操作系统真的那么做了,对于黑客来说,相当于告诉它,我的家在哪里哪里,你过来偷呀。内核空间的对象,一般都是非常重要的,里面的成员的值也不是随随便便能让用户空间去修改的。因此,为了系统的安全和健壮性。Windows并没有采用C语言这种原生态返回地址来操作内存和数据。而是采用一个叫句柄的的东西。这个玩意说白了,它能找到内核对象所在的位置,但是又不告诉你对象具体在哪。有点像跟你玩捉迷藏。反正目前为止,我们只需要知道,Windows句柄,实现了类似返回一个结构体地址的这么一个指针功能,但是又不是指针。
总结
因此我们现在了解,内核中的对象他们位于内核空间,在用户空间不能单纯用地址来引用他们,因此Windows使用句柄来管理和引用对象。当一个进程利用名称来创建或者打开一个对象的时,该句柄指向所创建或者打开的对象,例如,文件操作中,是使用句柄来表示的。每当应用程序打开或者创建一个文件的成功的时候,会返回一个句柄。以后应用程序都使用该句柄来标识该文件。如果有两个应用程序以共享的方式打开同一个文件 。那么它们将得到两个句柄,并且这两个句柄的值并不相同,但是却都指向同一个文件,且都通过各自的句柄操作同一个文件。因此,句柄只是一个对象的引用,同一个对象在不同的环境中可能有不同的句柄值。