内核对象管理器学习笔记

Windows 10 Kernel Version 10240 MP (1 procs) Free x64
Edition build lab: 10240.16384.amd64fre.th1.150709-1700

对象

对象的总体结构包括:附加信息头,对象头和对象体。附加信息头是可选的,InfoMask字段表示存在哪些附加信息头。

OBJECT_HEADER_*

可选头名称结构作用
创建信息头OBJECT_HEADER_CREATOR_INFO包含创建者信息,用来将创建的对象挂入其创建者的对象队列
命名信息头OBJECT_HEADER_NAME_INFO载有对象名和目录节点的指针
句柄信息头OBJECT_HEADER_HANDLE_INFO关于句柄的信息
配额信息头OBJECT_HEADER_QUOTA_INFO关于耗用内存配额的信息
	#define OB_INFOMASK_CREATOR_INFO  0x01
	#define OB_INFOMASK_NAME          0x02
	#define OB_INFOMASK_HANDLE        0x04
	#define OB_INFOMASK_QUOTA         0x08
    #define OB_INFOMASK_PROCESS_INFO  0x10

   _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 Spare            : Uint4B
   +0x020 ObjectCreateInfo : Ptr64 _OBJECT_CREATE_INFORMATION									来源于创建对象时的 OBJECT_ATTRIBUTES
   +0x020 QuotaBlockCharged : Ptr64 Void							
   +0x020 QuotaBlockCharged : Ptr64 Void
   +0x028 SecurityDescriptor : Ptr64 Void													安全描述符
   +0x030 Body             : _QUAD															通用对象头后面紧跟着真正的结构体(这个字段是后面真正结构体中的第一个成员)

_OBJECT_CREATE_INFORMATION

typedef struct _OBJECT_ATTRIBUTES {
  ULONG           Length;
  HANDLE          RootDirectory;
  PUNICODE_STRING ObjectName;
  ULONG           Attributes;
  PVOID           SecurityDescriptor;
  PVOID           SecurityQualityOfService;
} OBJECT_ATTRIBUTES;

nt!_OBJECT_CREATE_INFORMATION
   +0x000 Attributes       : Uint4B
   +0x008 RootDirectory    : Ptr64 Void
   +0x010 ProbeMode        : Char
   +0x014 PagedPoolCharge  : Uint4B
   +0x018 NonPagedPoolCharge : Uint4B
   +0x01c SecurityDescriptorCharge : Uint4B
   +0x020 SecurityDescriptor : Ptr64 Void
   +0x028 SecurityQos      : Ptr64 _SECURITY_QUALITY_OF_SERVICE
   +0x030 SecurityQualityOfService : _SECURITY_QUALITY_OF_SERVICE

对象目录

对象目录是由多个"节点"连接而成的树状结构,树的根是一个“目录”对象,即类型为OBJECT_DIRECTORY的对象。树中的每个节点都是对象,所以"节点名"就是"对象名"。除根节点之外,树中的所有中间节点都必须是目录对象或“符号连接”对象(即类型为OBJECT_SYMBOLIC_LINK的对象),而普通的对象则只能成为"叶节点"。对于对象目录中的任何节点,如果从根节点或某个中间节点开始逐节向此节点前进,记下沿途各个节点的节点名,并以分隔符"“加以分隔,就形成一个"路径名”。如果路径名中的第一个节点是根节点,就是全路径名或称绝对路径。根节点的节点名是"",内核中全局指针ObpRootDirectoryObject指向的就是对象目录的根节点。

_OBJECT_DIRECTORY

nt!_OBJECT_DIRECTORY
   +0x000 HashBuckets      : [37] Ptr64 _OBJECT_DIRECTORY_ENTRY				数组中的每个指针都可以用来维持一个"(对象)目录项
   +0x128 Lock             : _EX_PUSH_LOCK
   +0x130 DeviceMap        : Ptr64 _DEVICE_MAP
   +0x138 ShadowDirectory  : Ptr64 _OBJECT_DIRECTORY
   +0x140 SessionId        : Uint4B
   +0x148 NamespaceEntry   : Ptr64 Void
   +0x150 Flags            : Uint4B

