ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

遍历Windows内核ObjectType

2022-07-18 21:33:58  阅读:244  来源: 互联网

标签:遍历 Windows TYPE OBJECT 00000000 fffffa80 fffff800 fffff806 ObjectType


一、背景

        Windows内核中有很多类型,例如PROCESS、THREAD、FILE、MUTANT,这些类型都由对象管理器集中管理,见下图:

 

 

  其中有些对象类型是导出的,例如有IoDriverObjectType, PsProcessType等,有些是文档化的,有些是导出的,还有的是未导出的。在使用未导出的对象指针时就得想办法获得,在此遍历对象类型及其相关信息,使用未导出的对象类型时可以直接使用,对象类型结构之类不作详细分析,直接上相关实现的分析。

 

 二、几个主要的内核变量

   ObpTypeObjectType、ObpObjectTypes、ObTypeIndexTable。

  • ObpTypeObjectType

  这个表保存的是原始对象名称为"Type"的对象类型。Windbg调试Win7格式化如下:

5: kd>  dq nt!ObpTypeObjectType
fffff800`0666e5a8  fffffa80`30e4c530 00000000`00000000
fffff800`0666e5b8  00000000`00000000 fffffa80`30e4c530
fffff800`0666e5c8  fffffa80`30e4c3e0 fffffa80`30e4c290
fffff800`0666e5d8  fffffa80`30e525a0 fffffa80`30e52380
fffff800`0666e5e8  fffffa80`30e52230 fffffa80`30ee0080
fffff800`0666e5f8  fffffa80`30ee0f30 fffffa80`30ee0de0
fffff800`0666e608  fffffa80`30ee1080 fffffa80`30f5a940
fffff800`0666e618  fffffa80`30f4ca10 fffffa80`30f4c8c0

  然后取第一个数据查看如下:

