WinXp、Win7获取系统ObjectType和TypeIndex

Windows C/C++ 浅灬笑 3221℃ 0评论

本文转载自:http://www.cnblogs.com/unixstudio/archive/2012/11/09/2762906.html

通过ObjectType遍历_OBJECT_TYPE的原理

在使用ObjectType对_OBJECT_TYPE进行遍历的时候,应当首先找到ObpTypeObjectType这个变量的位置,这个变量是一个_OBJECT_TYPE对象。

紧邻着_OBJECT_TYPE之上有一个_OBJECT_HEADER结构,紧邻着_OBJECT_HEADER之上有一个_OBJECT_HEADER_CREATOR_INFO结构,遍历_OBJECT_TYPE实际上也就是遍历_OBJECT_HEADER_CREATOR_INFO这个结构,在_OBJECT_HEADER_CREATOR_INFO种有一个TypeList链表,通过这个链表即可完成对_OBJECT_HEADER_CREATOR_INFO的遍历,而_OBJECT_TYPE紧邻着_OBJECT_HEADER_CREATOR_INFO,这样就完成了对_OBJECT_TYPE的遍历,如下图所示:

createinfolist

 

WinXP下_OBJECT_TYPE、_OBJECT_HEADER、_OBJECT_HEADER_CREATOR_INFO结构的定义

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
//--------------------------------紧邻_OBJECT_HEADER
0: 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 //++++++++++++++这货就是下面的_OBJECT_TYPE
//-----------------------------------紧邻_OBJECT_TYPE,_OBJECT_TYPE就是Body
0: kd> dt _OBJECT_TYPE
nt!_OBJECT_TYPE
 +0x000 Mutex : _ERESOURCE
 +0x038 TypeList : _LIST_ENTRY
 +0x040 Name : _UNICODE_STRING
 +0x048 DefaultObject : Ptr32 Void
 +0x04c Index : Uint4B
 +0x050 TotalNumberOfObjects : Uint4B
 +0x054 TotalNumberOfHandles : Uint4B
 +0x058 HighWaterNumberOfObjects : Uint4B
 +0x05c HighWaterNumberOfHandles : Uint4B
 +0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER
 +0x0ac Key : Uint4B
 +0x0b0 ObjectLocks : [4] _ERESOURCE

转载部分

Windows内部有很多的对象类型,比如PROCESS类型,THREAD类型,FILE类型,LPC PORT类型,DEVICE类型等等,我们可以使用sysinternal提供的winobj工具来查看(win7 x86 sp1)

201211091649301898

在编程的过程中我们有时候需要用到类型的索引(TypeIndex),由于在不同的操作系统版本中TypeIndex会发生改变,本文将教大家一种方法来遍历这些类型还有其相应的TypeIndex,首先要知道类型也是一种对象,同样它也有OBJECT HEADER,OBJECT BODY等信息,是通过OBJECT MANAGER对象管理器来管理的,在这些类型对象当中有一个非常重要的对象,叫做Type对象,这是系统中第一个被初始化的类型对象(可称之为“元类型”),系统中其他的类型对象都是通过这个特殊的“元类型”对象来创建的

那么这些类型对象是放在什么地方又是通过什么样的关系组织起来的呢?我们之前说过类型也是一种对象,它的OBJECT BODY其实是nt!_object_type,用windbg dt查看一下(win7 x86 sp1)

201211091649345883

其中的第一个数据成员是TypeList,对象是不是就是通过这个TypeList连接起来的呢?

通过查阅ReactOS中的ObCreateObjectType中的实现,发下了如下的代码

201211091649369145

原来正是通过CreateInfo中的TypeList来链接起所有的类型对象,而这个链表的头结点就是ObpTypeObjectType,其实就是“元类型”对象

CreateInfo的数据结构是nt!_OBJECT_HEADER_CREATOR_INFO,里面果真有个TypeList

201211091649373705

因此如果要遍历所有的类型对象的话只要找到这个表的表头即可,那么表头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来得到,下面截图一下代码,为的是让大家自己敲代码来寻找,加深理解

201211091649374883

会了的话再去试着找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

 

转载请注明:悠然品鉴 » WinXp、Win7获取系统ObjectType和TypeIndex

喜欢 (2)or分享 (0)
发表我的评论
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址