Windows对象(Object)结构--关于Win7的补充

Windows对象(Object)结构--关于Win7的补充


自Window 7开始,_OBJECT_HEADER及其之前的一些结构发生了变化。首先来对比下Win7与XP的_OBJECT_HEADER:


[Windows 7]
0: kd> dt _object_header
nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : UChar
   +0x00d TraceFlags       : UChar
   +0x00e InfoMask         : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void
   +0x018 Body             : _QUAD

 

[Windows XP sp3]
kd> dt _object_header
nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Type             : Ptr32 _OBJECT_TYPE
   +0x00c NameInfoOffset   : UChar
   +0x00d HandleInfoOffset : UChar
   +0x00e QuotaInfoOffset  : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void
   +0x018 Body             : _QUAD

 

可以看到,+0x008处的指向_OBJECT_TYPE的指针已经没有了,取而代之的是在+0x00c处的类型索引值。
“Vista及其以下版本都是在_object_header结构中保存object_type指针,在Windows7中Object_header只保存Object_type的索引。但Windows7中添加了一个函数,ObGetObjectType,返回Object_type对象指针,所以操作Object_type不需要硬编码了。

NTKERNELAPI
PVOID
NTAPI
ObGetObjectType(
      IN PVOID pObject
      );
”(见看雪论坛langouster对某贴的回复

来看看这个函数:
0: kd> u ObGetObjectType
nt!ObGetObjectType:
83e4f3f6 8bff            mov     edi,edi
83e4f3f8 55              push    ebp
83e4f3f9 8bec            mov     ebp,esp
83e4f3fb 8b4508          mov     eax,dword ptr [ebp+8]
83e4f3fe 0fb640f4        movzx   eax,byte ptr [eax-0Ch]
83e4f402 8b0485c0b8d483  mov     eax,dword ptr nt!ObTypeIndexTable (83d4b8c0)[eax*4]
83e4f409 5d              pop     ebp
83e4f40a c20400          ret     4

实际上就是一个全局数组nt!ObTypeIndexTable保存了所有的对象类型的指针。

另一个重要的变化:
Win7的_OBJECT_HEADER不再有NameInfoOffset、HandleInfoOffset和QuotaInfoOffset来指示从_POOL_HEADER到_OBJECT_HEADER这一段神秘的可变长空间。占据这三个偏移位置的三个成员分别为:TypeIndex、TraceFlags和InfoMask。TypeIndex上文已经说明,TraceFlags目前作用未知,以后搞明白了再补充吧。下面研究InfoMask的作用。为了方便起见,选取了Win7的explorer的进程对象和文件对象作为参考。
0: kd> dt _eprocess 860fed10  
nt!_EPROCESS
   ...
   +0x16c ImageFileName    : [15]  "explorer.exe"
   ...
0: kd> dt _file_object 86952ec8
nt!_FILE_OBJECT
   ...
   +0x030 FileName         : _UNICODE_STRING "Windowsexplorer.exe"
   ...

通过观察内存,找到了他们的_POOL_HEADER(_POOL_HEADER/_OBJECT_HEADER
0: kd> dd 860fed10-30
860fece0  045e000a e36f7250 00001000 000002f0
860fecf0  00000078 86b2d200 00000195 00000006
860fed00  00000000 00080007 86b2d200 89588b65
860fed10  00260003 00000000 860fed18 860fed18
860fed20  860fed20 860fed20 1ecf9360 00000000
860fed30  00000000 00000000 00000000 86d91210
860fed40  85aa6340 00000000 00010001 00000000
860fed50  00000003 860fed54 860fed54 00000000
0: kd> dd 86952ec8-38
86952e90  0417001f e56c6946 00000400 000000f8
86952ea0  00000000 00000000 92f6f8a0 00000001
86952eb0  00000007 00000000 00000000 000c001c
86952ec0  00000001 00000000 00800005 86186030
86952ed0  86186c50 92f909f8 92f6d490 86953fa8
86952ee0  00000000 00000000 00000000 00010000
86952ef0  01000100 00044042 0038002a 92f76b48
86952f00  00000000 00000000 00000000 00000000

可变长区域内的结构都以_OBJECT_HEADER_开头,所以我们可以先看看Win7下使用了哪些结构:
0: kd> dt nt!_object_header*
          ntkrpamp!_OBJECT_HEADER
          ntkrpamp!_OBJECT_HEADER_QUOTA_INFO
          ntkrpamp!_OBJECT_HEADER_PROCESS_INFO
          ntkrpamp!_OBJECT_HEADER_HANDLE_INFO
          ntkrpamp!_OBJECT_HEADER_NAME_INFO
          ntkrpamp!_OBJECT_HEADER_CREATOR_INFO

0: kd> dt _OBJECT_HEADER_QUOTA_INFO
nt!_OBJECT_HEADER_QUOTA_INFO
   +0x000 PagedPoolCharge  : Uint4B
   +0x004 NonPagedPoolCharge : Uint4B
   +0x008 SecurityDescriptorCharge : Uint4B
   +0x00c SecurityDescriptorQuotaBlock : Ptr32 Void

0: kd> dt _OBJECT_HEADER_PROCESS_INFO
nt!_OBJECT_HEADER_PROCESS_INFO
   +0x000 ExclusiveProcess : Ptr32 _EPROCESS
   +0x004 Reserved         : Uint4B

0: kd> dt _OBJECT_HEADER_HANDLE_INFO -b
nt!_OBJECT_HEADER_HANDLE_INFO
   +0x000 HandleCountDataBase : Ptr32 
   +0x000 SingleEntry      : _OBJECT_HANDLE_COUNT_ENTRY
      +0x000 Process          : Ptr32 
      +0x004 HandleCount      : Pos 0, 24 Bits
      +0x004 LockCount        : Pos 24, 8 Bits

0: kd> dt _OBJECT_HEADER_NAME_INFO
nt!_OBJECT_HEADER_NAME_INFO
   +0x000 Directory        : Ptr32 _OBJECT_DIRECTORY
   +0x004 Name             : _UNICODE_STRING
   +0x00c ReferenceCount   : Int4B

0: kd> dt _OBJECT_HEADER_CREATOR_INFO
nt!_OBJECT_HEADER_CREATOR_INFO
   +0x000 TypeList         : _LIST_ENTRY
   +0x008 CreatorUniqueProcess : Ptr32 Void
   +0x00c CreatorBackTraceIndex : Uint2B
   +0x00e Reserved         : Uint2B

观察对比后的,感觉应该是这样的:

0: kd> dd 860fed10-30
860fece0  045e000a e36f7250 00001000 000002f0
860fecf0  00000078 86b2d200 00000195 00000006
860fed00  00000000 00080007 86b2d200 89588b65
860fed10  00260003 00000000 860fed18 860fed18
860fed20  860fed20 860fed20 1ecf9360 00000000
860fed30  00000000 00000000 00000000 86d91210
860fed40  85aa6340 00000000 00010001 00000000
860fed50  00000003 860fed54 860fed54 00000000
0: kd> dd 86952ec8-38
86952e90  0417001f e56c6946 00000400 000000f8
86952ea0  00000000 00000000 92f6f8a0 00000001
86952eb0  00000007 00000000 00000000 000c001c
86952ec0  00000001 00000000 00800005 86186030
86952ed0  86186c50 92f909f8 92f6d490 86953fa8
86952ee0  00000000 00000000 00000000 00010000
86952ef0  01000100 00044042 0038002a 92f76b48
86952f00  00000000 00000000 00000000 00000000

 

结构算是都硬套上了。现在来猜测一下InfoMask与这些结构的对应关系。
860fed10(_EPROCESS)的InfoMask为:0x8 = 1000b
86952ec8(_FILE_OBJECT)的InfoMask为:0xc = 1100b
那么我们可以:
#define OB_INFOMASK_QUOTA    0x8
#define OB_INFOMASK_HANDLE   0x4

同样方法,分析其他类型的内核对象得到:
#define OB_INFOMASK_NAME      0x2
#define OB_INFOMASK_PROCESS 0x1

_OBJECT_HEADER_CREATOR_INFO结构仍然由+0x00f Flags指示,故没有对应掩码。

 

阅读更多
换一批

没有更多推荐了,返回首页