5: kd> dt _object_type fffffa80`30e4c530
ntdll!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`30e4c4e0 - 0xfffffa80`3205db20 ]
   +0x010 Name             : _UNICODE_STRING "Type"
   +0x020 DefaultObject    : 0xfffff800`0666e7a0 Void
   +0x028 Index            : 0x2 ''
   +0x02c TotalNumberOfObjects : 0x2a
   +0x030 TotalNumberOfHandles : 0
   +0x034 HighWaterNumberOfObjects : 0x2a
   +0x038 HighWaterNumberOfHandles : 0
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x546a624f
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`30e4c5f0 - 0xfffffa80`30e4c5f0 ]

  这个就是第一个名为Type的ObjectType。再取后边第五个非fffffa80`30e4c530的看:

5: kd> dt _object_type fffffa80`30e4c3e0
ntdll!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`30e4c3e0 - 0xfffffa80`30e4c3e0 ]
   +0x010 Name             : _UNICODE_STRING "Directory"
   +0x020 DefaultObject    : 0xfffff800`0666e7a0 Void
   +0x028 Index            : 0x3 ''
   +0x02c TotalNumberOfObjects : 0x25
   +0x030 TotalNumberOfHandles : 0x70
   +0x034 HighWaterNumberOfObjects : 0x29
   +0x038 HighWaterNumberOfHandles : 0x83
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x65726944
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`30e4c4a0 - 0xfffffa80`30e4c4a0 ]

  

  其为目录对象。

  那似乎通过ObpTypeObjectType这个就可以遍历所有的对象类型,之前查看其它的文章也有这个指出的。

  那如何获取到ObpTypeObjectType,根据Windbg调试发现ObCreateObjectTypeEx中有对其的引用 :

nt!ObCreateObjectTypeEx+0x2e3:
fffff800`068a1373 0fb74602        movzx   eax,word ptr [rsi+2]
fffff800`068a1377 488d4c2460      lea     rcx,[rsp+60h]
fffff800`068a137c 488bd6          mov     rdx,rsi
fffff800`068a137f 6689442462      mov     word ptr [rsp+62h],ax
fffff800`068a1384 e827fec0ff      call    nt!RtlCopyUnicodeString (fffff800`064b11b0)
fffff800`068a1389 4c8b2518d2dcff  mov     r12,qword ptr [nt!ObpTypeObjectType (fffff800`0666e5a8)]
fffff800`068a1390 4d3be6          cmp     r12,r14
fffff800`068a1393 7555            jne     nt!ObCreateObjectTypeEx+0x35a (fffff800`068a13ea)  Branch

  而ObCreateObjectTypeEx又被ObCreateObjectType调用:

5: kd> uf nt!ObCreateObjectType
nt!ObCreateObjectType:
fffff800`068a1a90 4883ec38        sub     rsp,38h
fffff800`068a1a94 4c894c2420      mov     qword ptr [rsp+20h],r9
fffff800`068a1a99 4533c9          xor     r9d,r9d
fffff800`068a1a9c e8eff5ffff      call    nt!ObCreateObjectTypeEx (fffff800`068a1090)
fffff800`068a1aa1 4883c438        add     rsp,38h
fffff800`068a1aa5 c3              ret

  

  而ObCreateObjectType是导出的。

  似乎得出结论可以用此来定位。

  但在Win10系统上格式化结构却得出来的数据不正确,见下:

0: kd> dq nt!ObpTypeObjectType
fffff806`11c25b30  ffffb386`f147fea0 ffffe001`81a2fce0
fffff806`11c25b40  00000000`00000000 00000000`00000000
fffff806`11c25b50  00000000`00000000 00000000`00000000
fffff806`11c25b60  00000000`00000000 00000000`00000000
fffff806`11c25b70  00000000`00000000 00000000`00000000
fffff806`11c25b80  00000000`00000000 00000000`00000000
fffff806`11c25b90  00000000`00000000 00000000`00000000
fffff806`11c25ba0  00000000`00000000 00000000`00000000

  发现除了第一个头外后边都是空的。

  其原因就是在Win7上后边连续填充的数据对应的是另一个ObpObjectTypes的数据。

  

5: kd>  dq nt!ObpTypeObjectType
fffff800`0666e5a8  fffffa80`30e4c530 00000000`00000000
fffff800`0666e5b8  00000000`00000000 fffffa80`30e4c530
fffff800`0666e5c8  fffffa80`30e4c3e0 fffffa80`30e4c290
fffff800`0666e5d8  fffffa80`30e525a0 fffffa80`30e52380
fffff800`0666e5e8  fffffa80`30e52230 fffffa80`30ee0080
fffff800`0666e5f8  fffffa80`30ee0f30 fffffa80`30ee0de0
fffff800`0666e608  fffffa80`30ee1080 fffffa80`30f5a940
fffff800`0666e618  fffffa80`30f4ca10 fffffa80`30f4c8c0
5: kd> dq nt!ObpObjectTypes
fffff800`0666e5c0  fffffa80`30e4c530 fffffa80`30e4c3e0
fffff800`0666e5d0  fffffa80`30e4c290 fffffa80`30e525a0
fffff800`0666e5e0  fffffa80`30e52380 fffffa80`30e52230
fffff800`0666e5f0  fffffa80`30ee0080 fffffa80`30ee0f30
fffff800`0666e600  fffffa80`30ee0de0 fffffa80`30ee1080
fffff800`0666e610  fffffa80`30f5a940 fffffa80`30f4ca10
fffff800`0666e620  fffffa80`30f4c8c0 fffffa80`30f30c30
fffff800`0666e630  fffffa80`30f30ae0 fffffa80`30f538c0

  可以看到 ObpTypeObjectType之后第三个数据的地址及为ObpObjectTypes的开始地址。

  而在Win10上是不连续的,没办法用ObpTypeObjectType来遍历了。

0: kd> dq nt!ObpTypeObjectType
fffff806`11c25b30  ffffb386`f147fea0 ffffe001`81a2fce0
fffff806`11c25b40  00000000`00000000 00000000`00000000
fffff806`11c25b50  00000000`00000000 00000000`00000000
fffff806`11c25b60  00000000`00000000 00000000`00000000
fffff806`11c25b70  00000000`00000000 00000000`00000000
fffff806`11c25b80  00000000`00000000 00000000`00000000
fffff806`11c25b90  00000000`00000000 00000000`00000000
fffff806`11c25ba0  00000000`00000000 00000000`00000000
0: kd> dq nt!ObpObjectTypes
fffff806`11c25280  ffffb386`f147fea0 ffffb386`f1460a10
fffff806`11c25290  ffffb386`f145fe70 ffffb386`f14c7e80
fffff806`11c252a0  ffffb386`f14c77a0 ffffb386`f14c7220
fffff806`11c252b0  ffffb386`f14c7640 ffffb386`f14c70c0
fffff806`11c252c0  ffffb386`f14c7900 ffffb386`f14c7a60
fffff806`11c252d0  ffffb386`f14c7380 ffffb386`f14c74e0
fffff806`11c252e0  ffffb386`f14c7d20 ffffb386`f14c7bc0
fffff806`11c252f0  ffffb386`f14f1f00 ffffb386`f14f1c40

 

  • ObpObjectTypes

  这个变量来说确实是保存了所有的对象类型,但有个问题是不太容易从导出的函数来定位这个数据。IDA查看其代码引用处如下:

 

   第2、3、4个函数不是直接使用的ObpObjectTypes,而其它的都不能方便的从导出函数进行定位。

  所以此方法不通。

 

  • ObTypeIndexTable

  此变量是以索顺序来存放对象类型的指针的,结构数据如下:

5: kd> dq ObTypeIndexTable
fffff800`06670100  00000000`00000000 00000000`bad0b0b0
fffff800`06670110  fffffa80`30e4c530 fffffa80`30e4c3e0
fffff800`06670120  fffffa80`30e4c290 fffffa80`30e525a0
fffff800`06670130  fffffa80`30e52380 fffffa80`30e52230
fffff800`06670140  fffffa80`30ee0080 fffffa80`30ee0f30
fffff800`06670150  fffffa80`30ee0de0 fffffa80`30ee1080
fffff800`06670160  fffffa80`30f5a940 fffffa80`30f4ca10
fffff800`06670170  fffffa80`30f4c8c0 fffffa80`30f30c30
5: kd> dt _object_type fffffa80`30e4c530
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`30e4c4e0 - 0xfffffa80`3205db20 ]
   +0x010 Name             : _UNICODE_STRING "Type"
   +0x020 DefaultObject    : 0xfffff800`0666e7a0 Void
   +0x028 Index            : 0x2 ''
   +0x02c TotalNumberOfObjects : 0x2a
   +0x030 TotalNumberOfHandles : 0
   +0x034 HighWaterNumberOfObjects : 0x2a
   +0x038 HighWaterNumberOfHandles : 0
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x546a624f
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`30e4c5f0 - 0xfffffa80`30e4c5f0 ]
5: kd> dt _object_type fffffa80`30e4c3e0
nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY [ 0xfffffa80`30e4c3e0 - 0xfffffa80`30e4c3e0 ]
   +0x010 Name             : _UNICODE_STRING "Directory"
   +0x020 DefaultObject    : 0xfffff800`0666e7a0 Void
   +0x028 Index            : 0x3 ''
   +0x02c TotalNumberOfObjects : 0x29
   +0x030 TotalNumberOfHandles : 0x76
   +0x034 HighWaterNumberOfObjects : 0x29
   +0x038 HighWaterNumberOfHandles : 0x83
   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0b0 TypeLock         : _EX_PUSH_LOCK
   +0x0b8 Key              : 0x65726944
   +0x0c0 CallbackList     : _LIST_ENTRY [ 0xfffffa80`30e4c4a0 - 0xfffffa80`30e4c4a0 ]

   从第2个 fffffa80`30e4c530的地址结构格式化可以看出其Index为2,对应表中的地址索引为2。其这个表就是从第2号索引开始, 第1号索引00000000`bad0b0b0    指向的实际是无效对象类型。

   IDA查看其引用如下,有很多函数中都用到:

 

 

   取其中较实现查找的ObGetObjectType,通过查找特征码就可以获得:

5: kd> u nt!ObGetObjectType
nt!ObGetObjectType:
fffff800`06796e60 0fb641e8        movzx   eax,byte ptr [rcx-18h]
fffff800`06796e64 488d0d9592edff  lea     rcx,[nt!ObTypeIndexTable (fffff800`06670100)]
fffff800`06796e6b 488b04c1        mov     rax,qword ptr [rcx+rax*8]
fffff800`06796e6f c3              ret
fffff800`06796e70 cc              int     3
fffff800`06796e71 cc              int     3
fffff800`06796e72 cc              int     3
fffff800`06796e73 cc              int     3

