日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【旧文章搬运】Win7可变对象头结构之InfoMask解析

發布時間:2025/4/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【旧文章搬运】Win7可变对象头结构之InfoMask解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文發表于百度空間,2010-08-11
==========================================================================

?對Windows對象管理有一定了解的人都知道,在固定對象頭(OBJECT_HEADER)前面是一塊可變區域,稱為可變對象頭,它所包含的結構內容并不固定。在Win7之前,可變區域實際有哪些結構,通常是由OBJECT_HEADER中的幾個偏移值指出。如下:

lkd> dt _OBJECT_HEADER(WinXP SP2)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

?

其中的NameInfoOffset、HandleInfoOffset、QuotaInfoOffset就是用于指出該結構相對于固定對象頭(OBJECT_HEADER)的偏移。
如果NtGlobalFlags設置了MaintainTypeList標志,那么由于CreatorInfo的存在,這個部分還會更復雜一點,還得依據OBJECT_HEADER->Flag中的標志位來作一些判斷才能具體確定某個結構的具體偏移。
在Win7中,這一部分顯然經過了精心設計,一個InfoMask域再加一個ObpInfoMaskToOffset表就搞定了,顯得更加簡捷快速。
顧名思義,InfoMask就是一個掩碼,它的每一位表示可變對象頭中某個指定的結構是否存在。在Win7中,對象的結構大體上沒有太大變化,固定對象頭的前面仍然是可變對象頭。
根據不同類型的對象及實際情況,可變對象頭可能包含以下5個結構中的一個或幾個:?

(Size=0x08)ntkrpamp!_OBJECT_HEADER_PROCESS_INFO (Size=0x10)ntkrpamp!_OBJECT_HEADER_QUOTA_INFO (Size=0x08)ntkrpamp!_OBJECT_HEADER_HANDLE_INFO (Size=0x10)ntkrpamp!_OBJECT_HEADER_NAME_INFO (Size=0x10)ntkrpamp!_OBJECT_HEADER_CREATOR_INFO

這些結構對應的掩碼分別為:

#define OB_INFOMASK_PROCESS_INFO 0x10 #define OB_INFOMASK_QUOTA 0x08 #define OB_INFOMASK_HANDLE 0x04 #define OB_INFOMASK_NAME 0x02 #define OB_INFOMASK_CREATOR_INFO 0x01

因為可變對象頭可能包含5種結構,每一種結構包括存在或不存在兩種情況,那么一共是2^5=32種結果。所以,ObpInfoMaskToOffset表定義如下:

BYTE ObpInfoMaskToOffset[32];

而存在的結構就要占據一定的空間,那么對象頭(OBJECT_HEADER)距PoolHeader的偏移就會因結構存在與否產生對應的變化,該偏移實際上也就是可變對象頭的總大小。該表的初始化是在ObInitSystem()中進行的。初始化代碼如下:

