什么是句柄(内核对象)
当一个进程创建或者打开一个内核对象时,将获得一个句柄,通过这个句柄可以访问内核对象。
如:
HANDLE g_hMutex =::CreateMutex(NULL,FALSE, "XYZ");
HANDLE g_hMutex =::OpenMutex(MUTEX ALL ACCESS, FALSE, "XYZ");
HANDLE g_hEvent =::CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE g_hThread =::CreateTpread(NULL, 0, Proc, NULL, 0, NULL);
...
我们调用一些窗口相关函数的句柄,虽然也是句柄但是和这个是不一样的,这里面的句柄它一定对应一个内核对象。
这些内核对象其实也是一个结构体,要在0环才能进行读写。
为什么要有句柄?
句柄存在的目的是为了避免在应用层直接修改内核对象。
HANDLE g hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
如果 g_hEvent 存储的就是EVENT内核对象的地址,那么就意味着我们可以在应用层修改这个地址,一旦指向了无效的内核内存地址就会蓝屏
每一个进程都会一张句柄表。
创建的和打开的句柄它在0环对应的内核对象的地址就会存储到这张表中。(创建和打开是不一样的)
如果再次通过OpenEvent来打开,这时系统并不会为这个事件创建一个新的结构体,它有一个计数器打开一次它就加一次。
调用的函数返回值为HANDLE的返回的就是句柄表中对应成员的索引。
句柄表的位置
dt _EPROCESS
...
+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE
...
kd> dt _HANDLE_TABLE
nt!_HANDLE_TABLE
+0x000