三、代码实现

  PrintOjbectTypeList.h

#pragma once
#include <ntddk.h>

#if DBG
#define KDPRINT(projectName, format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,\
                                                                                          projectName "::【" __FUNCTION__  "】" ##format, \
                                                                                          ##__VA_ARGS__ ) 
#else
#define KDPRINT(format, ...)
#endif
typedef struct _OBJECT_TYPE_FLAGS {
    UCHAR CaseInsensitive : 1;
    UCHAR UnnamedObjectsOnly : 1;
    UCHAR UseDefaultObject : 1;
    UCHAR SecurityRequired : 1;
    UCHAR MaintainHandleCount : 1;
    UCHAR MaintainTypeList : 1;
    UCHAR SupportsObjectCallbacks : 1;
    UCHAR CacheAligned : 1;
}OBJECT_TYPE_FLAGS, * P_OBJECT_TYPE_FLAGS;


typedef struct _OBJECT_TYPE_INITIALIZER {
    USHORT                wLength;
    OBJECT_TYPE_FLAGS    ObjectTypeFlags;
    ULONG                ObjcetTypeCode;
    ULONG                InvalidAttributes;
    GENERIC_MAPPING        GenericMapping;
    ULONG                ValidAccessMask;
    ULONG                RetainAccess;
    ULONG                PoolType;
    ULONG                DefaultPagedPoolCharge;
    ULONG                DefaultNonPagedPoolCharge;
    PVOID                DumpProcedure;
    PVOID                OpenProcedure;
    PVOID                CloseProcedure;
    PVOID                DeleteProcedure;
    PVOID                ParseProcedure;
    PVOID                SecurityProcedure;
    PVOID                QueryNameProcedure;
    PVOID                OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, * POBJECT_TYPE_INITIALIZER;

typedef struct _OBJECT_TYPE_EX {
    LIST_ENTRY                    TypeList;
    UNICODE_STRING                Name;
    ULONGLONG                    DefaultObject;
    ULONG                        Index;
    ULONG                        TotalNumberOfObjects;
    ULONG                        TotalNumberOfHandles;
    ULONG                        HighWaterNumberOfObjects;
    ULONG                        HighWaterNumberOfHandles;
    OBJECT_TYPE_INITIALIZER        TypeInfo;
    ULONGLONG                    TypeLock;
    ULONG                        Key;
    LIST_ENTRY                    CallbackList;
}OBJECT_TYPE_EX, * POBJECT_TYPE_EX;

 

​  PrintObjectTypeList.cpp

#include "PrintObjectTypeList.h"

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    UNREFERENCED_PARAMETER(pDriverObject);
    KDPRINT("【PrintObjectTypeList】", "CurrentProcessId : 0x%p CurrentIRQL : 0x%u \r\n",
        PsGetCurrentProcessId(),
        KeGetCurrentIrql());
}

