注册 |登录

0GiNr技术社区论坛系统底层开发 › 查看主题

994

查看

4

回复
返回列表

Rank: 1

金钱
449 元 
经验
87 点 
威望
1 点 
贡献
0 点 
精华
go

关於Windows Handle与Object的解析机制

1
发表于 2010-2-1 21:03 | 只看该作者 | 倒序看帖 | 打印
凡本论坛原创内容,其作者享有著作权,未经许可谢绝转载。
最近因为某些原因,需要自己做Handle对Object的解析(ObReferenceObjectByHandle有ObjectType的问题),所以去网路上研究了Handle的运作机制
在这里整理出来跟大家分享

Handle和Object的对应是由一棵Tree来运作,Handle则表示了Tree每一层的Index,最後在树根就可以对应到Object
这里以Windows 7中的explorer.exe为例(每个作业系统稍有不同)

每个程序都有自己的Handle Tree(包括System),确保之间的Handle互相不会干扰
Handle Tree的相关资料纪录在HANDLE_TABLE结构中
EPROCESS中纪录着HANDLE_TABLE的位置
  1. +0x0ec DebugPort        :
  2.    +0x0f0 ExceptionPortData : 0x8e0aa658
  3.    +0x0f0 ExceptionPortValue : 0x8e0aa658
  4.    +0x0f0 ExceptionPortState : 0y000
  5.    +0x0f4 ObjectTable      : 0x914a9988 _HANDLE_TABLE
  6.    +0x0f8 Token            : _EX_FAST_REF
  7.    +0x0fc WorkingSetPage   : 0x25e54
  8.    +0x100 AddressCreationLock : _EX_PUSH_LOCK
  9.    +0x104 RotateInProgress :
  10.    +0x108 ForkInProgress   :
复制代码
进去HANDLE_TABLE看一下
  1. +0x000 TableCode        : 0x9be90001
  2.    +0x004 QuotaProcess     : 0x8e411750 _EPROCESS
  3.    +0x008 UniqueProcessId  : 0x0000058c
  4.    +0x00c HandleLock       : _EX_PUSH_LOCK
  5.    +0x010 HandleTableList  : _LIST_ENTRY [ 0x95a78ef8 - 0x95a7e898 ]
  6.    +0x018 HandleContentionEvent : _EX_PUSH_LOCK
  7.    +0x01c DebugInfo        : (null)
  8.    +0x020 ExtraInfoPages   : 0
  9.    +0x024 Flags            : 0
  10.    +0x024 StrictFIFO       : 0y0
  11.    +0x028 FirstFreeHandle  : 0xad4
  12.    +0x02c LastFreeHandleEntry : 0x9be91ff8 _HANDLE_TABLE_ENTRY
  13.    +0x030 HandleCount      : 0x2b3
  14.    +0x034 NextHandleNeedingPool : 0x1000
  15.    +0x038 HandleCountHighWatermark : 0x2be
复制代码
我们想知道的Handle Tree位置就纪录在TableCode中,但TableCode的功能不只纪录Handle Tree位置,事实上它的低2bit纪录着Handle Tree的层数
Handle Tree最多有三层,最少一层,由於Handle Tree的位置永远为4的倍数,所以TableCode的低2bit可以空出来
我们发现TableCode的低2bit为1,代表Handle Tree有2层。实际上Handle Tree的位置为0x9be90000(忽略低2bit)

看一下0x9be90000的东西
  1. kd> dd 0x9be90000
  2. 9be90000  95a38000 9be91000 00000000 00000000
  3. 9be90010  00000000 00000000 00000000 00000000
  4. 9be90020  00000000 00000000 00000000 00000000
  5. 9be90030  00000000 00000000 00000000 00000000
  6. 9be90040  00000000 00000000 00000000 00000000
  7. 9be90050  00000000 00000000 00000000 00000000
  8. 9be90060  00000000 00000000 00000000 00000000
  9. 9be90070  00000000 00000000 00000000 00000000
复制代码
纪录着两个位置0x95a38000和0x9be91000

其实Handle Tree的三层是这样定义的
最低层定义为一个HANDLE_TABLE_ENTRY的阵列,共有512个
中间层定义为一个ULONG的阵列,共2048个,每个元素存着一个位址,指向一个最低层阵列
最高层也是个ULONG阵列,共32个,每个元素存着一个位址,指向一个中间层阵列

如果TableCode的低2bit为0,代表只有一层,那麽TableCode便指向最低层阵列
如果低2bit为1,那麽TableCode便指向中间层阵列
如果低2bit为1,那麽TableCode便指向最高层阵列

