1,首先列举进程列表,随便选择一个查看的对象,这里以explorer.exe进程为对象。
kd> !process 0 0
PROCESS857f3960 SessionId: 1 Cid: 0a84 Peb: 7ffd4000 ParentCid: 0a54
DirBase: 1ec69440 ObjectTable: 93358af0 HandleCount: 781.
Image: explorer.exe
2,用!object命令查看对象信息。
kd> !object 857f3960
Object: 857f3960 Type: (8564b668) Process
ObjectHeader: 857f3948 (new version)
HandleCount: 6 PointerCount: 400
从输出信息,获取到对象头的地址。
3,接下来查看对象头的信息。
kd> dt nt!_object_header 857f3948
+0x000 PointerCount : 0n400
+0x004 HandleCount : 0n6
+0x004 NextToFree : 0x00000006 Void
+0x008 Lock : _EX_PUSH_LOCK
+0x00c TypeIndex : 0x7 ''
+0x00d TraceFlags : 0 ''
+0x00e InfoMask : 0x8 ''
+0x00f Flags : 0 ''
+0x010 ObjectCreateInfo : 0x873b8040 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x873b8040 Void
+0x014 SecurityDescriptor : 0x938d4a32 Void
+0x018 Body : _QUAD
win7以前的操作系统版本上,有个type域指明了_object_type的地址,而win7取而代之的是给出了一个typeIndex索引。既然是索引,必然有一个对应表。其实,这样反而简化了获取_object_type的方法。
4,查看系统全局的_object_type表,如下
kd> dd nt!obTypeIndexTable
82991900 00000000 bad0b0b0 8564bc30 8564bb68
82991910 8564baa0 8564b870 8564b730 8564b668
82991920 8564b5a0 8564b4d8 856e8040 856e89c0
82991930 85701978 85705508 856f7418 856f7350
82991940 856f8418 856f8350 856fa418 856fa350
82991950 85705f78 85705eb0 85705de8 856fbf78
82991960 856fbeb0 856fbde8 856fbd20 856fbc58
82991970 856fbb90 856fb6c8 856fb600 856fb538
其中obTypeIndexTable是全局变量数组。因为第3步中的typeIndex=0x7,从而间接获取到_object_type的地址,也就是表里对应的8564b668值(注意数组是以下标0开始的)。
5,查看_object_type结构信息
kd> dt nt!_object_type 8564b668
+0x000 TypeList : _LIST_ENTRY [ 0x8564b668 - 0x8564b668 ]
+0x008 Name : _UNICODE_STRING "Process"
+0x010 DefaultObject : (null)
+0x014 Index : 0x7 ''
+0x018 TotalNumberOfObjects : 0x24
+0x01c TotalNumberOfHandles : 0xd4
+0x020 HighWaterNumberOfObjects : 0x29
+0x024 HighWaterNumberOfHandles : 0xe7
+0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x078 TypeLock : _EX_PUSH_LOCK
+0x07c Key : 0x636f7250
+0x080 CallbackList : _LIST_ENTRY [ 0x8564b6e8 - 0x8564b6e8 ]
可以从Name字段看出,这是一个Process对象类型,当然,从winObj.exe工具也可以看出系统有process这样的对象类型。
其中,有一个关键域TypeInfo,所谓的很多object hook也就是在对这个域做文章,现在看看它的结构体内容。
6,查看_OBJECT_TYPE_INITIALIZER结构体信息
kd> dt nt!_OBJECT_TYPE_INITIALIZER 0x8564b668+28
+0x000 Length : 0x50
+0x002 ObjectTypeFlags : 0x4a 'J'
+0x002 CaseInsensitive : 0y0
+0x002 UnnamedObjectsOnly : 0y1
+0x002 UseDefaultObject : 0y0
+0x002 SecurityRequired : 0y1
+0x002 MaintainHandleCount : 0y0
+0x002 MaintainTypeList : 0y0
+0x002 SupportsObjectCallbacks : 0y1
+0x004 ObjectTypeCode : 0
+0x008 InvalidAttributes : 0xb0
+0x00c GenericMapping : _GENERIC_MAPPING
+0x01c ValidAccessMask : 0x1fffff
+0x020 RetainAccess : 0x101000
+0x024 PoolType : 0 ( NonPagedPool )
+0x028 DefaultPagedPoolCharge : 0x1000
+0x02c DefaultNonPagedPoolCharge : 0x2f0
+0x030 DumpProcedure : (null)
+0x034 OpenProcedure : 0x82a5eccb long nt!PspProcessOpen+0
+0x038 CloseProcedure : 0x82abed2e void nt!PspProcessClose+0
+0x03c DeleteProcedure : 0x82ac15f5 void nt!PspProcessDelete+0
+0x040 ParseProcedure : (null)
+0x044 SecurityProcedure : 0x82ab35b6 long nt!SeDefaultObjectMethod+0
+0x048 QueryNameProcedure : (null)
+0x04c OkayToCloseProcedure : (null)
其中,蓝色标注的字段是该对象类型所包含的固有方法,这些函数是可以部分HOOK的,从而达到一定的目的。
也就是说,windows的对象结构,包含了数据属性,同时也包含了必有的几个方法。对以上对象类型的方法进行HOOK,就称之为Object Hook。