汉花唐落 发表于 2017-6-1 13:32:35

无硬编码获取所有对象类型地址

NTKERNELAPI PVOID NTAPI
ObGetObjectType(
      IN PVOID pObject
      );



void GetObjectTypeWin7x86()
{
        BOOLEAN i = 2;
        ULONG        j= 2;
        ULONG64 ObjectType;
        //
        while (ObGetObjectType(&i+0xC))
        {
                ObjectType = ObGetObjectType(&i + 0xC);//C来自于ObGetObjectType反汇编处的eax-0xCwin7 x86
                KdPrint(("对象类型[%d]=%wZ\n", j, ObjectType+0x8));
                i++;
                j++;
        }
                        /*获取TypeIndex的值,解释一下为什么是减去0Ch。正常的计算应该是:
                        object地址-Object_header的大小+TypeIndex的偏移,所以有:
                        eax-0x18h+0x0Ch 即为 eax – 0x0Ch
                        82a8f3fe 0fb640f4      movzx   eax,byte ptr
                        根据索引值在ObTypeIndexTable数组中找到对应的ObjectType。
                        url:http://www.blogfshare.com/win7-obtypeindextable.html
                        */
}

void GetObjectTypeWin7x64()//0x18来的原理同上
{
        BOOLEAN i = 2;
        ULONG        j = 2;
        ULONG64 ObjectType;
        UNICODE_STRING ObjectName;
        RtlInitUnicodeString(&ObjectName,L"Process");
        while (ObGetObjectType(&i+0x18))
        {
                ObjectType = ObGetObjectType(&i + 0x18);
                KdPrint(("对象类型[%d]=%wZ\n", j, ObjectType+0x10));
                i++;
                j++;
        }
        /*
        ObGetObjectType(&i + 0x18) 里面就要一个地址我们给他i的地址, + 0x18就是还原TypeIndex的
        相当于把这个指令变为
        movzx   eax,byte ptr --> movzx    eax,i
       
        nt!ObGetObjectType:
        fffff800`0613c854 0fb641e8      movzx   eax,byte ptr //rcx-18h = rcx - sizeof(OBJECT_TYPE)0x30 + TypeIndex偏移0x18
        fffff800`0613c858 488d0da1e2effflea   rcx,
        fffff800`0613c85f 488b04c1      mov   rax,qword ptr
        fffff800`0613c863 c3            ret
        */
        /*
        ObjectType = ObGetObjectType(&i + 0x18);
        KdPrint(("对象类型[%d]=%wZ\n", j, ObjectType+0x10));
        ObjectType = ObGetObjectType(&k + 0x18);
        KdPrint(("对象类型[%d]=%wZ\n", j, ObjectType+0x10));
        */
}



如果上面的解释不太明白 请看下面是我自己的理解
为什么一个是+0x18 一个是+0xc
首先,确定一点是ObGetObjectType这个函数是根据TypeIndex去ObTypeIndexTable取地址的
这个函数在没有检查参数,直接读了一个内存地址
看反汇编,这里以win7x64为例子:

PAGE:000000014032A854               public ObGetObjectType
PAGE:000000014032A854 ObGetObjectType proc near               ; CODE XREF: CMFCheckAccess:loc_14032AB3Ep
PAGE:000000014032A854                                       ; PnpHandleProcessWalkWorker+15p ...
PAGE:000000014032A854               movzx   eax, byte ptr
PAGE:000000014032A858               lea   rcx, ObTypeIndexTable
PAGE:000000014032A85F               mov   rax,
PAGE:000000014032A863               retn
PAGE:000000014032A863 ObGetObjectType endp
PAGE:000000014032A863
从参数的地址中获取数据当TypeIndex

那么我们只需要改变这个地址,怎么改呢?这里的参数放在rcx中,我们只能改rcx的值,我们先把-18h除去,就是+0x18
rcx的值我们用我们变量的地址来填充
就变成了

movzx eax,byte ptr [变量的地址+18h - 18h]


那么结果呢,你懂得
下面是封转好的

/根据调试对象类型名字,获取调试对象类型指针
PVOID GetObjectTypeByName(PWCHAR ObjectTypeName)
{
      UNICODE_STRING name;
      BOOLEAN i = 2;
      PVOID pObjectType;

      if (ObjectTypeName == NULL)
      {
                return 0;
      }
      RtlInitUnicodeString(&name, ObjectTypeName);

      while (ObGetObjectType((PVOID)(&i + 0x18)))
      {
                pObjectType = ObGetObjectType(&i + 0x18);
                i++;

                if (RtlEqualUnicodeString((PVOID)((ULONG_PTR)pObjectType + 0x10), &name, TRUE))
                {
                        return pObjectType;
                }

      }

      return 0;
}

//调用方法
PVOID       gProcessObjectType = 0;
gProcessObjectType = <span style="font-family: Arial, Helvetica, sans-serif;">GetObjectTypeByName</span>(L"Process");
页: [1]
查看完整版本: 无硬编码获取所有对象类型地址