吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2474|回复: 2
收起左侧

[其他转载] 【分享】Winodws Object结构

[复制链接]
Godsec 发表于 2016-7-22 13:27
本帖最后由 Cizel 于 2016-7-24 17:01 编辑

Windows系统的各种资源以对象(Object)的形式来组织,例如File Object, Driver Object, Device Object等等,但实际上这些所谓的对象在系统的对象管理器(Object Manager)看来只是完整对象的一个部分——对象实体(Object Body)。Windows XP中有31种不同类型的对象,Object Body反映了某一类型对象的特征信息,例如,文件对象使用FILE_OBJECT结构描述、驱动对象使用DRIVER_OBJECT结构描述、DEVICE_OBJECT用于描述设备对象等等。而各种Object的共有的信息(例如,对象类型、对象的引用计数、句柄数等信息)保存在OBJECT_HEADER与其他的几个结构中。换而言之,在对象管理器内部,不同类型的对象具有相同的Object Header,但Object Body部分却是不同的。
先放上一张Windows Object完整的结构图,其中OBJECT_HEADER取自Windows XP SP2 英文版。

         +----------------------------------------------------------------+
+------->| ( OBJECT_HEADER_QUOTA_INFO )                                   |
|  +---->| ( OBJECT_HEADER_HANDLE_INFO )                                  |
|  |  +->| ( OBJECT_HEADER_NAME_INFO )                                    |
|  |  |  | ( OBJECT_HEADER_CREATOR_INFO )                                 |
|  |  |  +------------------------[ 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 Body ]------------------------+
         | OBJECT_DIRECTORY, DRIVER_OBJECT, DEVICE_OBJECT, FILE_OBJECT... |
         +----------------------------------------------------------------+

一个对象由三部分组成,在Object Header之前是一段变长的区域,由四个独立的结构体组成:
  Code:
typedef struct _OBJECT_HEADER_QUOTA_INFO {
    ULONG PagedPoolCharge;
    ULONG NonPagedPoolCharge;
    ULONG SecurityDescriptorCharge;
    PEPROCESS ExclusiveProcess;
#ifdef _WIN64
    ULONG64  Reserved;   // Win64 requires these structures to be 16 byte aligned.
#endif
} OBJECT_HEADER_QUOTA_INFO, *POBJECT_HEADER_QUOTA_INFO;

typedef struct _OBJECT_HEADER_HANDLE_INFO {
    union {
        POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase;
        OBJECT_HANDLE_COUNT_ENTRY SingleEntry;
    };
} OBJECT_HEADER_HANDLE_INFO, *POBJECT_HEADER_HANDLE_INFO;

