Windows核心執行體物件管理器的操作過程與分析
我之前寫過一個有關於物件管理的讀書筆記。但是這篇文章與前面的不同,這是我個人對物件管理器到底是什麼的一個分析,而且也是直接對WRK程式碼進行的閱讀。
執行體物件即我們通常所言的核心物件,我們知道Windows核心中有許多“管理器”,然而管理器並不是一個實體的存在而是一個抽象的概念。它更像是一系列相關函式和資料結構的集合。
《Windows Internals》中如此定義物件管理器:“本節將介紹Windows的物件管理器,即執行體內部負責建立、刪除、保護和跟蹤物件的元件”。
我們先從建立物件開始。依次是:建立物件、刪除物件、引用物件、解除引用物件、控制物件訪問、查詢物件、
一.建立物件
物件建立操作肯定從r3傳來。
針對每個物件型別都有各自的建立核心物件的函式。舉個例子,
NtCreateFile()
NtCreateEvent()
NtCreateTimer()
NtCreateKey()
NtCreateProcess()
NtCreateThread()
這些函式都是由相應的Zw版本對應而來的。
這些函式內部都是用了ObCreateObject()這個函式來建立物件。
ObCreateObject()函式主要做了兩件事
1.解析傳入的OBJECT_ATTRIBUTES結構到物件的OBJECT_CREATE_INFORMATION結構以及其他結構中。
2.呼叫ObpAllocateObject()函式建立物件。
我們主要關注ObpAllocateObject()函式怎麼建立的物件。
1 NTSTATUS 2 ObpAllocateObject ( 3 IN POBJECT_CREATE_INFORMATION ObjectCreateInfo, 4 IN KPROCESSOR_MODE OwnershipMode, 5 IN POBJECT_TYPE ObjectType OPTIONAL, 6 IN PUNICODE_STRING ObjectName, 7 IN ULONG ObjectBodySize, 8 OUT POBJECT_HEADER *ReturnedObjectHeader 9 ) 10 11 /*++ 12 13 Routine Description: 14 15 This routine allocates a new object including the object header 16 and body from pool and fill in the appropriate fields. 17 18 Arguments: 19 20 ObjectCreateInfo - Supplies the create information for the new object 21 22 OwnershipMode - Supplies the processor mode of who is going to own 23 the object 24 25 ObjectType - Optionally supplies the object type of the object being 26 created. If the object create info not null then this field must 27 be supplied. 28 29 ObjectName - Supplies the name of the object being created 30 31 ObjectBodySize - Specifies the size, in bytes, of the body of the object 32 being created 33 34 ReturnedObjectHeader - Receives a pointer to the object header for the 35 newly created objet. 36 37 Return Value: 38 39 An appropriate status value. 40 41 --*/ 42 43 { 44 ULONG HeaderSize; 45 POBJECT_HEADER ObjectHeader; 46 ULONG QuotaInfoSize; 47 ULONG HandleInfoSize; 48 ULONG NameInfoSize; 49 ULONG CreatorInfoSize; 50 POBJECT_HEADER_QUOTA_INFO QuotaInfo; 51 POBJECT_HEADER_HANDLE_INFO HandleInfo; 52 POBJECT_HEADER_NAME_INFO NameInfo; 53 POBJECT_HEADER_CREATOR_INFO CreatorInfo; 54 POOL_TYPE PoolType; 55 56 PAGED_CODE(); 57 58 // 59 // Compute the sizes of the optional object header components. 60 // 61 62 if (ObjectCreateInfo == NULL) { 63 64 QuotaInfoSize = 0; 65 HandleInfoSize = 0; 66 NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); 67 CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );//OBJECT_HEADER_CREATOR_INFO一定存在 68 69 } else { 70 71 // 72 // The caller specified some additional object create info 73 // 74 // First check to see if we need to set the quota 75 // 76 77 if (((ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge || 78 ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge || 79 ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA) && 80 PsGetCurrentProcess() != PsInitialSystemProcess) || 81 (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { 82 //這時,配額頭才是存在的 83 QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO ); 84 85 86 } else { 87 88 QuotaInfoSize = 0; 89 } 90 91 // 92 // Check if we are to allocate space to maintain handle counts 93 // 94 95 if (ObjectType->TypeInfo.MaintainHandleCount) { 96 //這時,控制程式碼頭才是存在的 97 HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO ); 98 99 100 } else { 101 102 HandleInfoSize = 0; 103 } 104 105 // 106 // Check if we are to allocate space for the name 107 // 108 109 if (ObjectName->Buffer != NULL) { 110 //這時,名字頭才是存在的 111 NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); 112 113 114 } else { 115 116 NameInfoSize = 0; 117 } 118 119 // 120 // Finally check if we are to maintain the creator info 121 // 122 123 if (ObjectType->TypeInfo.MaintainTypeList) { 124 125 CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); 126 127 } else { 128 129 CreatorInfoSize = 0; 130 } 131 } 132 133 // 134 // Now compute the total header size 135 // 136 //計算整個頭的大小 137 HeaderSize = QuotaInfoSize + 138 HandleInfoSize + 139 NameInfoSize + 140 CreatorInfoSize + 141 FIELD_OFFSET( OBJECT_HEADER, Body ); 142 143 // 144 // Allocate and initialize the object. 145 // 146 // If the object type is not specified or specifies nonpaged pool, 147 // then allocate the object from nonpaged pool. 148 // Otherwise, allocate the object from paged pool. 149 // 150 151 if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) { 152 //為啥等於空時要用非分頁池? 153 PoolType = NonPagedPool; 154 155 } else { 156 157 PoolType = PagedPool; 158 } 159 160 ObjectHeader = ExAllocatePoolWithTag( PoolType, 161 HeaderSize + ObjectBodySize, 162 (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |//這裡體現了物件型別中國Key欄位的作用 163 PROTECTED_POOL ); 164 165 if (ObjectHeader == NULL) { 166 167 return STATUS_INSUFFICIENT_RESOURCES; 168 } 169 170 // 171 // Now based on if we are to put in the quota, handle, name, or creator info we 172 // will do the extra work. This order is very important because we rely on 173 // it to free the object. 174 // 175 176 if (QuotaInfoSize != 0) { 177 //設定配額頭OBJECT_HEADER_QUOTA_INFO 178 QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader; 179 QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge; 180 QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge; 181 QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge; 182 QuotaInfo->ExclusiveProcess = NULL; 183 ObjectHeader = (POBJECT_HEADER)(QuotaInfo + 1); 184 } 185 186 if (HandleInfoSize != 0) { 187 //設定Handle頭OBJECT_HEADER_HANDLE_INFO 188 HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader; 189 HandleInfo->SingleEntry.HandleCount = 0; 190 ObjectHeader = (POBJECT_HEADER)(HandleInfo + 1); 191 } 192 193 if (NameInfoSize != 0) { 194 //設定Name頭OBJECT_HEADER_NAME_INFO 195 NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader; 196 NameInfo->Name = *ObjectName; 197 NameInfo->Directory = NULL; 198 NameInfo->QueryReferences = 1; 199 200 if ( (OwnershipMode == KernelMode) 201 && 202 (ObjectCreateInfo != NULL) 203 && 204 (ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE) ) { 205 206 NameInfo->QueryReferences |= OBP_NAME_KERNEL_PROTECTED; 207 } 208 209 ObjectHeader = (POBJECT_HEADER)(NameInfo + 1); 210 } 211 212 if (CreatorInfoSize != 0) { 213 //設定建立資訊頭OBJECT_HEADER_CREATOR_INFO 214 CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader; 215 CreatorInfo->CreatorBackTraceIndex = 0; 216 CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId;//把建立物件的程式的資訊存在建立資訊頭中 217 InitializeListHead( &CreatorInfo->TypeList );//加入到同一型別的核心物件的列表 218 219 PERFINFO_ADD_OBJECT_TO_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectType); 220 221 ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1); 222 } 223 224 // 225 // Compute the proper offsets based on what we have 226 // 227 228 //設定OBJECT_HEADER中幾個可選頭的偏移值 229 if (QuotaInfoSize != 0) { 230 231 ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize); 232 233 } else { 234 235 ObjectHeader->QuotaInfoOffset = 0; 236 } 237 238 if (HandleInfoSize != 0) { 239 240 ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize); 241 242 } else { 243 244 ObjectHeader->HandleInfoOffset = 0; 245 } 246 247 if (NameInfoSize != 0) { 248 249 ObjectHeader->NameInfoOffset = (UCHAR)(NameInfoSize + CreatorInfoSize); 250 251 } else { 252 253 ObjectHeader->NameInfoOffset = 0; 254 } 255 256 // 257 // Say that this is a new object, and conditionally set the other flags 258 // 259 //新增標誌位 260 ObjectHeader->Flags = OB_FLAG_NEW_OBJECT; 261 262 if (CreatorInfoSize != 0) { 263 264 ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO; 265 } 266 267 if (HandleInfoSize != 0) { 268 269 ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY; 270 } 271 272 // 273 // Set the counters and its type 274 // 275 276 ObjectHeader->PointerCount = 1;//引用數 277 ObjectHeader->HandleCount = 0;//控制程式碼引用數 278 ObjectHeader->Type = ObjectType; 279 280 // 281 // Initialize the object header. 282 // 283 // N.B. The initialization of the object header is done field by 284 // field rather than zeroing the memory and then initializing 285 // the pertinent fields. 286 // 287 // N.B. It is assumed that the caller will initialize the object 288 // attributes, object ownership, and parse context. 289 // 290 291 //根據使用者傳入的引數設定OBJECT_HEADER的Flags值 292 if (OwnershipMode == KernelMode) { 293 294 ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT; 295 } 296 297 if (ObjectCreateInfo != NULL && 298 ObjectCreateInfo->Attributes & OBJ_PERMANENT ) { 299 300 ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT; 301 } 302 303 if ((ObjectCreateInfo != NULL) && 304 (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { 305 306 ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT; 307 } 308 309 ObjectHeader->ObjectCreateInfo = ObjectCreateInfo; 310 ObjectHeader->SecurityDescriptor = NULL; 311 312 if (ObjectType != NULL) { 313 314 InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects); 315 316 if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) { 317 318 ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects; 319 } 320 } 321 322 323 //返回的值 324 *ReturnedObjectHeader = ObjectHeader; 325 326 return STATUS_SUCCESS; 327 }
我們可以看到實質上核心物件就是用ExAllocatePoolWithTag分配的一塊記憶體。
這個是OBJECT_HEADER,大量的操作都針對這個位進行。
看以看到物件頭和所有可選頭的填充都在這個函式中完成。
1 typedef struct _OBJECT_HEADER 2 { 3 LONG PointerCount;//引用計數 4 union 5 { 6 LONG HandleCount;//控制程式碼計數 7 PVOID NextToFree; 8 }; 9 POBJECT_TYPE Type;//物件型別 10 UCHAR NameInfoOffset;//OBJECT_HEADER_NAME_INFO偏移 11 UCHAR HandleInfoOffset;//OBJECT_HEADER_HANDLE_INFO偏移 12 UCHAR QuotaInfoOffset;//OBJECT_HEADER_QUOTA_INFO偏移 13 UCHAR Flags;//標明此物件各種的屬性的識別符號 14 union 15 { 16 POBJECT_CREATE_INFORMATION ObjectCreateInfo;//OBJECT_CREATE_INFORMATION結構地址 17 PVOID QuotaBlockCharged; 18 }; 19 PVOID SecurityDescriptor;//安全描述符結構地址 20 QUAD Body;//物件體地址 21 } OBJECT_HEADER, *POBJECT_HEADER;
前面說ObCreateObject()函式“解析傳入的OBJECT_ATTRIBUTES結構到物件的OBJECT_CREATE_INFORMATION結構以及其他結構中。”
在ObCreateObject()中的解析,在ObpAllocateObject()中派上了用途。ObpAllocateObject()不再有OBJECT_ATTRIBUTES結構作為引數。
二.刪除物件
在ObDereferenceObject()中,會判斷OBJECT_HEADER中的PointerCount值,如果為0就呼叫ObpDeleteObject()函式來進行刪除。
ObpDeleteObject函式先把物件從OBJECT_HEADER_CREATOR_INFO.TypeList列表中刪除,然後釋放名字UNICODE_STRING的緩衝區,最後呼叫OBJECT_TYPE中定義的DeleteProcedure函式。
三.引用物件和解除引用物件
比如函式ObReferenceObjectByPointer()
引用和解除引用物件是在獲取了OBJECT指標後,用OBJECT_TO_OBJECT_HEADER宏轉換成OBJECT_HEADER指標,然後用InterlockedIncrement()加鎖修改這個值。
四.控制物件訪問
在開啟一個物件時,引數中要填寫預期的操作以申請許可權。
相關文章
- ART執行時為新建立物件分配記憶體的過程分析2015-07-22物件記憶體
- HiveSQL的執行過程分析2014-05-08HiveSQL
- sql執行過程分析2011-04-18SQL
- 程式執行過程記憶體分析詳解2021-01-02記憶體
- 原始碼分析OKHttp的執行過程2018-10-27原始碼HTTP
- Mapreduce(二):MR的執行過程分析2015-09-16
- Informix 執行緒sleep 分析過程2023-03-10ORM執行緒
- Java 執行緒池的建立過程分析2016-11-04Java執行緒
- windows核心原理分析之DPC函式的執行(1)2015-06-04Windows函式
- crtmpserver 執行過程簡明分析2018-05-14Server
- knockout原始碼分析之執行過程2016-07-17原始碼
- PostgreSQL的insert語句執行過程分析2022-03-18SQL
- Tomcat停機過程分析與執行緒處理方法2018-02-26Tomcat執行緒
- windows核心程式設計--windows程式的執行2020-04-04Windows程式設計
- 指令的執行過程2024-08-11
- 分析oc物件的記憶體結構及其建立過程2019-03-10物件記憶體
- mybatis-spring sql執行過程分析2017-12-08MyBatisSpringSQL
- Java 執行過程中的記憶體模型2021-01-31Java記憶體模型
- 程式執行過程中的記憶體活動2012-04-21記憶體
- SAP Spartacus 裡的 cxOutletRef 指令執行過程分析2021-05-15
- 軟體測試過程中的度量與分析2012-06-14
- JVM核心之JVM執行和類載入全過程2018-04-23JVM
- Windows啟動過程(MBR引導過程分析)2017-06-12Windows
- sql 執行過程2013-03-28SQL
- Redis 命令的執行過程2018-03-30Redis
- jsp的執行過程2024-03-18JS
- laravel 應用層執行過程原始碼分析2021-03-29Laravel原始碼
- 線上定時指令碼執行慢,分析過程2018-03-15指令碼
- JVM 執行緒堆疊分析過程詳解2015-03-20JVM執行緒
- Redis 持久化 RDB 與 AOF的執行過程UYUT2022-03-01Redis持久化
- Windows核心程式管理器解析2016-04-22Windows
- 執行緒池建立執行緒的過程2020-10-21執行緒
- openGauss核心:SQL解析過程分析2022-06-28SQL
- windows程式/執行緒建立過程 --- windows作業系統學習2013-12-06Windows執行緒作業系統
- 通過 HelloWorld 瞭解 Java 程式執行過程以及執行時記憶體2018-08-28Java記憶體
- Mybatis原始碼分析(五)探究SQL語句的執行過程2019-03-10MyBatis原始碼SQL
- MYSQL sql執行過程的一些跟蹤分析(一)2019-01-19MySql
- javascript引擎執行的過程的理解--執行階段2019-02-28JavaScript