内核对象种类
名称 | 类型 |
---|---|
Job、Directory | 对象目录中的路径 |
SymbolLink | 符号链接 |
Section | 内存映射文件 |
Port | LPC端口 |
IoCompletion | Io完成端口 |
File | 文件(并非专指磁盘文件) |
Mutex、Event、Semaphore、Timer | 同步对象 |
Key | 注册表中的键 |
Token | 用户/组令牌 |
Process、Thread | 进程线程 |
Pipe | 管道 |
Mailslot | 邮件槽 |
Debug | 调试端口 |
内核对象结构
不同类型的内核对象有不同的结构,比如 _EPROCESS 和 _ETHREAD 结构就不同:
但是它们都有相同的 _OBJECT_HEADER 结构,位置在内核对象地址 - 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
+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 // 来源于创建对象时的 OBJECT_ATTRIBUTES
+0x020 QuotaBlockCharged : Ptr64 Void
+0x028 SecurityDescriptor : Ptr64 Void // 安全描述符(对象的拥有者、ACL等信息)
+0x030 Body : _QUAD // 通用对象头后面紧跟着真正的结构体(这个字段是后面真正结构体中的第一个成员)
///
nt!_OBJECT_HEADER_CREATOR_INFO
+0x000 TypeList : _LIST_ENTRY // OBJECT_TYPE 链表
+0x010 CreatorUniqueProcess : Ptr64 Void // 对象是由哪个进程创建的
+0x018 CreatorBackTraceIndex : Uint2B
+0x01a Reserved1 : Uint2B
+0x01c Reserved2 : Uint4B
/// 使用 ObGetObjectType 获取 OBJECT_TYPE
nt!_OBJECT_TYPE
+0x000 TypeList : _LIST_ENTRY // 本类对象的链表,记录所有同类对象
+0x010 Name : _UNICODE_STRING // 对象类型名
+0x020 DefaultObject : Ptr64 Void // 本类对象默认使用的同步事件对象
+0x028 Index : UChar // 本类型的索引,也即表示这是系统中第几个注册的对象类型
+0x02c TotalNumberOfObjects : Uint4B // 对象链表中总的对象个数
+0x030 TotalNumberOfHandles : Uint4B // 所有同类对象的打开句柄总数
+0x034 HighWaterNumberOfObjects : Uint4B // 历史本类对象个数峰值
+0x038 HighWaterNumberOfHandles : Uint4B // 历史本类对象的句柄个数峰值
>>> +0x040 TypeInfo : _OBJECT_TYPE_INITIALIZER // 很重要,object hook 全靠这个
+0x0b8 TypeLock : _EX_PUSH_LOCK // 对象类型锁
+0x0c0 Key : Uint4B // 事实上用作内存分配的tag,同类对象占用的内存块都标记为同一个tag
+0x0c8 CallbackList : _LIST_ENTRY // 回调函数链表
/
nt!_OBJECT_TYPE_INITIALIZER
+0x000 Length : Uint2B // 本结构体本身的长度
+0x002 ObjectTypeFlags : Uint2B
+0x002 CaseInsensitive : Pos 0, 1 Bit // 本类对象的对象名是否大小写不敏感
+0x002 UnnamedObjectsOnly : Pos 1, 1 Bit
+0x002 UseDefaultObject : Pos 2, 1 Bit // 是否使用全局默认的同步事件对象
+0x002 SecurityRequired : Pos 3, 1 Bit // 本类对象是否需要安全控制
+0x002 MaintainHandleCount : Pos 4, 1 Bit // 对象头中是否维护句柄统计信息
+0x002 MaintainTypeList : Pos 5, 1 Bit // 是否维护创建者信息
+0x002 SupportsObjectCallbacks : Pos 6, 1 Bit // 支持的对象回调
+0x002 CacheAligned : Pos 7, 1 Bit // 隐藏对齐
+0x003 UseExtendedParameters : Pos 0, 1 Bit // 启用扩展参数
+0x003 Reserved : Pos 1, 7 Bits
+0x004 ObjectTypeCode : Uint4B
+0x008 InvalidAttributes : Uint4B
+0x00c GenericMapping : _GENERIC_MAPPING // 通用映射
+0x01c ValidAccessMask : Uint4B // 本类对象支持的属性集合
+0x020 RetainAccess : Uint4B
+0x024 PoolType : _POOL_TYPE // 本类对象位于分页池还是非分页池(一般内核对象都分配在非分页池中)
+0x028 DefaultPagedPoolCharge : Uint4B // 对象占用的分页池总体大小
+0x02c DefaultNonPagedPoolCharge : Uint4B // 对象占用的非分页池总体大小
// object hook 就是改变这几个成员指向的函数地址 =======================================
>>>+0x030 DumpProcedure : Ptr64 void // dump 对象时调用
>>>+0x038 OpenProcedure : Ptr64 long // 打开对象时调用
>>>+0x040 CloseProcedure : Ptr64 void // 关闭句柄时调用
>>>+0x048 DeleteProcedure : Ptr64 void // 销毁对象时调用
>>>+0x050 ParseProcedure : Ptr64 long // 解析路径时调用(设备、文件、键)
>>>+0x050 ParseProcedureEx : Ptr64 long
>>>+0x058 SecurityProcedure : Ptr64 long // 查询、设置对象安全描述符时调用
>>>+0x060 QueryNameProcedure : Ptr64 long // 文件对象提供了自定义的QueryNameString函数
>>>+0x068 OkayToCloseProcedure : Ptr64 unsigned char // 每次关闭句柄前都会调用这个函数检查可否关闭
+0x070 WaitObjectFlagMask : Uint4B
+0x074 WaitObjectFlagOffset : Uint2B
+0x076 WaitObjectPointerOffset : Uint2B