// begin_ntosp
typedef struct _OBJECT_HEADER_NAME_INFO {
    POBJECT_DIRECTORY Directory;
    UNICODE_STRING Name;
    ULONG QueryReferences;
#if DBG
    ULONG Reserved2;
    LONG DbgDereferenceCount;
#ifdef _WIN64
    ULONG64  Reserved3;   // Win64 requires these structures to be 16 byte aligned.
#endif
#endif
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
// end_ntosp

typedef struct _OBJECT_HEADER_CREATOR_INFO {
    LIST_ENTRY TypeList;
    HANDLE CreatorUniqueProcess;
    USHORT CreatorBackTraceIndex;
    USHORT Reserved;
} OBJECT_HEADER_CREATOR_INFO, *POBJECT_HEADER_CREATOR_INFO;


一个对象可以包含全部四个结构,也可能只包含其中的某个,因此这段区域是变长的。
之后是OBJECT_HEADER结构,NameInfoOffsetHandleInfoOffsetQuotaInfoOffset分别为OBJECT_HEADEROBJECT_HEADER_NAME_INFOOBJECT_HEADER_HANDLE_INFOOBJECT_HEADER_QUOTA_INFO这三个结构的偏移。

WinDBG“!object”命令可以显示对象的信息:
  Code:
kd> !object \Driver\Disk
Object: 8985da08  Type: (898df3b0) Driver
    ObjectHeader: 8985d9f0
    HandleCount: 0  PointerCount: 6
    Directory Object: e1005160  Name: Disk


继续看一下OBJECT_HEADER结构的信息:
  Code:
kd> dt nt!_object_header 8985d9f0
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 6
   +0x004 HandleCount      : 0
   +0x004 NextToFree       : (null)
   +0x008 Type             : 0x898df3b0 _OBJECT_TYPE
   +0x00c NameInfoOffset   : 0x10 ''
   +0x00d HandleInfoOffset : 0 ''
   +0x00e QuotaInfoOffset  : 0 ''
   +0x00f Flags            : 0x32 '2'
   +0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x00000001
   +0x014 SecurityDescriptor : 0xe100c843
   +0x018 Body             : _QUAD


NameInfoOffset中指出OBJECT_HEADER_NAME_INFO的便宜量为0×10,它的地址为OBJECT_HEADER - OBJECT_HEADER.NameInfoOffset,即0×8985d9f0-0×10,继续来看:
  Code:
kd> dt nt!_object_header_name_info 8985d9f0-0x10
nt!_OBJECT_HEADER_NAME_INFO
   +0x000 Directory        : 0xe1005160 _OBJECT_DIRECTORY
   +0x004 Name             : _UNICODE_STRING "Disk"
   +0x00c QueryReferences  : 1


第三部分就是对象的实体部分(Object Body),根据对象类型的不同,这部分的结构也不相同。日常使用的DRIVER_OBJECTDEVICE_OBJECTFILE_OBJECT等等都是Object Body结构,继续回头看一下!object \Driver\Disk的输出,Object: 8985da08Object Body部分——DRIVER_OBJECT结构。
  Code:
kd> dt nt!_driver_object 8985da08
nt!_DRIVER_OBJECT
   +0x000 Type             : 4
   +0x002 Size             : 168
   +0x004 DeviceObject     : 0x89900c68 _DEVICE_OBJECT
   +0x008 Flags            : 0x12
   +0x00c DriverStart      : 0xf7627000
   +0x010 DriverSize       : 0x8e00
   +0x014 DriverSection    : 0x89927a70
   +0x018 DriverExtension  : 0x8985dab0 _DRIVER_EXTENSION
   +0x01c DriverName       : _UNICODE_STRING "\Driver\Disk"
   +0x024 HardwareDatabase : 0x8068db10 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM"
   +0x028 FastIoDispatch   : (null)
   +0x02c DriverInit       : 0xf762e8ab     disk!GsDriverEntry+0
   +0x030 DriverStartIo    : (null)
   +0x034 DriverUnload     : 0xf763e53a     CLASSPNP!ClassUnload+0
   +0x038 MajorFunction    : [28] 0xf763dc30     CLASSPNP!ClassCreateClose+0

kd> !drvobj 8985da08
Driver object (8985da08) is for:
\Driver\Disk
Driver Extension List: (id , addr)
(f763e3be 8985d8f0)
Device Object list:
89900c68  89896c68  8985ec68  8985cab8


现在有这样一个问题,我们经常使用Object Body的结构,但是要访问OBJECT_HEADER该如何做呢?
OBJECT_HEADER的大小为0×18字节,因此Object Body = OBJECT_HEADER + 0×18,但是0×18是个硬编码值,如果OBJECT_HEADER在以后的系统中发生了变化,显然用这个0×18是不可靠的。
OBJECT_HEADER结构中有一个Body成员,如果执行“dt nt!_OBJECT_HEADER -b”会有以下的输出:
  Code:
kd> dt nt!_OBJECT_HEADER -b
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32
   +0x008 Type             : Ptr32
   +0x00c NameInfoOffset   : UChar
   +0x00d HandleInfoOffset : UChar
   +0x00e QuotaInfoOffset  : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32
   +0x010 QuotaBlockCharged : Ptr32
   +0x014 SecurityDescriptor : Ptr32
   +0x018 Body             : _QUAD
      +0×000 DoNotUseThisField : Float


注意“+0×000 DoNotUseThisField : Float”部分。Body成员在OBJECT_HEADER结构中的偏移量实际上就是Object BodyOBJECT_HEADER的偏移量(0×18),它只是作为定位偏移量来使用,因此会有“Do Not Use This Field”的提示。
WRK的代码中定义了一个宏函数(见 %wrk%\base\ntos\inc\ob.h),用于从Object Body访问OBJECT_HEADER结构。
  Code:
#define OBJECT_TO_OBJECT_HEADER( o ) \
    CONTAINING_RECORD( (o), OBJECT_HEADER, Body )

//
// Calculate the address of the base of the structure given its type, and an
// address of a field within the structure.
//
#ifndef CONTAINING_RECORD
#define CONTAINING_RECORD(address, type, field) \
    ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
#endif


利用OBJECT_TO_OBJECT_HEADER()传递一个Object Body的地址给它(例如,Disk.sysDriverObject),就可以轻松的得到这个对象的OBJECT_HEADER结构。

以上是个人的一点理解,有不对的地方请大家多多指教。

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

E式丶男孩 发表于 2016-7-22 14:42
大哥有的是真本事啊
wabqsohucom 发表于 2016-7-22 16:53
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-27 07:34

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表