Windows句柄表格式

上次说了一点关于Windows 2000句柄表的东西,继续说关于XP的。

XP的句柄表格式与2000的完全不同。《Windows Internal》里面只是简单的说了一下关
于Windows XP/2003和2000的差异,在于开始的时候只分配最底层的句柄表,上面两层的
句柄表只在需要的时候才分配。而且最底层的句柄表和上两层的大小都不在是限制为256
项,而是根据内存分页的大小来分配——每一级表都是一页大。

我们先来看看XP当中的句柄表结构:
lkd> dt nt!_handle_table
nt!_HANDLE_TABLE
+0x000 TableCode : Uint4B
+0x004 QuotaProcess : Ptr32 _EPROCESS
+0x008 UniqueProcessId : Ptr32 Void
+0x00c HandleTableLock : [4] _EX_PUSH_LOCK
+0x01c HandleTableList : _LIST_ENTRY
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo : Ptr32 _HANDLE_TRACE_DEBUG_INFO
+0x02c ExtraInfoPages : Int4B
+0x030 FirstFree : Uint4B
+0x034 LastFree : Uint4B
+0x038 NextHandleNeedingPool : Uint4B
+0x03c HandleCount : Int4B
+0x040 Flags : Uint4B
+0x040 StrictFIFO : Pos 0, 1 Bit

这里面没有指针之类的东西啊,那么实际的句柄表的地址存储在哪里的?

事实上保存在TableCode当中——但是TableCode并不是地址,它比地址所担任的责任多一
点:标明这个指针指向的是哪一级别的句柄表。我们知道在x86上面Windows总是分配内
存使其沿四个字节对齐,所以实际的句柄表地址的低两位一定是0??XP就用这两位来标示
这个表是哪个级别。在XP 的观点当中,最底层的,用来保存实际句柄项的是第0级,上
面依次是1和2级。

同时,由于每一级句柄表的大小都是不一定的,因此每一级别的句柄表当中所存的项目
量也是不同的,由此导致的就是究竟如何解释句柄的值也是是不一定的。为了简单起见
,以我的Windows XP系统为例,页大小为4096,因此可以存储的句柄项为4096/8-1=511
(为什么-1可以参见WI,是为了Handle Auditing),上面两级的句柄表可以存储的指针
项为4096/4-1=1023个。这样一来,将32位的句柄除以4,剩下的30位有效位当中,从低
到高,就有9位表示在0级句柄表当中的索引,10位表示在1级的索引,10位表示在2级的
索引,一共可以有29位是有效的,这样句柄的最高位一定要是0,因为这个是无效的。

还是来几个例子吧:

第一个例子,只有第0级句柄表:

lkd> !handle 14 7 414
processor number 0, process 00000414
Searching for Process with Cid == 414
PROCESS 81f86548 SessionId: 0 Cid: 0414 Peb: 7ffdf000 ParentCid: 0664
DirBase: 0b6c0460 ObjectTable: e26cdab0 HandleCount: 38.
Image: notepad.exe

Handle table at e13f0000 with 38 Entries in use
0014: Object: e170d8d0 GrantedAccess: 000f000f Entry: e13f0028
Object: e170d8d0 Type: (823ef258) Directory
ObjectHeader: e170d8b8
HandleCount: 33 PointerCount: 3
Directory Object: e10003e0 Name: Windows

然后我们手动来查找14这个句柄:0x14/4=5,因此在0级句柄表当中索引是5。
lkd> dt nt!_handle_table e26cdab0
nt!_HANDLE_TABLE
+0x000 TableCode : 0xe13f0000
+0x004 QuotaProcess : 0x81f86548 _EPROCESS
...

TableCode最低两位是00,因此表明第0级句柄表的地址是在0xe13f0000。
lkd> dd 0xe13f0000+5*8
e13f0028 e170d8b9 000f000f e2ed7121 021f0001
...

_object_header地址:
0xe170d8b9 & 0xFFFFFFF8 | 0x80000000 = 0xe170d8b8。在XP当中_object_header大小
仍然是0x18,所以object body在0xe170d8d0:

lkd> !object e170d8d0
Object: e170d8d0 Type: (823ef258) Directory
ObjectHeader: e170d8b8
HandleCount: 32 PointerCount: 36
Directory Object: e10003e0 Name: Windows

Hash Address Type Name
---- ------- ---- ----
04 e15dbbb8 Port SbApiPort
09 e15e2eb0 Port ApiPort
32 e22d3310 Directory WindowStations

与!handle的输出相符。

第二个例子,有一级句柄表:
lkd> !handle 14d4 7 4fc
processor number 0, process 000004fc
Searching for Process with Cid == 4fc
PROCESS 81f83020 SessionId: 0 Cid: 04fc Peb: 7ffd5000 ParentCid: 02c8
DirBase: 0b6c0100 ObjectTable: e23f2ac8 HandleCount: 1254.
Image: svchost.exe

Handle table at e3173000 with 1254 Entries in use
14d4: Object: e15a4c48 GrantedAccess: 00000010 Entry: e32529a8
Object: e15a4c48 Type: (823b47f0) Key
ObjectHeader: e15a4c30
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: /REGISTRY/MACHINE/SYSTEM/CONTROLSET001
/SERVICES/SHAREDACCESS/EPOCH

句柄0x14d4/4=0x535=101 00110101,因此在第1级表当中索引是2,第0级表当中的索引
是0x135。
lkd> dt nt!_handle_table e23f2ac8
nt!_HANDLE_TABLE
+0x000 TableCode : 0xe3173001
+0x004 QuotaProcess : 0x81f83020 _EPROCESS
...

可见TableCode的最低两位是1,表明第1级句柄表的地址为0xe3173000:
lkd> dd 0xe3173000+4*2
e3173008 e3252000 00000000 00000000 00000000
...

因此第0级句柄表是0xe3252000
lkd> dd 0xe3252000+135*8
e32529a8 e15a4c31 00000010 00000000 000014b4
...

所以object body在0xe15a4c48:
lkd> !object 0xe15a4c48
Object: e15a4c48 Type: (823b47f0) Key
ObjectHeader: e15a4c30
HandleCount: 1 PointerCount: 1
Directory Object: 00000000 Name: /REGISTRY/MACHINE/SYSTEM/CONTROLSET001/SER
VICES/SHAREDACCESS/EPOCH

与!handle的输出也是一致的。

两级句柄表的就不举了,因为需要至少511*1023=522753以上个句柄才需要分配第2级的
句柄表,不愿意去试了,愿意的自己去试好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值