从上面来看,由於是中间层,0x95a38000和0x9be91000这两个位置便分别指向两个HANDLE_TABLE_ENTRY的阵列(最低层阵列)

我们来看0x95a38000最低层阵列中的第一项
  1. kd> dt _HANDLE_TABLE_ENTRY 95a38000
  2. nt!_HANDLE_TABLE_ENTRY
  3.    +0x000 Object           : (null)
  4.    +0x000 ObAttributes     : 0
  5.    +0x000 InfoTable        : (null)
  6.    +0x000 Value            : 0
  7.    +0x004 GrantedAccess    : 0xfffffffe
  8.    +0x004 GrantedAccessIndex : 0xfffe
  9.    +0x006 CreatorBackTraceIndex : 0xffff
  10.    +0x004 NextFreeTableEntry : 0xfffffffe
复制代码
我们发现他什麽都没有,其实最低层阵列中的第一项永远是无效的,所以我们来看第二项
  1. kd> dt _HANDLE_TABLE_ENTRY 95a38000+8
  2. nt!_HANDLE_TABLE_ENTRY
  3.    +0x000 Object           : 0x953351f9
  4.    +0x000 ObAttributes     : 0x953351f9
  5.    +0x000 InfoTable        : 0x953351f9 _HANDLE_TABLE_ENTRY_INFO
  6.    +0x000 Value            : 0x953351f9
  7.    +0x004 GrantedAccess    : 3
  8.    +0x004 GrantedAccessIndex : 3
  9.    +0x006 CreatorBackTraceIndex : 0
  10.    +0x004 NextFreeTableEntry : 3
复制代码
第二项就有些东西了
其中Object栏位的值就是指向我们想知道的Object Header,由於Object在内核建立时,位置永远为4的倍数,所以低2bit要忽略掉(这低2bit是用来作为标示该Object的属性)
0x953351f9去掉低2bit为0x953351F8。注意,0x953351F8不是指向Object本身,而是Object Header,要再加0x18的偏移才是Object本身,所以真正Object位址为0x95335210
  1. kd> !object  95335210
  2. Object: 95335210  Type: (8c5b3820) Directory
  3.     ObjectHeader: 953351f8 (new version)
  4.     HandleCount: 28  PointerCount: 66
  5.     Directory Object: 8fe01120  Name: KnownDlls
复制代码
另外有些HANDLE_TABLE_ENTRY中的Object栏位为null,这代表该HANDLE_TABLE_ENTRY还没有被使用(Handle还没被使用),它的NextFreeTableEntry栏位存着下一个空的HANDLE_TABLE_ENTRY的Handle,方便Widnows要新增Handle,可以快速的找到下一个没使用Handle

这边提到了Handle和HANDLE_TABLE_ENTRY的关系,他们的关系是
Handle其实是个ULONG,他的第2-10的bit储存着最低层阵列的Index
第11-20的bit储存中间层阵列的Index
第21-25个bit储存最高层阵列的Index
低2bit则直接忽略掉

例如explorer.exe中的0xa9c这个Handle
  1. 000000  |  00000  |  0000000001  |  010100111  |  00
  2.              ^            ^             ^
  3.        最高層Index  中間層Index      最低層Index
复制代码
由於explorer.exe的Handle Tree只有2层,所以最高层Index直接忽略
中间层的Index为0x1,最低层Index为0xA7,根据下表,最低层阵列位址应为0x9be91000
  1. kd> dd 0x9be90000
  2. 9be90000  95a38000 9be91000 00000000 00000000
  3. 9be90010  00000000 00000000 00000000 00000000
  4. 9be90020  00000000 00000000 00000000 00000000
  5. 9be90030  00000000 00000000 00000000 00000000
  6. 9be90040  00000000 00000000 00000000 00000000
  7. 9be90050  00000000 00000000 00000000 00000000
  8. 9be90060  00000000 00000000 00000000 00000000
  9. 9be90070  00000000 00000000 00000000 00000000
复制代码
我们来看最低层阵列0x9be91000中的0xA7项
  1. kd> dt _HANDLE_TABLE_ENTRY 9be91000+(0xA7*8)
  2. nt!_HANDLE_TABLE_ENTRY
  3.    +0x000 Object           : 0x9bf8a3c1
  4.    +0x000 ObAttributes     : 0x9bf8a3c1
  5.    +0x000 InfoTable        : 0x9bf8a3c1 _HANDLE_TABLE_ENTRY_INFO
  6.    +0x000 Value            : 0x9bf8a3c1
  7.    +0x004 GrantedAccess    : 0x10
  8.    +0x004 GrantedAccessIndex : 0x10
  9.    +0x006 CreatorBackTraceIndex : 0
  10.    +0x004 NextFreeTableEntry : 0x10