_OBJECT_DIRECTORY_ENTRY

nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : Ptr64 _OBJECT_DIRECTORY_ENTRY			指针ChanLink用来构成队列		
   +0x008 Object           : Ptr64 Void								指针Object则指向其所连接的对象
   +0x010 HashValue        : Uint4B									具体挂在哪一个队列中则取决于节点名(对象名)的Hash值

对象类型

_OBJECT_TYPE

一类内核对象的通用属性

   _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 					对象类型初始化信息
   +0x0b8 TypeLock         : _EX_PUSH_LOCK								对象类型锁
   +0x0c0 Key              : Uint4B										事实上用作内存分配的tag,同类对象占用的内存块都标记为同一个tag
   +0x0c8 CallbackList     : _LIST_ENTRY								回调函数链表

_OBJECT_TYPE_INITIALIZER

   _OBJECT_TYPE_INITIALIZER
   +0x000 Length           : Uint2B									结构长度
   +0x002 ObjectTypeFlags  : UChar									类型标志
   +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
   +0x004 ObjectTypeCode   : Uint4B
   +0x008 InvalidAttributes : Uint4B
   +0x00c GenericMapping   : _GENERIC_MAPPING						通用映射
   +0x01c ValidAccessMask  : Uint4B									有效访问掩码
   +0x020 RetainAccess     : Uint4B
   +0x024 PoolType         : _POOL_TYPE							   池类型(PagePool, NonPagePool)
   +0x028 DefaultPagedPoolCharge : Uint4B						默认分页池消耗
   +0x02c DefaultNonPagedPoolCharge : Uint4B					默认分页非池消耗
   // object hook 就是改变这几个成员指向的函数地址
   +0x030 DumpProcedure    : Ptr64     void 						转储例程
   +0x038 OpenProcedure    : Ptr64     long 						打开例程
   +0x040 CloseProcedure   : Ptr64     void 						关闭例程
   +0x048 DeleteProcedure  : Ptr64     void 						删除例程
   +0x050 ParseProcedure   : Ptr64     long 						解析例程
   +0x058 SecurityProcedure : Ptr64     long 						安全例程
   +0x060 QueryNameProcedure : Ptr64     long 						查找名称例程
   +0x068 OkayToCloseProcedure : Ptr64     unsigned char 			关闭例程拓展
   +0x070 WaitObjectFlagMask : Uint4B
   +0x074 WaitObjectFlagOffset : Uint2B
   +0x076 WaitObjectPointerOffset : Uint2B

句柄表

句柄表是windows对象管理器用来管理句柄的结构,每个进程都包含一个执行体进程结构块(_EPROCESS),而该结构中的的ObjectTable字段就是句柄表的指针。
句柄表

_HANDLE_TABLE

 ACPI!_HANDLE_TABLE
   +0x000 NextHandleNeedingPool : Uint4B
   +0x004 ExtraInfoPages   : Int4B
   +0x008 TableCode        : Uint8B					一个指向顶层句柄表树节点的指针(低2位为句柄表层数)
   +0x010 QuotaProcess     : Ptr64 _EPROCESS
   +0x018 HandleTableList  : _LIST_ENTRY   
   +0x028 UniqueProcessId  : Uint4B					这个进程的 ProcessID
   +0x02c Flags            : Uint4B
   +0x02c StrictFIFO       : Pos 0, 1 Bit
   +0x02c EnableHandleExceptions : Pos 1, 1 Bit
   +0x02c Rundown          : Pos 2, 1 Bit
   +0x02c Duplicated       : Pos 3, 1 Bit
   +0x02c RaiseUMExceptionOnInvalidHandleClose : Pos 4, 1 Bit
   +0x030 HandleContentionEvent : _EX_PUSH_LOCK
   +0x038 HandleTableLock  : _EX_PUSH_LOCK
   +0x040 FreeLists        : [1] _HANDLE_TABLE_FREE_LIST
   +0x040 ActualEntry      : [32] UChar
   +0x060 DebugInfo        : Ptr64 _HANDLE_TRACE_DEBUG_INFO

