遍历系统的所有ObjectType和TypeIndex
Windows内部有很多的对象类型,比如PROCESS类型,THREAD类型,FILE类型,LPC PORT类型,DEVICE类型等等,我们可以使用sysinternal提供的winobj工具来查看(win7 x86 sp1)
在编程的过程中我们有时候需要用到类型的索引(TypeIndex),由于在不同的操作系统版本中TypeIndex会发生改变,本文将教大家一种方法来遍历这些类型还有其相应的TypeIndex
首先要知道类型也是一种对象,同样它也有OBJECT HEADER,OBJECT BODY等信息,是通过OBJECT MANAGER对象管理器来管理的
在这些类型对象当中有一个非常重要的对象,叫做Type对象,这是系统中第一个被初始化的类型对象(可称之为“元类型”),系统中其他的类型对象都是通过这个特殊的“元类型”对象来创建的
那么这些类型对象是放在什么地方又是通过什么样的关系组织起来的呢?
我们之前说过类型也是一种对象,它的OBJECT BODY其实是nt!_object_type,用windbg dt查看一下(win7 x86 sp1)
其中的第一个数据成员是TypeList,对象是不是就是通过这个TypeList连接起来的呢?
通过查阅ReactOS中的ObCreateObjectType中的实现,发下了如下的代码
原来正是通过CreateInfo中的TypeList来链接起所有的类型对象,而这个链表的头结点就是ObpTypeObjectType,其实就是“元类型”对象
CreateInfo的数据结构是nt!_OBJECT_HEADER_CREATOR_INFO,里面果真有个TypeList
因此如果要遍历所有的类型对象的话只要找到这个表的表头即可,那么表头ObpTypeObjectType怎么找呢?这里介绍两种方法
- 通过前面<<获取操作系统的内核基地址>>文章中提到的KdVersionBlock--〉_KDDEBUGGER_DATA64—>ObpTypeObjectType,这是最省心的办法了
- 通过特征码来搜索ObCreateObjectType函数找到ObpTypeObjectType,XPSP3下搜索35ff,53,win7 x86 sp1下搜索a1和bb
第一种方法不需要特征码比较的简单这里就不再介绍了,下面着重介绍第二种方法,经常看到有文章介绍如何通过特征码来搜索未导出的函数或者变量,初学者都会感到困惑,今天我就来为大家解惑解惑~
首先我们需要的ObpTypeObjectType在ObCreateObjectType中被调用到,我们反汇编一下这个函数,uf ObCreateObjectType(下面如果未特别说明,就表示是win7 x86 sp1的环境)
kd> uf ObCreateObjectType nt!ObCreateObjectType: 829aff6a 8bff mov edi,edi 829aff6c 55 push ebp 829aff6d 8bec mov ebp,esp 829aff6f ff7514 push dword ptr [ebp+14h] 829aff72 6a00 push 0 829aff74 ff750c push dword ptr [ebp+0Ch] 829aff77 ff7508 push dword ptr [ebp+8] 829aff7a e809000000 call nt!ObCreateObjectTypeEx (829aff88) 829aff7f 5d pop ebp 829aff80 c21000 ret 10h
里面还调用了nt!ObCreateObjectTypeEx,我们再反汇编一下这个函数,uf ObCreateObjectTypeEx,这个函数反汇编后的结果比较长,我们在反汇编窗口中Ctrl+F搜索一下ObpTypeObjectType,定位到下面片段
nt!ObCreateObjectTypeEx+0x277: 829b01ff 668b4302 mov ax,word ptr [ebx+2] 829b0203 668944242e mov word ptr [esp+2Eh],ax 829b0208 53 push ebx 829b0209 8d442430 lea eax,[esp+30h] 829b020d 50 push eax 829b020e e8fd01f3ff call nt!RtlCopyUnicodeString (828e0410) 829b0213 a154a79782 mov eax,dword ptr [nt!ObpTypeObjectType (8297a754)]
829b0218 bb88000000 mov ebx,88h
829b021d 85c0 test eax,eax
829b021f 7404 je nt!ObCreateObjectTypeEx+0x29d (829b0225)
看到没,在地址829b0213中的机器码为a154a79782,后面四个字节的机器码就是ObpTypeObjectType的地址(小端机器所以顺序是倒着过来的),因此我们通过搜索函数中a1和bb特征码来唯一的定位到这个地址即可~
搜索的起始位置就是ObCreateObjectType,这个函数的地址可以通过MmGetSystemRoutineAddress来得到,下面截图一下代码,为的是让大家自己敲代码来寻找,加深理解
会了的话再去试着找XP下的地址,看结果对不对就去比较上面方法1中KdVersionBlock--〉_KDDEBUGGER_DATA64—>ObpTypeObjectType得到的地址
同样的有很多人想去解析PspCidTable句柄表,这个地址的获取也可以利用上面的两种方法
好了,转入正题,现在我们知道了ObpTypeObjectType的地址,那么TypeObjectType(“元类型”)的地址就是
*(PULONG_PTR)ObpTypeObjectType
我们利用dt一下这个地址
kd> dd ObpTypeObjectType 8297a754 84f48f58 00000000 00000000 84f48f58 8297a764 84f48e90 84f48dc8 84f48b80 84f48a40 8297a774 84f48978 84f488b0 84f43c18 84f43b50 8297a784 84f434d0 84ff4b60 84ff4890 84ff0300 8297a794 84ff0140 84ff07b0 84ff4380 84fe5408 8297a7a4 84fe5340 84fe2418 84fe2350 84fe3418 8297a7b4 84fe3350 84fe6040 84fe6f78 84fe6eb0 8297a7c4 84fe6de8 84fe6d20 84fe6858 84fe6790 kd> dt _object_type 84f48f58 ntdll!_OBJECT_TYPE +0x000 TypeList : _LIST_ENTRY [ 0x84f48f30 - 0x85676310 ] +0x008 Name: _UNICODE_STRING "Type"
+0x010 DefaultObject : 0x8297a860 Void
+0x014Index: 0x2''
+0x018 TotalNumberOfObjects : 0x2a +0x01c TotalNumberOfHandles : 0 +0x020 HighWaterNumberOfObjects : 0x2a +0x024 HighWaterNumberOfHandles : 0 +0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER +0x078 TypeLock : _EX_PUSH_LOCK +0x07c Key : 0x546a624f +0x080 CallbackList : _LIST_ENTRY [ 0x84f48fd8 - 0x84f48fd8 ]
发现它的名字为Type,Index为2
然后再寻找它的OBJECT_HEADER_CREATOR_INFO结构,这个结构在BODY的上方,winxp & win7下这个偏移量都是0x28
-----------------------------------------------high address
object body
-----------------------------------------------
object header
----------------------------------------------
object_header_creator_info
----------------------------------------------low address
因为有些对象不一定有CreatorInfo,NameInfo,HandleInfo等可选附加信息,看了一下windows internals里面说到object type是肯定有CreatorInfo结构,这下就放心了~
下面放出遍历整个系统类型对象和TypeIndex的代码(win7 x86 sp1 & winxp sp3,如果不是这两种系统的话请慎重)
#include <ntddk.h> DRIVER_INITIALIZE DriverEntry; DRIVER_UNLOAD DriverUnload; ULONG OffsetObjectTypeName; ULONG OffsetCreatorInfoObject; ULONG OffsetObjectIndexObjectType; POBJECT_TYPE ObpTypeObjectType; VOID DriverUnload(PDRIVER_OBJECT Driver) { DbgPrint("Driver Unload!\n"); } POBJECT_TYPE GetObpTypeObjectType_WinXP() { PUCHAR addr,p; UNICODE_STRING usObCreateObjectType; POBJECT_TYPE _ObpTypeObjectType=NULL; RtlInitUnicodeString(&usObCreateObjectType,L"ObCreateObjectType"); addr=MmGetSystemRoutineAddress(&usObCreateObjectType); ASSERT(addr!=NULL); DbgPrint("ObCreateObjectType=0x%08x\n",addr); for (p=addr;p<addr+PAGE_SIZE;p++) { if ((*(PUSHORT)p==0x35ff) && (*(PUCHAR)(p+6)==0x53)) { ObpTypeObjectType=(POBJECT_TYPE)(*(PULONG)(p+2)); DbgPrint("ObpTypeObjectType=0x%08x\n",_ObpTypeObjectType); return _ObpTypeObjectType; } } if (p==addr+PAGE_SIZE) DbgPrint("Cannot find ObpTypeObjectType!\n"); return NULL; } POBJECT_TYPE GetObpTypeObjectType_Win7() { PUCHAR addr,p; UNICODE_STRING usObCreateObjectType; POBJECT_TYPE _ObpTypeObjectType=NULL; RtlInitUnicodeString(&usObCreateObjectType,L"ObCreateObjectType"); addr=MmGetSystemRoutineAddress(&usObCreateObjectType); ASSERT(addr!=NULL); DbgPrint("ObCreateObjectType=0x%08x\n",addr); for (p=addr;p<addr+PAGE_SIZE;p++) { if ((*(PUCHAR)p==0xa1) && (*(PUCHAR)(p+5)==0xbb)) { _ObpTypeObjectType=(POBJECT_TYPE)(*(PULONG)(p+1)); DbgPrint("ObpTypeObjectType=0x%08x\n",_ObpTypeObjectType); return _ObpTypeObjectType; } } if (p==addr+PAGE_SIZE) DbgPrint("Cannot find ObpTypeObjectType!\n"); return NULL; } NTSTATUS DriverEntry(PDRIVER_OBJECT Driver,PUNICODE_STRING RegPath) { NTSTATUS status=STATUS_SUCCESS; ULONG_PTR TypeObjectAddr; PLIST_ENTRY TypeObjectCreatorInfo; PLIST_ENTRY NextEntry; RTL_OSVERSIONINFOW VersionInformation; status=RtlGetVersion(&VersionInformation); if(!NT_SUCCESS(status)) { DbgPrint("PsGetVersion failed,error=0x%08x\n",status); return STATUS_UNSUCCESSFUL; } if (VersionInformation.dwMajorVersion==6)//win7 { OffsetObjectTypeName=0x08; OffsetCreatorInfoObject=0x28; OffsetObjectIndexObjectType=0x14; ObpTypeObjectType=GetObpTypeObjectType_Win7(); } else{//winxp OffsetObjectTypeName=0x40; OffsetCreatorInfoObject=0x28; OffsetObjectIndexObjectType=0x4c; ObpTypeObjectType=GetObpTypeObjectType_WinXP(); } TypeObjectAddr=*(PULONG_PTR)ObpTypeObjectType; TypeObjectCreatorInfo=(PLIST_ENTRY)(TypeObjectAddr-OffsetCreatorInfoObject); NextEntry=TypeObjectCreatorInfo; while (NextEntry->Flink!=TypeObjectCreatorInfo) { DbgPrint("TypeAddr=0x%08x,TypeName=%wZ,TypeIndex=%d\n", (ULONG_PTR)NextEntry+OffsetCreatorInfoObject, (PUNICODE_STRING)((ULONG_PTR)NextEntry+OffsetCreatorInfoObject+OffsetObjectTypeName), *(PUCHAR)((ULONG_PTR)NextEntry+OffsetCreatorInfoObject+OffsetObjectIndexObjectType)); NextEntry=NextEntry->Flink; } Driver->DriverUnload=DriverUnload; return status; }
win7 x86 sp1的结果如下
ObCreateObjectType=0x829aff6a ObpTypeObjectType=0x8297a754 TypeAddr=0x84f48f58,TypeName=Type,TypeIndex=2 TypeAddr=0x84f48e90,TypeName=Directory,TypeIndex=3 TypeAddr=0x84f48dc8,TypeName=SymbolicLink,TypeIndex=4 TypeAddr=0x84f48b80,TypeName=Token,TypeIndex=5 TypeAddr=0x84f48a40,TypeName=Job,TypeIndex=6 TypeAddr=0x84f48978,TypeName=Process,TypeIndex=7 TypeAddr=0x84f488b0,TypeName=Thread,TypeIndex=8 TypeAddr=0x84f43c18,TypeName=UserApcReserve,TypeIndex=9 TypeAddr=0x84f43b50,TypeName=IoCompletionReserve,TypeIndex=10 TypeAddr=0x84f434d0,TypeName=DebugObject,TypeIndex=11 TypeAddr=0x84ff4b60,TypeName=Event,TypeIndex=12 TypeAddr=0x84ff4890,TypeName=EventPair,TypeIndex=13 TypeAddr=0x84ff0300,TypeName=Mutant,TypeIndex=14 TypeAddr=0x84ff0140,TypeName=Callback,TypeIndex=15 TypeAddr=0x84ff07b0,TypeName=Semaphore,TypeIndex=16 TypeAddr=0x84ff4380,TypeName=Timer,TypeIndex=17 TypeAddr=0x84fe5408,TypeName=Profile,TypeIndex=18 TypeAddr=0x84fe5340,TypeName=KeyedEvent,TypeIndex=19 TypeAddr=0x84fe2418,TypeName=WindowStation,TypeIndex=20 TypeAddr=0x84fe2350,TypeName=Desktop,TypeIndex=21 TypeAddr=0x84fe3418,TypeName=TpWorkerFactory,TypeIndex=22 TypeAddr=0x84fe3350,TypeName=Adapter,TypeIndex=23 TypeAddr=0x84fe6040,TypeName=Controller,TypeIndex=24 TypeAddr=0x84fe6f78,TypeName=Device,TypeIndex=25 TypeAddr=0x84fe6eb0,TypeName=Driver,TypeIndex=26 TypeAddr=0x84fe6de8,TypeName=IoCompletion,TypeIndex=27 TypeAddr=0x84fe6d20,TypeName=File,TypeIndex=28 TypeAddr=0x84fe6858,TypeName=TmTm,TypeIndex=29 TypeAddr=0x84fe6790,TypeName=TmTx,TypeIndex=30 TypeAddr=0x84fe66c8,TypeName=TmRm,TypeIndex=31 TypeAddr=0x84fe6600,TypeName=TmEn,TypeIndex=32 TypeAddr=0x84fe6430,TypeName=Section,TypeIndex=33 TypeAddr=0x84feef78,TypeName=Session,TypeIndex=34 TypeAddr=0x84feb8b8,TypeName=Key,TypeIndex=35 TypeAddr=0x84fe7ee0,TypeName=ALPC Port,TypeIndex=36 TypeAddr=0x84fe7630,TypeName=PowerRequest,TypeIndex=37 TypeAddr=0x84ff1e18,TypeName=WmiGuid,TypeIndex=38 TypeAddr=0x84ff1360,TypeName=EtwRegistration,TypeIndex=39 TypeAddr=0x84ff1298,TypeName=EtwConsumer,TypeIndex=40 TypeAddr=0x85dff150,TypeName=FilterConnectionPort,TypeIndex=41 TypeAddr=0x851424d0,TypeName=FilterCommunicationPort,TypeIndex=42 TypeAddr=0x85676338,TypeName=PcwObject,TypeIndex=43
winxp sp3的结果如下
ObCreateObjectType=0x805c5ea6 ObpTypeObjectType=0x80568c70 TypeAddr=0x867e9580,TypeName=Type,TypeIndex=1 TypeAddr=0x867e93b0,TypeName=Directory,TypeIndex=2 TypeAddr=0x867e91e0,TypeName=SymbolicLink,TypeIndex=3 TypeAddr=0x867b5040,TypeName=Token,TypeIndex=4 TypeAddr=0x867b5e70,TypeName=Process,TypeIndex=5 TypeAddr=0x867b5ca0,TypeName=Thread,TypeIndex=6 TypeAddr=0x867b5ad0,TypeName=Job,TypeIndex=7 TypeAddr=0x867b5408,TypeName=DebugObject,TypeIndex=8 TypeAddr=0x867b2980,TypeName=Event,TypeIndex=9 TypeAddr=0x867b27b0,TypeName=EventPair,TypeIndex=10 TypeAddr=0x867b25e0,TypeName=Mutant,TypeIndex=11 TypeAddr=0x867b2410,TypeName=Callback,TypeIndex=12 TypeAddr=0x867b1040,TypeName=Semaphore,TypeIndex=13 TypeAddr=0x867b1e70,TypeName=Timer,TypeIndex=14 TypeAddr=0x867b1ca0,TypeName=Profile,TypeIndex=15 TypeAddr=0x867b1ad0,TypeName=KeyedEvent,TypeIndex=16 TypeAddr=0x867b1900,TypeName=WindowStation,TypeIndex=17 TypeAddr=0x867b1730,TypeName=Desktop,TypeIndex=18 TypeAddr=0x867b1418,TypeName=Section,TypeIndex=19 TypeAddr=0x867ab5f8,TypeName=Key,TypeIndex=20 TypeAddr=0x867e8078,TypeName=Port,TypeIndex=21 TypeAddr=0x8679e040,TypeName=WaitablePort,TypeIndex=22 TypeAddr=0x8679e6c8,TypeName=Adapter,TypeIndex=23 TypeAddr=0x8679e4f8,TypeName=Controller,TypeIndex=24 TypeAddr=0x8679e328,TypeName=Device,TypeIndex=25 TypeAddr=0x867e7040,TypeName=Driver,TypeIndex=26 TypeAddr=0x867e7e70,TypeName=IoCompletion,TypeIndex=27 TypeAddr=0x867e7ca0,TypeName=File,TypeIndex=28 TypeAddr=0x86799250,TypeName=WmiGuid,TypeIndex=29 TypeAddr=0x864082d8,TypeName=FilterConnectionPort,TypeIndex=30 TypeAddr=0x8626e040,TypeName=FilterCommunicationPort,TypeIndex=31
学会了这种方法,以后就不怕系统的变化导致获取不到相应的TypeIndex
BTW:系统内部还有个ObpObjectTypes的数组,存放的时所有类型对象的地址,不过没有导出,请问这个要怎么去获取?