复制代码
处理Object栏位的值後,最後得到真正的Object位址为0x9BF8A3D8
  1. kd> !object 9BF8A3D8
  2. Object: 9bf8a3d8  Type: (8c65cb10) Key
  3.     ObjectHeader: 9bf8a3c0 (new version)
  4.     HandleCount: 1  PointerCount: 1
  5.     Directory Object: 00000000  Name: \REGISTRY\MACHINE\SOFTWARE\MICROSOFT\WINDOWS\CURRENTVERSION\HOMEGROUP\SHARINGINPROGRESS
复制代码
下面的小程式是我做Handle解析所写得程式,取的HANDLE_TABLE是System的
  1. ULONG HighLevelTableIndex;
  2.         ULONG MidLevelTableIndex;
  3.         ULONG LowLevelTableIndex;

  4.         PVOID pHandleTable;
  5.         ULONG TableCode;
  6.         PULONG pHighLevelTable;
  7.         PULONG pMidLevelTable;
  8.         PHANDLE_TABLE_ENTRY pLowLevelTable;
  9.         ULONG HandleValue;

  10.         HighLevelTableIndex=((ULONG)Handle & 0x3e00000)/0x200000;
  11.         MidLevelTableIndex=((ULONG)Handle & 0x1ff800)/0x800;
  12.         LowLevelTableIndex=((ULONG)Handle & 0x7fc)/0x4;

  13.         pHandleTable=(PVOID)*(PULONG)((ULONG)PsInitialSystemProcess+EPROCESS_ObjectTable);
  14.         TableCode=*(PULONG)pHandleTable;
  15.         switch(TableCode & 3){
  16.                 case 0:
  17.                         pLowLevelTable=(PHANDLE_TABLE_ENTRY)(TableCode & 0xfffffffc);
  18.                         *pObject=(PVOID)(((ULONG)pLowLevelTable[LowLevelTableIndex].Object & 0xfffffff8)-OBJECT_HEADER_OFFSET);

  19.                         break;
  20.                 case 1:
  21.                         pMidLevelTable=(PULONG)(TableCode & 0xfffffffc);
  22.                         pLowLevelTable=(PHANDLE_TABLE_ENTRY)pMidLevelTable[MidLevelTableIndex];
  23.                         *pObject=(PVOID)(((ULONG)pLowLevelTable[LowLevelTableIndex].Object & 0xfffffff8)-OBJECT_HEADER_OFFSET);

  24.                         break;
  25.                 case 2:
  26.                         pHighLevelTable=(PULONG)(TableCode & 0xfffffffc);
  27.                         pMidLevelTable=(PULONG)pHighLevelTable[HighLevelTableIndex];
  28.                         pLowLevelTable=(PHANDLE_TABLE_ENTRY)pMidLevelTable[MidLevelTableIndex];
  29.                         *pObject=(PVOID)(((ULONG)pLowLevelTable[LowLevelTableIndex].Object & 0xfffffff8)-OBJECT_HEADER_OFFSET);

  30.                         break;
  31.                 default:
  32.                         return STATUS_UNSUCCESSFUL;

  33.                         break;
  34.         }

  35.         return STATUS_SUCCESS;
复制代码
    • FlowerCode: 支持原创金钱 + 240 元 威望 + 1 点

TOP

0GiNr核心团队

论坛管理员

Rank: 12Rank: 12

金钱
10491 元 
经验
10357 点 
威望
205 点 
贡献
17 点 
精华

技术高手

2
发表于 2010-2-1 23:41 | 只看该作者
我承认我看到了0x9XXXXXXX以为是用户态地址

TOP

大牛

PH The Great

Rank: 4Rank: 4

金钱
1493 元 
经验
808 点 
威望
40 点 
贡献
13 点 
精华
3
发表于 2010-2-2 13:50 | 只看该作者
惊现台湾同胞!这个看起来就是句柄表的解析,想起了SD的PSPCIDTABLE解读

TOP

Rank: 3

金钱
315 元 
经验
247 点 
威望
25 点 
贡献
0 点 
精华
4
发表于 2010-2-2 23:29 | 只看该作者
台湾同胞?

TOP

Rank: 1

金钱
244 元 
经验
30 点 
威望
3 点 
贡献
0 点 
精华
5
发表于 2010-2-5 17:16 | 只看该作者
3维稀疏矩阵

TOP

0GiNr安全门户 |联系我们

GMT+8, 2010-9-7 20:36.

Powered by Discuz! X1

© 2001-2010 Comsenz Inc.