_HANDLE_TABLE_ENTRY

ACPI!_HANDLE_TABLE_ENTRY
   +0x000 VolatileLowValue : Int8B
   +0x000 LowValue         : Int8B
   +0x000 InfoTable        : Ptr64 _HANDLE_TABLE_ENTRY_INFO
   +0x008 HighValue        : Int8B
   +0x008 NextFreeHandleEntry : Ptr64 _HANDLE_TABLE_ENTRY
   +0x008 LeafHandleValue  : _EXHANDLE
   +0x000 RefCountField    : Int8B
   +0x000 Unlocked         : Pos 0, 1 Bit
   +0x000 RefCnt           : Pos 1, 16 Bits
   +0x000 Attributes       : Pos 17, 3 Bits						句柄的属性
   +0x000 ObjectPointerBits : Pos 20, 44 Bits					内核对象指针
   +0x008 GrantedAccessBits : Pos 0, 25 Bits					句柄的访问掩码
   +0x008 NoRightsUpgrade  : Pos 25, 1 Bit
   +0x008 Spare1           : Pos 26, 6 Bits
   +0x00c Spare2           : Uint4B

windbg脚本

打印系统内所有对象类型的对象名和地址

r @$t0=(ObTypeIndexTable+0x10);
.for(r @$t8=2;poi(@$t0)!=0;r @$t0=@$t0+0x8;r @$t8=@$t8+1)
{
	r @$t1=poi(@$t0);
	.printf "name:%msu	address:%p	index:%d\n",@$t1+0x10,@$t1,@$t8;
}
.printf  "Enum Type Name end"

打印根目录对象或指定对象目录

// ObpRootDirectoryObject  根目录对象指针
r @$t0=poi(ObpRootDirectoryObject);
// 可选参数,目录对象地址
.if(${/d:$arg1})
{
	r @$t0 =  ${/f:$arg1};
}

.for(r @$t6=0; @$t6<0n37; r @$t6=@$t6+1;)
{
	r @$t2=poi(@$t0+(@$t6*0x08));
	.if(@$t2!=0)
	{
		r @$t2 = poi(@$t2+0x8);
		.printf "address:%p  ,Num:%d\n",@$t2,@$t6;
		!object @$t2  0x1;
	}
}


打印句柄所指对象

//两个参数分别为进程EPROCESS地址和HANDLE值
.if( ${/d:$arg1} ){
	r @$t0 = 	poi( ${$arg1}+0x418 ) ;	
	r @$t1 = by(@$t0 +0x8 ) &0x03;
	r @$t0 = poi(@$t0 +0x8 )&0xfffffffffffffffc;

	.if( ${/d:$arg2} ){
	r @$t2 = ( ${$arg2} / 0n4 )  /  0n256;
	r @$t3 = ( ${$arg2} / 0n4 )  % 0n256;
	
	.if( @$t1 == 1 ){
	r @$t0 = poi( @$t0 + @$t2 * 0x10 );
	}
	
	.if( @$t1 == 2 ){
	.printf "not support 3 layer";
	}

	r @$t0 = poi(@$t0+@$t3*0x10);
	!object  ((((@$t0>>0x14)<<0x4)|0xFFFF000000000000))+0x30;
	}
	.else{
	.printf "please entry eprocess and handle";
	}
}

参考资料

  • 《Windows内核原理与实现》
  • https://blog.csdn.net/joshua_yu/article/details/590266
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极光1234

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值