void PrintObTypeIndexList(PVOID pObTypeIndexTable)
{
    if (pObTypeIndexTable)
    {
        PUCHAR pStartAddress = ((PUCHAR)pObTypeIndexTable + 8 * 2); //从第2个开始
        POBJECT_TYPE_EX *pTempObjectType = (POBJECT_TYPE_EX*)(pStartAddress);
        ULONG ulIndex = 0;
        while(*pTempObjectType != NULL)
        {
            KDPRINT("【PrintObjectTypeList】", "Index:%02ld  Address:0x%p Name:%wZ\r\n", 
                ulIndex,
                *pTempObjectType,
                &(*pTempObjectType)->Name);
            pTempObjectType++;
            ulIndex++;
        }

    }
}

PVOID GetObTypeIndexTable()
{
    UNICODE_STRING usObGetObjectType = RTL_CONSTANT_STRING(L"ObGetObjectType");
    PVOID pGetObTypeIndexTable = NULL;
    PVOID pObGetObjectType = (PVOID)MmGetSystemRoutineAddress(&usObGetObjectType);
    do
    {
        if (!pObGetObjectType)
        {
            KDPRINT("【PrintObjectTypeList】", "MmGetSystemRoutineAddress Failed! \r\n");
            break;
        }

        PUCHAR pStartAddress = (PUCHAR)pObGetObjectType;
        PUCHAR pTempAddress = pStartAddress;
        for (; pTempAddress < pStartAddress + PAGE_SIZE; pTempAddress++)
        {
            if ((*(pTempAddress - 3) == 0x48) &&
                (*(pTempAddress - 2) == 0x8d) &&
                (*(pTempAddress - 1) == 0x0d) &&
                (*(pTempAddress + 4) == 0x48) &&
                (*(pTempAddress + 5) == 0x8b) &&
                (*(pTempAddress + 6) == 0x04) &&
                (*(pTempAddress + 7) == 0xc1))
            {
                LONG lOffset = *(PLONG)(pTempAddress);
                pGetObTypeIndexTable = pTempAddress + 4 + lOffset;
                break;
            }
        }

    } while (false);
    if (pGetObTypeIndexTable)
    {
        KDPRINT("【ObRegisterCallback】", "Found ObTypeIndexTable Address:0x%p \r\n", pGetObTypeIndexTable);
    }
    else
    {
        KDPRINT("【PrintObjectTypeList】", "ObTypeIndexTable Not Found!\r\n");
    }
    return pGetObTypeIndexTable;
}

