概述
首先,每个进程/线程对象上面都有个_OBJECT_HEADER结构,而句柄结构在这个结构的后面,64位下这个结构大小为0X30
以进程结构体举例:
nt!_OBJECT_HEADER
+0x000 PointerCount : Int8B
+0x008 HandleCount : Int8B
+0x008 NextToFree : Ptr64 Void
+0x010 Lock : _EX_PUSH_LOCK
+0x018 TypeIndex : UChar
+0x019 TraceFlags : UChar
+0x019 DbgRefTrace : Pos 0, 1 Bit
+0x019 DbgTracePermanent : Pos 1, 1 Bit
+0x01a InfoMask : UChar
+0x01b Flags : UChar flags = 0x71; //进程退出,修改后再改句柄表隐藏
+0x01b NewObject : Pos 0, 1 Bit
+0x01b KernelObject : Pos 1, 1 Bit
+0x01b KernelOnlyAccess : Pos 2, 1 Bit
+0x01b ExclusiveObject : Pos 3, 1 Bit
+0x01b PermanentObject : Pos 4, 1 Bit
+0x01b DefaultSecurityQuota : Pos 5, 1 Bit
+0x01b SingleHandleEntry : Pos 6, 1 Bit
+0x01b DeletedInline : Pos 7, 1 Bit
+0x01c Reserved : Uint4B
+0x020 ObjectCreateInfo : Ptr64 _OBJECT_CREATE_INFORMATION
+0x020 QuotaBlockCharged : Ptr64 Void
+0x028 SecurityDescriptor : Ptr64 Void
+0x030 Body : _QUAD //进程/线程对象在这个位置
这里开始就是
_EPROCESS / _ETHREAD 结构
2.微软提供了一个未文档化函数可以返回结构体头部
NTKERNELAPI POBJECT_TYPE ObGetObjectType(PVOID Object);
//ObGetObjectType可以通过进程对象取到_OBJECT_TYPE结构体头地址
0: kd> dt _OBJECT_TYPE
ntdll!_OBJECT_TYPE
+0x000 TypeList : _LIST_ENTRY
+0x010 Name : _UNICODE_STRING //进程就是 process 线程就是Thread
+0x020 DefaultObject : Ptr64 Void
+0x028 Index : UChar //句柄类型ID process 是 7 ;Thread是8
+0x02c TotalNumberOfObjects : Uint4B
+0x030 TotalNumberOfHandles : Uint4B
+0x034 HighWaterNumberOfObjects : Uint4B
+0x038 HighWaterNumberOfHandles : Uint4B
+0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x0b0 TypeLock : _EX_PUSH_LOCK
+0x0b8 Key : Uint4B
+0x0c0 CallbackList : _LIST_ENTRY
那么手动如何得到_OBJECT_TYPE的地址呢,逆向下win7(WIN8.1)内核模块
PAGE:0000000140330B54 public ObGetObjectType
PAGE:0000000140330B54 ObGetObjectType proc near ; CODE XREF: CMFCheckAccess:loc_14033123E↓p
PAGE:0000000140330B54 ; PnpHandleProcessWalkWorker+15↓p ...
PAGE:0000000140330B54 movzx eax, byte ptr [rcx-18h]
PAGE:0000000140330B58 lea rcx, ObTypeIndexTable
PAGE:0000000140330B5F mov rax, [rcx+rax*8]
PAGE:0000000140330B63 retn
得知:ObTypeIndexTable + [对象-0x18] *8 = _OBJECT_TYPE头部
win7虚拟机找个进程测试下
WIN10开始就换了个解密方法,真蛋疼
PAGE:00000001404C65A8 public ObGetObjectType
PAGE:00000001404C65A8 ObGetObjectType proc near ; DATA XREF: .pdata:00000001403AA730↑o
PAGE:00000001404C65A8 lea rax, [rcx-30h] ; ffffd18dccb7f050
PAGE:00000001404C65AC movzx ecx, byte ptr [rcx-18h] ; 0x7c 注意:movzx会填充整个x64寄存器为0再赋值
PAGE:00000001404C65B0 shr rax, 8 ; FFD18DCCB7F0
PAGE:00000001404C65B4 movzx eax, al ; F0
PAGE:00000001404C65B7 xor rax, rcx ; f0 xor 7c=8C
PAGE:00000001404C65BA movzx ecx, byte ptr cs:ObHeaderCookie ; 8b
PAGE:00000001404C65C1 xor rax, rcx ; xor 8c,8b =7
PAGE:00000001404C65C4 lea rcx, ObTypeIndexTable
PAGE:00000001404C65CB mov rax, [rcx+rax*8]
PAGE:00000001404C65CF retn
PAGE:00000001404C65CF ObGetObjectType endp
解密出来公式大概这样:
[ObTypeIndexTable+((((object - 0x30) >> 8 ) &0xFF^ *(pchar)(object-0x18))^*(pchar)ObHeaderCookie))*8] = _OBJECT_TYPE头
[ObTypeIndexTable+((0xf0^ 0x7c)^0x8b)8]
[fffff800`6b911e10+78]
至此,解密完成,当然代码还是用微软提供的函数吧 ObGetObjectType,有现成的干嘛不用呢
最后
以上就是光亮烧鹅为你收集整理的28.探秘_OBJECT_TYPE结构的全部内容,希望文章能够帮你解决28.探秘_OBJECT_TYPE结构所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复