ULONG i = 0;ULONG offset = 0;do{offset = 0;if ( i & OB_INFOMASK_CREATOR_INFO )offset = sizeof(_OBJECT_HEADER_CREATOR_INFO);if ( i & OB_INFOMASK_NAME )offset += sizeof(_OBJECT_HEADER_NAME_INFO);if ( i & OB_INFOMASK_HANDLE )offset += sizeof(_OBJECT_HEADER_HANDLE_INFO);if ( i & OB_INFOMASK_QUOTA )offset += sizeof(_OBJECT_HEADER_QUOTA_INFO);if ( i & OB_INFOMASK_PROCESS_INFO )offset += sizeof(_OBJECT_HEADER_PROCESS_INFO);ObpInfoMaskToOffset[i++] = offset;}while(i<32);初始化完成后表的內容如下: kd> db ObpInfoMaskToOffset 83b97e60 00 10 10 20 08 18 18 28-10 20 20 30 18 28 28 38 ... ...(. 0.((8 83b97e70 08 18 18 28 10 20 20 30-18 28 28 38 20 30 30 40 ...(. 0.((8 00@

可以看到,根據掩碼不同,那么實際存在的可變頭結構就不同,其大小是掩碼所代表的有效結構的大小之和。

可變頭為空,那么偏移自然為0,若5個結構都包含了,那么偏移就是所有結構之和,也就是0x40。
所以,根據對象頭中的掩碼InfoMask,就可以確定可變頭部分的大小和具體包含的結構,及每一個結構相對于固定對象頭(OBJECT_HEADER)的實際偏移。
因為這個偏移是相對于固定對象頭(OBJECT_HEADER)往前的偏移,而在初始化過程中,這個偏移的值卻又是依次累加的,所以后來加上的結構大小,在整個可變對象頭中反而比較靠上,掩碼小的結構離固定對象頭越近。我以一個明確的圖來說明這些信息:

舉個例子,比如某對象的ObjectHeader->InfoMask值為9,那么就說明它包含了_OBJECT_HEADER_CREATOR_INFO(對應掩碼為1)和_OBJECT_HEADER_QUOTA_INFO(對應掩碼為8)兩個結構,ObpInfoMaskToOffset[9]的值為0x20,正是這兩個結構的大小之和。并且,由于掩碼小的結構離固定對象頭越近,所以可以明確知道ObjectHeader-0x10是_OBJECT_HEADER_CREATOR_INFO結構,ObjectHeader->0x20是_OBJECT_HEADER_QUOTA_INFO結構。
下面我以一個實際的例子來詳細說明。

kd> dt _OBJECT_TYPE 84e4aa38 //查看對象類型 nt!_OBJECT_TYPE+0x000 TypeList : _LIST_ENTRY [ 0x8603a548 - 0x863593e8 ] //為了便觀察到同類型的所有對象,我設置了MaintainTypeList標志+0x008 Name : _UNICODE_STRING "WindowStation"+0x010 DefaultObject : (null) +0x014 Index : 0x14 ''+0x018 TotalNumberOfObjects : 6+0x01c TotalNumberOfHandles : 0x35+0x020 HighWaterNumberOfObjects : 6+0x024 HighWaterNumberOfHandles : 0x3f+0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER+0x078 TypeLock : _EX_PUSH_LOCK+0x07c Key : 0x646e6957+0x080 CallbackList : _LIST_ENTRY [ 0x84e4aab8 - 0x84e4aab8 ] kd> !pool 0x8603a548 //觀察第一個對象的內存池分配 Pool page 8603a548 region is Nonpaged pool8603a500 size: 18 previous size: 48 (Allocated) MmSi *8603a518 size: b0 previous size: 18 (Allocated) *Wind (Protected)Owning component : Unknown (update pooltag.txt)8603a5c8 size: 78 previous size: b0 (Allocated) EtwR (Protected) ...

可以看到,內存池的分配從8603a518開始。

kd> dd 8603a518 8603a518 04160003 e46e6957 00000000 00000068 8603a528 00000094 83b44c40 8a42edb8 00000002 8603a538 90ca2cd8 000e000e 90d95cd0 00000000 8603a548 86062f80 84e4aa38 0000016c 00000000 8603a558 0000000c 00000005 00000000 000f0014 8603a568 83b44c40 90d9c23e 00000000 86022848 8603a578 8604d8c8 91badaa0 00000000 ffabb8e8 8603a588 00000000 00000000 00000000 00000000

根據對象的TypeIndex為0x14,及TypeIndex在OBJECT_HEADER中的偏移,不難看出8603a558就是對象頭。

kd> dt _OBJECT_HEADER 8603a558 nt!_OBJECT_HEADER+0x000 PointerCount : 12+0x004 HandleCount : 5+0x004 NextToFree : 0x00000005 +0x008 Lock : _EX_PUSH_LOCK+0x00c TypeIndex : 0x14 ''+0x00d TraceFlags : 0 ''+0x00e InfoMask : 0xf ''+0x00f Flags : 0 ''+0x010 ObjectCreateInfo : 0x83b44c40 _OBJECT_CREATE_INFORMATION+0x010 QuotaBlockCharged : 0x83b44c40 +0x014 SecurityDescriptor : 0x90d9c23e +0x018 Body : _QUAD

可以看到,InfoMask為0xF=8+4+2+1,也就是說包含了_OBJECT_HEADER_QUOTA_INFO(掩碼為8)、_OBJECT_HEADER_HANDLE_INFO(掩碼為4)、_OBJECT_HEADER_NAME_INFO(掩碼為2)和_OBJECT_HEADER_CREATOR_INFO(掩碼為1)這四個結構。掩碼最大的結構_OBJECT_HEADER_QUOTA_INFO在最上面:

kd> dt _OBJECT_HEADER_QUOTA_INFO 8603a520 nt!_OBJECT_HEADER_QUOTA_INFO+0x000 PagedPoolCharge : 0+0x004 NonPagedPoolCharge : 0x68+0x008 SecurityDescriptorCharge : 0x94+0x00c SecurityDescriptorQuotaBlock : 0x83b44c40 //加上該結構的大小,就是下一個結構_OBJECT_HEADER_HANDLE_INFO kd> dt _OBJECT_HEADER_HANDLE_INFO 8603a520+10 nt!_OBJECT_HEADER_HANDLE_INFO+0x000 HandleCountDataBase : 0x8a42edb8 _OBJECT_HANDLE_COUNT_DATABASE+0x000 SingleEntry : _OBJECT_HANDLE_COUNT_ENTRY //同理,下一個結構是_OBJECT_HEADER_NAME_INFO kd> dt _OBJECT_HEADER_NAME_INFO 8603a520+10+8 nt!_OBJECT_HEADER_NAME_INFO+0x000 Directory : 0x90ca2cd8 _OBJECT_DIRECTORY+0x004 Name : _UNICODE_STRING "WinSta0"+0x00c ReferenceCount : 0 //然后是_OBJECT_HEADER_CREATOR_INFO kd> dt _OBJECT_HEADER_CREATOR_INFO 8603a520+10+8+10 nt!_OBJECT_HEADER_CREATOR_INFO+0x000 TypeList : _LIST_ENTRY [ 0x86062f80 - 0x84e4aa38 ]+0x008 CreatorUniqueProcess : 0x0000016c +0x00c CreatorBackTraceIndex : 0+0x00e Reserved : 0 kd> !process 16c 0 Searching for Process with Cid == 16c Cid Handle table at 93365000 with 553 Entries in use PROCESS 84e39d40 SessionId: 0 Cid: 016c Peb: 7ffd4000 ParentCid: 0140DirBase: 1ee8a0a0 ObjectTable: 90cae1f8 HandleCount: 75.Image: wininit.exe

查看WinSta0的創建者,發現是wininit.exe~~

理解上以上結構,相信對于獲取可變對象頭中某個結構的位置已經不在話下。實際上,Win7的內核導出了一個函數專門用于獲取對象頭中的_OBJECT_HEADER_NAME_INFO結構。該函數就是ObQueryNameInfo(),還原成源碼如下:

PVOID ObQueryNameInfo(IN PVOID Object) {POBJECT_HEADER ObjectHeader=OBJECT_TO_OBJECT_HEADER(Object);BYTE InfoMask=ObjectHeader->InfoMask;ULONG NameInfo=0;if(InfoMask & OB_INFOMASK_NAME){NameInfo=(ULONG)ObjectHeader - ObpInfoMaskToOffset[InfoMask & (OB_INFOMASK_NAME+OB_INFOMASK_CREATOR_INFO)];}else{NameInfo=0;}return (PVOID)NameInfo; }

源碼很好理解,取ObjectHeader->InfoMask,判斷OB_INFOMASK_NAME標志位是否有效,若無效說明可變頭中并沒有這個結構。若有效,就根據掩碼取_OBJECT_HEADER_NAME_INFO靠下的兩個結構的大小(包括_OBJECT_HEADER_NAME_INFO和_OBJECT_HEADER_CREATOR_INFO兩個結構),然后對象頭減去這個偏移量,就是_OBJECT_HEADER_NAME_INFO結構的位置了,結合前面的結構圖,相信不難理解。

實際上,根據掩碼與結構大小的對應關系,完全可以用一個更一般的方式來獲取相應的可變對象頭結構信息。如下:

PVOID GetSpecificObjectHeaderInfo(PVOID Object,BYTE HeaderMask) {POBJECT_HEADER ObjectHeader=(POBJECT_HEADER)OBJECT_TO_OBJECT_HEADER(Object);BYTE InfoMask=ObjectHeader->InfoMask;BYTE MaxMask=0;ULONG HeaderInfo=0;if(InfoMask & HeaderMask){MaxMask=2*HeaderMask-1;HeaderInfo=(ULONG)ObjectHeader - ObpInfoMaskToOffset[InfoMask & MaxMask];}else{HeaderInfo=0;}return (PVOID)HeaderInfo; }

參數解釋:

?Object : 欲操作的對象
?HeaderMask : 要獲取的對象結構對應的掩碼
?函數中的ObpInfoMaskToOffset可以自己定義,反正內容和初始化方式已經清楚了,內容一樣用起來沒什么影響
這樣,直接用GetSpecificObjectHeaderInfo(Object,OB_INFOMASK_NAME)就可以代替ObQueryNameInfo(Object)了。
如果要獲取_OBJECT_HEADER_HANDLE_INFO結構,那么GetSpecificObjectHeaderInfo(Object,OB_INFOMASK_HANDLE)就可以了,,獲取其它結構信息也是如此,非常方便~~

關于Win7的可變對象頭,就說到這里~~

轉載于:https://www.cnblogs.com/achillis/p/10183526.html

總結

以上是生活随笔為你收集整理的【旧文章搬运】Win7可变对象头结构之InfoMask解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。