EXTERN_C NTSTATUS  DriverEntry(PDRIVER_OBJECT pDriverObject,
    PUNICODE_STRING pRegistryPath)
{
    UNREFERENCED_PARAMETER(pDriverObject);
    UNREFERENCED_PARAMETER(pRegistryPath);
    KDPRINT("【PrintObjectTypeList】", " Hello Kernel World! CurrentProcessId:0x%p CurrentIRQL:0x%u\r\n",
        PsGetCurrentProcessId(),
        KeGetCurrentIrql());
    pDriverObject->DriverUnload = DriverUnload;

    NTSTATUS ntStatus = STATUS_SUCCESS;
    PVOID pGetObTypeIndexTable = GetObTypeIndexTable();
    if (pGetObTypeIndexTable)
    {
        PrintObTypeIndexList(pGetObTypeIndexTable);
    }

    return ntStatus;
}

 

四、调试结果

  •   Win7 x64

 

  •   Win10 x64

 

 

 

五、结束语

  本次代码只考虑了x64环境下的Win7 和 Win10,32位环境下以及XP未考虑,但思路大同小异。

  通过对对象类型的遍历,可以用在使用未导出的对象类型的时候取消对象指针。

 

标签:遍历,Windows,TYPE,OBJECT,00000000,fffffa80,fffff800,fffff806,ObjectType
来源: https://www.cnblogs.com/ImprisonedSoul/p/16491127.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有