全局句柄表
1.全局句柄表
句柄介绍
句柄一共有3种
- 全局句柄表 进程 线程 句柄表
- 私有句柄表 进程私有的
- 窗口句柄
全局句柄表
在全局句柄表种只有进程
和线程对象
OpenProcess/OpenThread
权限 是否继承和 id
获取创建进程的handle的流程:
获取到进程id 取全局句柄表种找到进程对象,把进程对象插到进程的私有句柄表中,从而返回一个索引号,返回3环,这就是三环获得的句柄
无论是线程id还是进程id都是全局句柄表的索引号
在windows只有进程和线程有id,其他的只有对象名字
当全局句柄表地址后面是0,那么代表的是句柄表,3096一个页的大小,每一项8个字节,也就是一个id索引号就是8字节,当空间耗尽后,会把表里面的数据移到一个新的申请的内存,将原来的表清空,这时候全局句柄表地址后面是1,4个字节1项,再满了后就存放到新的开辟的内存中
句柄表地址后面的0,1,2代表层级
地址分成两部分,高字节存放属性低字节存放地址和几个小属性
举例
拿DebugView举例,进程pid是2792
在ida中可以看到名字是PspCidtable
交叉引用查看一下,注意这个函数不是导出函数
可以看到都是和线程和进程有关的
可以看到PsLookupProcessByProcessId
函数在这个位置使用了这个函数,俺么就可以通过这个函数定位到这个PspCidtable
函数的运行地址
也就是说我们要获取到这个地址就是PspCidtable
函数的地址
windbg中dd
一下就可以看到全局句柄表
DT一下就可以看到对应的结构
kd> dt _HANDLE_TABLE 8d2010a0
ntdll!_HANDLE_TABLE
+0x000 TableCode : 0xa7982001//这个尾数代表有几层0是1层,1是2层
+0x004 QuotaProcess : (null)
+0x008 UniqueProcessId : (null)
+0x00c HandleLock : _EX_PUSH_LOCK
+0x010 HandleTableList : _LIST_ENTRY [ 0x8d2010b0 - 0x8d2010b0 ]
+0x018 HandleContentionEvent : _EX_PUSH_LOCK
+0x01c DebugInfo : (null)
+0x020 ExtraInfoPages : 0n0
+0x024 Flags : 1
+0x024 StrictFIFO : 0y1
+0x028 FirstFreeHandle : 0xf48
+0x02c LastFreeHandleEntry : 0xa7980d40 _HANDLE_TABLE_ENTRY
+0x030 HandleCount : 0x1ed
+0x034 NextHandleNeedingPool : 0x1000
+0x038 HandleCountHighWatermark : 0x29b
dd
一下查看一下哦表中的值(注意把TableCode
尾数改成0)
kd> dd 0xa7982000
a7982000 8d205000 a7980000 00000000 00000000
a7982010 00000000 00000000 00000000 00000000
a7982020 00000000 00000000 00000000 00000000
a7982030 00000000 00000000 00000000 00000000
a7982040 00000000 00000000 00000000 00000000
a7982050 00000000 00000000 00000000 00000000
a7982060 00000000 00000000 00000000 00000000
a7982070 00000000 00000000 00000000 00000000
这里每一项代表了一张表
这里我们DebugView的pid是2792
需要除以4
,因为步长是4
,也就是698
(注意是10进制)
每一张表中有512个元素
所以用之前获得的698
除以512
可以知道在哪张表,这里就在第1张表,也就是编号为0
也就是上图中的那张表
之后再拿698
取模余512
(就是%),也就是186
取出表中的索引号
接下来用windbg查看
但是因为windbg自动是16进制的,所以我们上面取到的索引号
要转成16
进制,也就是BA
,最后还要*8
(因为8字节)才可以获取到句柄表中的地址
kd> DQ 8d205000+BA*8
8d2055d0 00000000`88d736b9 00000000`88aae751
8d2055e0 00000000`88aa3a81 00000000`88aaf541
8d2055f0 00000000`88aa51f1 00000f64`00000000
8d205600 00000000`88aadd21 00000000`88ac7d49
8d205610 00000000`88ab8a59 00000000`88ac3591
8d205620 00000000`88102341 00000000`88ac9031
8d205630 000007a4`00000000 00000000`881029d9
8d205640 00000000`88aca2a9 00000000`88ace639
可以发现有些地址尾号仍然有一个1
这个1
是一把锁