JIURL play the object of Win2k: JIURL Home: http://jiurl.yeah.net Date: 2003-7-30
Windows 2000 has the following 27 kinds of objects Directory Thread Mutant Controller Type Profile Event SymbolicLink Section EventPair Desktop Timer File WindowStation Driver WmiGuid Token Device IoCompletion Process Adapter Key Job WaitablePort Port Callback Semaphore. These 27 names fully explain how important the object is how important Win2K. Figure 1 Let's first look at the object, as shown in Figure 1. Objects consist at least by object heads and objects, and may have some relevant information before the object header (lower than the pair address). For different types of objects, the definition of the object head is the same, and the size of the object is completely different. Optional information, the object head, the object body is tightly hidden. You can also use the following tools to increase the understanding of the object. WinObj in http://www.sysinternals.com, you can observe the objects in the namespace. "Programming The Microsoft Windows Driver Model" Tools in the book CD. These two tool functions are similar. Object heads and optional structures Object_Header have four optional structures, Object_name, Object_Handle_DB, Object_quota_CHARGES, OBJECT_CREATOR_INFO. Whether they exist, they will be described by the relevant domains in Object_Header. The first three structures exist that their position relative to Object_Header is described by the relevant fields in Object_Header. Only Object_creator_info structure, if there is, it is located before Object_Header, and next to Object_Header. Object_Header is defined as follows, size 24 (decimal) byte, is 6 DWORD. (There is no specifically indicated, all types of this article define some chapters from the "undocumented Windows 2000 Secrets: a Programmer's Cookbook" book and its represented source code.
Since this part does not have any official document, the error is inevitable, everyone must have some doubts about these types) typef struct _object_Header {/ * 000 * / dword Pointercount; // Number of References / * 004 * / DWORD HANDECOUNT; / / number of open handles / * 008 * / POBJECT_TYPE ObjectType; / * 00C * / BYTE NameOffset; // -> OBJECT_NAME / * 00D * / BYTE HandleDBOffset; // -> OBJECT_HANDLE_DB / * 00E * / BYTE QuotaChargesOffset; // - > OBJECT_QUOTA_CHARGES / * 00F * / BYTE ObjectFlags; // OB_FLAG _ * / * 010 * / union {// OB_FLAG_CREATE_INFO ObjectCreateInfo: QuotaBlock / * 010 * / PQUOTA_BLOCK QuotaBlock; / * 010 * / POBJECT_CREATE_INFO ObjectCreateInfo; / * 014 * /?} ; / * 014 * / PSECURITY_DESCRIPTOR SecurityDescriptor; / * 018 * /} OBJECT_HEADER; .PointerCountntoskrnl.exe the API ObfReferenceObject (), ObReferenceObjectByHandle (), ObReferenceObjectByName (), and ObReferenceObjectByPointer () is the increase in PointerCount, ObfDereferenceObject () and ObdereferenceObject () is used to reduce this value. .Handlecount indicates how many of this object's open handle. ObjectType points to the pointer to the Object_Type structure. .Nameoffset minus the value of the nameOffset with the address of Object_Header to locate the Object_name section. If the nameOffset value is 0, this object_header does not have Object_name. Used to point out the name of the object, one of optional information. .HandPoffset subtracts the value of the HandledBoffset with the address of Object_Header to locate the Object_Handle_DB section. If the handledboffset value is 0, it means that this object_header does not have Object_Handle_DB. One of the options available. .QuotachargeSoffset minus the value of the qotachagesoffset with the address of Object_Header to locate the Object_quota_CHARGES section. If the quotachargesoffset value is 0, it means that this object_header does not have Object_quota_charges. One of the options available.
.ObjectFlags # define OB_FLAG_CREATE_INFO 0x01 // has OBJECT_CREATE_INFO # define OB_FLAG_KERNEL_MODE 0x02 // created by kernel # define OB_FLAG_CREATOR_INFO 0x04 // has OBJECT_CREATOR_INFO # define OB_FLAG_EXCLUSIVE 0x08 // OBJ_EXCLUSIVE # define OB_FLAG_PERMANENT 0x10 // OBJ_PERMANENT # define OB_FLAG_SECURITY 0x20 // has security descriptor #define ob_flag_single_process 0x40 // no handledblist That is, the 0th, OB_FLAG_CREATE_INFO bit. 1st, ob_flag_kernel_mode bit. 2nd, ob_flag_creator_info bit. 3rd place, ob_flag_exclusive bit. 4th, ob_flag_permanent bit. 5th, ob_flag_security bits. The 6th, ob_flag_single_process bit. If the OB_FLAG_CREATOR_INFO bit is 1, it is next to an Object_creator_info structure before Object_Header. Note that Object_create_info is different from Object_creator_info. .Quotablock or .ObjectCreateInfo If the ObjectFlag_create_info bit is 1, here is ObjectCreateInfo, a pointer, pointing to an Object_create_info structure. Object_create_info is one of optional information. Otherwise, here is Quotablock, a pointer, pointing to a quota_block structure, providing information about the use of Paged and Non-Paged Memory pools. PSPDefaultquoTablock A global variable saves a defaultquoTablock. Many addresses in Quotablock in the quotablock are the same as PSPDefaultQuoTablock, pointing to DefaultQuoTablock. The value of this Union can be NULL. . ScurityDescriptor If the ObjectFlag_Security bit is 1, SecurityDescriptor is a pointer, pointing to a security_descriptor structure. If the ObjectFlags's ob_flag_security bit is 0, the securityDescriptor value is NULL. OBJECT_NAME defined as typedef struct _OBJECT_NAME {/ * 000 * / POBJECT_DIRECTORY Directory; / * 004 * / UNICODE_STRING Name; / * 00C * / DWORD Reserved; / * 010 * /} OBJECT_NAME; .Directory point where the corresponding Directory Directory Object. Can be empty. The name of the .name object is a Unicode_String structure, the Unicode_String structure is defined in the DDK as follows.
Typedef struct _unicode_string {ushort length; ushort maximumlength; pwstr buffer;} unicode_string * punicode_string; .ReServed reserves other options. We will introduce later. Let's take a look at an actual example, a Directory type object called "/", which is actually the root object of Directory.
kd> object / object / Object:!! 8141ecd0 Type: (81452820) DirectoryObjectHeader: 8141ecb8HandleCount: 0 PointerCount: 34Directory Object: 00000000 Name: / 120 symbolic links snapped through this directoryHashBucket [00]: 8141b930 Directory 'ArcName'HashBucket [01] : e2f7b600 Port 'SeLsaCommandPort'HashBucket [03]: e1007390 Key' / REGISTRY'HashBucket [07]: e2bb16e0 Port 'DbgUiApiPort'HashBucket [09]: 810e7e00 Directory' NLS'HashBucket [10]: 8141ea50 SymbolicLink 'DosDevices'HashBucket [13 ]: e14088a0 Port 'SeRmCommandPort'HashBucket [14]: 810e8540 Mutant' NlsCacheMutant'e2fdb4c0 Port 'LsaAuthenticationPort'81421450 Device' Dfs'810fc870 Event 'LanmanServerAnnounceEvent'HashBucket [16]: 81416530 Directory' Driver'HashBucket [17]: e17c79c0 Port ' DbgSsApiPort'HashBucket [18]: 81437d30 Directory 'WmiGuid'HashBucket [19]: 8141b850 Directory' Device'HashBucket [20]: 810f68d0 Directory 'Windows'HashBucket [21]: 810a7e70 Event' SAM_SERVICE_STARTED'HashBucket [22]: 810f67f0 Directory ' RP C Control'e1408aa0 Port 'SmApiPort'81422af0 Device' Fat'HashBucket [23]: 810e8730 Directory 'BaseNamedObjects'HashBucket [24]: 8141eb10 Directory' ?? '81416450 Directory' FileSystem'HashBucket [26]: 8141ebf0 Directory 'ObjectTypes'HashBucket [27]: 8141ba10 Directory 'Security'e302e6e0 Port' ErrorLogPort'HashBucket [31]: 8141bbb0 SymbolicLink 'SystemRoot'HashBucket [32]: 8141d2d0 Directory' Callback'HashBucket [33]: 810ab330 Event 'EFSInitEvent'810f7df0 Event' SeLsaInitEvent'810ec9d0 Event '
UNIQUESessionIDEvent'Hashbucket [35]: 810f5f50 Directory 'knowndlls' // From the output we can see ObjectHeader: 8141ECB8, ObjectHeader structure size is 24 bytes, which is 6 DWORD. kd> dd 8141ecb8 l 6dd 8141ecb8 l 68141ecb8 00000023 00000000 81452820 320000108141ecc8 00000001 e10010f8 // analyze the value of each field of the structure ObjectHeader / * 000 * / DWORD PointerCount; // number of references00000023 / * 004 * / DWORD HandleCount; / / number of open handles00000000 / * 008 * / POBJECT_TYPE ObjectType; 81452820 / * 00C * / BYTE NameOffset; // -> OBJECT_NAME10 // there OBJECT_NAME / * 00D * / BYTE HandleDBOffset; // -> OBJECT_HANDLE_DB00 // no OBJECT_HANDLE_DB / * 00E * / BYTE QuotaChargesOffset; // -> OBJECT_QUOTA_CHARGES00 // no OBJECT_QUOTA_CHARGES / * 00F * / BYTE ObjectFlags; // OB_FLAG_ * 32 // 32 (hex) = 00110010 (bin), i.e. OB_FLAG_KERNEL_MODE, OB_FLAG_PERMANENT, OB_FLAG_SECURITY 3 which is set up. / * 010 * / union {// OB_FLAG_CREATE_INFO ObjectCreateInfo: QuotaBlock / * 010 * / PQUOTA_BLOCK QuotaBlock; / * 010 * / POBJECT_CREATE_INFO ObjectCreateInfo; / * 014 * /?}; 00000001 // OB_FLAG_CREATE_INFO bit is not set up, but the value It is not a pqueota_block quotablock. / * 014 * / psecurity_descriptor securityDescriptor; E10010F8 // OB_FLAG_SECURITY flag is set up, SecurityDescriptor is not empty. Here is a Psecurity_Descriptor pointer, we will discuss the four options in ObjectHeader in ObjectHead, both 0, indicating that there is no corresponding structure, the NameOffset value is 10, indicating a corresponding object_name structure, and is located in the ObjectHeader address - 0x10. Note that the object_name structure is 0x10 length. It can be seen that Object_name and ObjectHeader are next. Let's take a look at the contents of Object_name. KD> DD 8141ECB8-10 L 4DD 8141ECB8-10 L 48141ECA8 00000000 00040002 81452148 0000000000 / * 000 * / POBJECT_DIRECTORY DIRECTORY 0000000 // The Directory pointer is 0, because the object "/" is root, not in any directory. For example, Directory objects / knowndlls, it is not 0.
The value I got is 8141ECD0, which is the address of the object "/" ObjectBody. / * 004 * / UNICODE_STRING Name; 0002 0004 81452148 // UNICODE_STRING of PWSTR Buffer is 81452148kd> du 81452148du 8145214881452148 "/" // can see the name of the object called "/" / * 00C * / DWORD Reserved; 00000000 object header Simple analysis is here, for different types of objects, the format of the object head is the same. Directory Type Objects Now we continue to analyze the Directory type of objects. Different types of objects are different due to different uses, and the structure of the object is completely different, just like the case in Fig. 1. The content of some type of object is determined by this type of need. What is the purpose of the Directory type object? The Directory here is not a file system directory, but an object's directory, we can see this from the tool such as WinObj. The organization of the organism directory uses and the structure of the organization of the file system directory. From the previous use of the output, we can see that Kd can get the following information from the Directory type object. ! Kd> object / object / Object:! 8141ecd0 Type: (81452820) Directory ... HashBucket [13]: e14088a0 Port 'SeRmCommandPort'HashBucket [14]: 810e8540 Mutant' NlsCacheMutant'e2fdb4c0 Port 'LsaAuthenticationPort'81421450 Device' Dfs' 810fc870 Event 'LanmanServerAnnounceEvent'HashBucket [16]: 81416530 Directory' Driver'HashBucket [17]: e17c79c0 Port 'DbgSsApiPort' ... we look at the object volume OBJECT_DIRECTORY Directory type definition #define OBJECT_HASH_TABLE_SIZE 37typedef struct _OBJECT_DIRECTORY {/ * 000 * / POBJECT_DIRECTORY_ENTRY HashTable [OBJECT_HASH_TABLE_SIZE]; / * 094 * / POBJECT_DIRECTORY_ENTRY CurrentEntry; / * 098 * / BOOLEAN CurrentEntryValid; / * 099 * / BYTE Reserved1; / * 09A * / WORD Reserved2; / * 09C * / DWORD Reserved3; / * 0A0 * /} OBJECT_DIRECTORY; typedef struct _OBJECT_DIRECTORY_ENTRY {/ * 000 * / struct _OBJECT_DIRECTORY_ENTRY * NextEntry; / * 004 * / pOBJECT Object; / * 008 * /} OBJECT_DIRECTORY_ENTRY; OBJECT_DIRECTORY we can see from the definition is mainly a 37 ha Hig Table. Each item is a pointer to Object_Directory_ENTRY. Pointing a chain consisting of Object_Directory_ENTRY. The Object_Directory_entry structure has two domains. The first domain is a pointer to the next Object_Directory_entry, if the value is empty, indicating that the chain is over.
The second domain is a pointer to the object of a certain type of object. For example, in the above example, there is only one of the "Directory 'Driver'", the second domain of the item points to a Directory type object. When there is a new object you want to put in a directory, or when you need to find an object according to the object's name, you can determine which one of the 37 tables of the hash table is made through the hash function. What to do here is to make a certain calculation of each character of the object name, finally get a number, with this number with 37, take the amount, get some number in 0-36, to determine the hash Furniture. That is to use the hash function to calculate the object name to determine where the object should be in the hash table. If you want to know the specific algorithm of that hash function, you can follow the ObplooKuPDirectoryEntry function. Use Kd? ObplookuPDirectoryEntry to get the entry address of the function and break the address with the Softice. I followed Softice, this function has 3 parameters, the first parameter is a pointer to Object_Directory, specifying the directory of the lookup. The second parameter is a pointer to Unicode_String, specifies the name to look up. I will not describe it in detail. If you just want to find an object of a name, you can traverse every Object_Directory_entry of the entire directory, which is slow, but if there is any change in the hash function in the future, it will not be affected. The reason for using a hash table in Object_Directory is to speed up the lookup speed. If you don't use a hash table, you can only maintain an object chain list for each directory, but if you find the pointer to the object in a directory, you may have to traverse each object in this directory. The hash table is used, and the calculation of the hash function will quickly determine only a part of the object under this directory. The current number of items of the current directory object has 37. A factor affecting the number of items is usually how many objects may be in a directory, and should be as guaranteed to have only one item, or the chain is short, to ensure the speed of the lookup. Use in KD! Object command to observe several object directories, you can see the hash function used by Win2K, and 37 as the number of hash menu items, the effect is good, the object is more evenly distributed in the hash table, and many There is only one object corresponding to the hash table, and there are multiple objects of the object are not very long. Let's look at the actual example, from the previous KD output KD>! Object /! Object / Object: 8141ecd0 type: (81452820) DirectoryObjectHepe: 8141ecb8 ... We see object "Object" Ota in 8141ecb8, object body At 8141ECD0, the object head structure is 0x18, or it can be seen that the object head and the object body are close. Let's analyze the object of the directory type object "/".
kd> dd 8141ecd0 l a0 / 4dd 8141ecd0 l a0 / 48141ecd0 e1008c68 e2f7c008 00000000 e10073c88141ece0 00000000 00000000 00000000 e2bac0888141ecf0 00000000 e2bea1a8 e10001e8 000000008141ed00 00000000 e13891a8 e2bea328 000000008141ed10 e131eb08 e2baf188 e132f208 e1008ba88141ed20 e17b6708 e13d4268 e17b65e8 e135a7688141ed30 e1007f28 00000000 e10004a8 e10077088141ed40 00000000 00000000 00000000 e1008b088141ed50 e10003a8 e2ffe508 00000000 e17bca688141ed60 00000000 8141ecf4 00780001 00000000 foregoing is obtained using the output kd HashBucket [00]: 8141b930 Directory 'ArcName' ... HashBucket [14]: 810e8540 Mutant 'NlsCacheMutant'e2fdb4c0 Port' LsaAuthenticationPort'81421450 Device 'Dfs'810fc870 Event' LanmanServerAnnounceEvent '.. .HashBucket [35]: 810f5f50 Directory 'KnownDlls' value of 0 e1008c68 hash table, is POBJECT_DIRECTORY_ENTRYkd> dd e1008c68 l 2dd e1008c68 l 2e1008c68 00000000 8141b930 can see the points OBJECT_DIRECTORY_ENTRY .NextEntry is empty, as 8141b930 .Object Seeing with kd 8141b930 is really an object, and this object is an object of a directory type, through it, and some objects can be found.
!! Kd> object 8141b930 object 8141b930Object: 8141b930 Type: (81452820) DirectoryObjectHeader: 8141b918HandleCount: 0 PointerCount: 12Directory Object: 8141ecd0 Name: ArcNameHashBucket [00]: 813c4c90 SymbolicLink 'multi (0) disk (0) rdisk (0) partition ( 3) '814070d0 SymbolicLink' Multi (0) DISK (0) RDisk (0) 'Hashbucket [03]: 813C4C30 SymbolicLink' Multi (0) DISK (0) RDisk (0) Partition (4) 'Hashbucket [07]: 813c4bd0 SymbolicLink 'Multi (0) DISK (0) RDisk (0) Partition (5)' Hashbucket [10]: 813c4b70 symboliclink 'multi (0) Disk (0) RDisk (0) Partition (6)' Hashbucket [14]: 813c4b10 SymbolicLink 'Multi (0) DISK (0) RDisk (0) Partition (7)' Hashbucket [17]: 813C4AB0 SymbolicLink 'Multi (0) Disk (0) RDisk (0) Partition (8)' Hashbucket [21]: 813C4A50 SymbolicLink 'Multi (0) DISK (9)' Hashbucket [30]: 81420370 SymbolicLink 'Multi (0) Disk (0) RDisk (0) Partition (1)' Hashbucket [33]: 813e7230 SymbolicLink 'Multi (0) DISK (0) RDisk (0) Partition (2)' 813f9450 SymbolicLink 'Multi (0) Disk (0) FDISK (0)' has a group 14 of the hash table is E2BEA328, is a POBJECT_DIRECTORY_E ! NTRYkd> dd e2bea328 l 2dd e2bea328 l 2e2bea328 e13fee68 810e8540kd> object 810e8540 object 810e8540Object:! 810e8540 Type: (8141ccc0) MutantObjectHeader: 810e8528HandleCount: 14 PointerCount: 15Directory Object: 8141ecd0 Name: NlsCacheMutant // first item in the list, the next entry address e13fee68, target address 810e8540kd> dd e13fee68 l 2dd e13fee68 l 2e13fee68 e13c02e8 e2fdb4c0kd> object e2fdb4c0 object e2fdb4c0Object:!! e2fdb4c0 Type: (81416e80) PortObjectHeader: e2fdb4a8HandleCount: 1 PointerCount: 29Directory Object: 8141ecd0 Name: LsaAuthenticationPort // list In the second item, the next address is E13C02E8, the object address is E2FDB4C0KD>
! Dd e13c02e8 l 2dd e13c02e8 l 2e13c02e8 e178c908 81421450kd> object 81421450 object 81421450Object:! 81421450 Type: (81416920) DeviceObjectHeader: 81421438HandleCount: 0 PointerCount: 2Directory Object: 8141ecd0 Name: Dfs // third term of the list, the next address is e178c908, target address 81421450kd> dd e178c908 l 2dd e178c908 l 2e178c908 00000000 810fc870kd> object 810fc870 object 810fc870Object:!! 810fc870 Type: (8141e460) EventObjectHeader: 810fc858HandleCount: 1 PointerCount: 3Directory Object: 8141ecd0 Name: LanmanServerAnnounceEvent // list of In the four items, the next address is empty, indicating the end of the list, the object address is 810FC870 We see the pointer to the other object through the hash table and the list, including the directory object. Now let's know the address of the directory type object "/" ("/" is the root directory, which saves the pointer to the next directory object) We can find the objects in all directories. The address of the directory object "/" is saved in the global variable in the global variable in Win2k. On Win2K Build 2195, this global variable has an address of 8046ac24. You can get KD>? OBProotDirectoryObject? ObProotdirectoryObjectEValuate Expression: -2142852060 = 8046AC24DD 8046AC24 L 18046AC24 8141ECD0 We have seen 8141ECD0 is the address of the target object "/". In WinObj, we can't see any process, thread type objects. This is because there is no other object pointer in any Directory Object. They certainly exist, otherwise there is no need to get a process, thread type. They are actually EPROCESS and ETHREAD. That is to say, EPRocess, Ethread has Object_Header before it. !! Kd> process 8 0 process 8 0Searching for Process with Cid == 8PROCESS 8141e020 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000DirBase: 00030000 ObjectTable: 81452a68 TableSize: 108.Image: EPROCESS Address System // System process is ! 8141e020kd> object 8141e020 object 8141e020Object:! 8141e020 Type: (814524e0) ProcessObjectHeader: 8141e008HandleCount: 2 PointerCount: 36kd> dd 8141e008 l 6dd 8141e008 l 68141e008 00000024 00000002 814524e0 220000008141e018 804699c0 e1000618 many objects are not placed in any directory.
About Directory Object is introduced here. When the object of Type type introduces Object_Header, we did not analyze the / * 008 * / POBJECT_TYPE OBJECTTYPE; this domain. This is a very important domain, which is a pointer, pointing to information containing object types. ! Foregoing examples kd> object / object / Object:! 8141ecd0 Type: (81452820) Directory ... kd> dd 8141ecb8 l 6dd 8141ecb8 l 68141ecb8 00000023 00000000 81452820 320000108141ecc8 00000001 e10010f8kd know "/" Directory object type, that is, Find the relevant structure by POBJECT_TYPE OBJECTTYPE, the information obtained is obtained. In fact, Object_Type is also an object, it is the object of Type type. It is also like that shown in Figure 1, there is a pair of objects, objects, and optional information. We saw the "/" Type Object address as 81452820, we now analyze this Type Object's head. ! Kd> object 81452820 object 81452820Object:! 81452820 Type: (81452920) TypeObjectHeader: 81452808HandleCount: 0 PointerCount: 1Directory Object: 8141ebf0 Name: Directory of the head should 0x81452820-0x18 = 0x81452808 (next to the object because the head body, The head is in front, the head size is 0x18 bytes) from the output of the KD, and it is thought to see the KD is also.
kd> dd 81452808 l 6dd 81452808 l 681452808 00000001 00000000 81452920 1700002081452818 00000000 00000000 / * 000 * / DWORD PointerCount; // number of references00000001 / * 004 * / DWORD HandleCount; // number of open handles00000000 / * 008 * / POBJECT_TYPE ObjectType; 81452920 / * 00C * / BYTE NameOffset; // -> OBJECT_NAME20 / * 00D * / BYTE HandleDBOffset; // -> OBJECT_HANDLE_DB00 / * 00E * / BYTE QuotaChargesOffset; // -> OBJECT_QUOTA_CHARGES00 / * 00F * / BYTE ObjectFlags; // OB_FLAG_ * 17 17 (hex) = 00010111 (bin) OB_FLAG_CREATE_INFO OB_FLAG_KERNEL_MODE OB_FLAG_CREATOR_INFO OB_FLAG_PERMANENT / * 010 * / union {// OB_FLAG_CREATE_INFO ObjectCreateInfo: QuotaBlock / * 010 * / PQUOTA_BLOCK QuotaBlock; / * 010 * / POBJECT_CREATE_INFO ObjectCreateInfo; / * 014 *? /}; 00000000 / * 014 * / psecurity_descriptor securityDescriptor; 00000000 See the existence Object_name, and at the offset 20, that is, 0x81452808-0x20. kd> object address 81452808-20 l 4dd 81452808-20 l 4814527e8 8141ebf0 00140012 e1001948 00000000 // directory where dd is 8141ebf0kd> object 8141ebf0 object 8141ebf0Object:!! 8141ebf0 Type: (81452820) Directory ... // and in the WinObj As seen is the Directory type object "Type" KD> DU E1001948 Du E1001948E1001948 "Directory" // Type object's name is "Directory" Object_Header's flag OB_FLAG_CREATOR_INFO is set, indicating that the Object_creator_info structure exists, this optional structure is not like other three The need to indicate the offset, and this structure is in front of Object_Header before the Object_Header exists.
OBJECT_CREATOR_INFO structure is defined as typedef struct _OBJECT_CREATOR_INFO {/ * 000 * / LIST_ENTRY ObjectList; // OBJECT_CREATOR_INFO / * 008 * / HANDLE UniqueProcessId; / * 00C * / WORD Reserved1; / * 00E * / WORD Reserved2; / * 010 * /} OBJECT_CREATOR_INFO ; typedef struct _LIST_ENTRY {// from ntdef.hstruct _LIST_ENTRY * Flink; struct _LIST_ENTRY * Blink;} LIST_ENTRY, * PLIST_ENTRY, * RESTRICTED_POINTER PRLIST_ENTRY; .ObjectList objects of the same type are the doubly linked list chained together. .UniqueProcessID is a process ID that creates this object. // Due to the head of the object, it is close to the object head, the size is 0x10 bytes, so KD> DD 81452808-10 L 4DD 81452808-10 L 4DD 81452808-10 L 4814527F8 814526F8 814528F8 000000 million 000000 / * 000 * / list_entry ObjectList; // Object_creator_info814526f8 814528f8 / * 008 * / HANDLE UniqueProcessId; 00000000 kd we traverse it ObjectListkd> dd 814527f8 l 4dd 814527f8 l 4814527f8 814526f8 814528f8 00000000 00000000 // 814527f8 is 81452808-10kd> 814526f8 28 814526f8 28Evaluate expression:?? -2126174432 = 81452720 ! // Since OBJECT_CREATOR_INFO size 0x10, followed OBJECT_HEADER size 0x18, followed by the body and is the target object parameter is a pointer kd target body> object 81452720 object 81452720Object:!! 81452720 Type: (81452920) TypeObjectHeader: 81452708HandleCount : 0 PointerCount: 1Directory object: 8141ebf0 Name: SymbolicLink // can be seen under a type object "SymbolicLink" in the chain, the chain is visible ObjectList objects of the same type kd> dd 814526f8 l 4dd 814526f8 l 4814526f8 814525f8 814527f8 00000000 00000000 / / We went down with List_entry, until 814527F8, indicated that it has been looped.
kd> dd 814525f8 l 4dd 814525f8 l 4814525f8 814524b8 814526f8 00000000 00000000kd> dd 814524b8 l 4dd 814524b8 l 4814524b8 814523b8 814525f8 00000000 00000000kd> dd 814523b8 l 4dd 814523b8 l 4814523b8 814522b8 814524b8 00000000 00000000kd> dd 814522b8 l 4dd 814522b8 l 4814522b8 8141e438 814523b8 00000000 00000000kd> dd 8141e438 l 4dd 8141e438 l 48141e438 8141e338 814522b8 00000008 00000000kd> dd 8141e338 l 4dd 8141e338 l 48141e338 8141cc98 8141e438 00000008 00000000kd> dd 8141cc98 l 4dd 8141cc98 l 48141cc98 8141cb98 8141e338 00000008 00000000kd> dd 8141cb98 l 4dd 8141cb98 l 48141cb98 8141c878 8141cc98 00000008 00000000kd> dd 8141c878 l 4dd 8141c878 l 48141c878 8141c778 8141cb98 00000008 00000000kd> dd 8141c778 l 4dd 8141c778 l 48141c778 8141c678 8141c878 00000008 00000000kd> dd 8141c678 l 4dd 8141c678 l 48141c678 8141c578 8141c778 00000008 00000000kd> dd 8141c578 l 4dd 8141c578 l 48141c578 8141c478 8141c678 00000008 00000000kd> dd 8141c478 l 4dd 8141C478 L 48141C478 8141B738 8141C578 000 00008 00000000kd> dd 8141b738 l 4dd 8141b738 l 48141b738 8141b098 8141c478 00000008 00000000kd> dd 8141b098 l 4dd 8141b098 l 48141b098 81416e58 8141b738 00000008 00000000kd> dd 81416e58 l 4dd 81416e58 l 481416e58 81416d58 8141b098 00000008 00000000kd> dd 81416d58 l 4dd 81416d58 l 481416d58 81416af8 81416e58 00000008 00000000kd > dd 81416af8 l 4dd 81416af8 l 481416af8 814169f8 81416d58 00000008 00000000kd> dd 814169f8 l 4dd 814169f8 l 4814169f8 814168f8 81416af8 00000008 00000000kd> dd 814168f8 l 4dd 814168f8 l 4814168f8 814167f8 814169f8 00000008 00000000kd> dd 814167f8 l 4dd 814167f8 l 4814167f8 814166f8 814168f8 00000008 00000000kd>
dd 814166f8 l 4dd 814166f8 l 4814166f8 814165f8 814167f8 00000008 00000000kd> dd 814165f8 l 4dd 814165f8 l 4814165f8 814379b8 814166f8 00000008 00000000kd> dd 814379b8 l 4dd 814379b8 l 4814379b8 81452958 814165f8 00000008 003f0000kd> dd 81452958 l 4dd 81452958 l 481452958 814528f8 814379b8 000a0008 e1000ce8kd> dd 814528f8 L 4DD 814528F8 L 4814528F8 814527F8 81452958 00000000 00000000KD> DD 814527F8 L 4DD 814527F8 L 4814527f8 814526f8 814528f8 00000000 000,000 // encountered 814527f8, indicating that it has been circulated.
Here we look at an object body typedef Type Object of struct _OBJECT_TYPE {/ * 000 * / ERESOURCE Lock; / * 038 * / LIST_ENTRY ObjectListHead; // OBJECT_CREATOR_INFO / * 040 * / UNICODE_STRING ObjectTypeName; // see above / * 048 * / union {/ * 048 * / PVOID DefaultObject; // ObpDefaultObject / * 048 * / DWORD Code; // File: 5C, WaitablePort: A0}; / * 04C * / DWORD ObjectTypeIndex; // OB_TYPE_INDEX _ * / * 050 * / DWORD ObjectCount ; / * 054 * / DWORD HandleCount; / * 058 * / DWORD PeakObjectCount; / * 05C * / DWORD PeakHandleCount; / * 060 * / OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; / * 0AC * / DWORD ObjectTypeTag; // OB_TYPE_TAG _ * / * 0B0 * / } OBJECT_TYPE; // address 81452820, 0xB0 bytes long OBJECT_TYPE structure kd> dd 81452820 l b0 / 4dd 81452820 l b0 / 481452820 81452720 81452920 00000000 0000000081452830 00000000 00000000 00000000 0000000081452840 00000000 00000000 00000000 0000000081452850 00000000 00000000 81452858 8145285881452860 00140012 e1001948 00000000 0000000281452870 00000018 0000002d @ 0000000018101010101010145288010281452880 000000814528a0 00000000 00000000 000000d0 00000000814528b0 00000000 00000000 00000000 00000000814528c0 804bfb34 00000000 00000000 65726944 / * 000 * / ERESOURCE Lock; 81452820 81452720 81452920 00000000 0000000081452830 00000000 00000000 00000000 0000000081452840 00000000 00000000 00000000 0000000081452850 00000000 00000000 / * 038 * / LIST_ENTRY ObjectListHead; // OBJECT_CREATOR_INFO81452858 81452858 / * 040 * / UNICODE_STRING objectTypeName; 0012 0014 e1001948 // see if the string objectTypeName referred to it, kd> du e1001948du e1001948e1001948 "Directory" // it is "Directory" / * 048 * / PVOID DefaultObject; // ObpDefaultObject / * 048 * / dword code; // file: 5c, waitableport: A000000000 / * 04C * / DWORD ObjectTypeIndex;
// ob_type_index_ * 00000002 // #define ob_type_index_directory 2 // [DIRE] "Directory" system should be judged here, the type name is just to see. Other types of definitions will be listed later. / * 050 * / DWORD ObjectCount; 00000018 / * 054 * / DWORD HandleCount; 00000038 / * 058 * / DWORD PeakObjectCount; 00000018 / * 05C * / DWORD PeakHandleCount; 00000044 / * 060 * / OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 81452880 0000004c 00000100 00020003 0002000c81452890 00020003 000f000f 000f000f 00000000814528a0 00000000 00000000 000000d0 00000000814528b0 00000000 00000000 00000000 00000000814528c0 804bfb34 00000000 00000000 / * 0AC * / DWORD ObjectTypeTag; // OB_TYPE_TAG_ * 65726944 // is to ascii "eriD", # define OB_TYPE_TAG_DIRECTORY 'eriD' // [Dire] "Directory" Other types of definitions will be listed later.
OBJECT_TYPE_INITIALIZER structure is defined as typedef struct _OBJECT_TYPE_INITIALIZER {/ * 000 * / WORD Length; // 0x004C / * 002 * / BOOLEAN UseDefaultObject; // OBJECT_TYPE.DefaultObject / * 003 * / BOOLEAN Reserved1; / * 004 * / DWORD InvalidAttributes; / * 008 * / GENERIC_MAPPING GenericMapping; / * 018 * / ACCESS_MASK ValidAccessMask; / * 01C * / BOOLEAN SecurityRequired; / * 01D * / BOOLEAN MaintainHandleCount; // OBJECT_HANDLE_DB / * 01E * / BOOLEAN MaintainTypeList; // OBJECT_CREATOR_INFO / * 01F * / BYTE Reserved2; / * 020 * / BOOL PagedPool; / * 024 * / DWORD DefaultPagedPoolCharge; / * 028 * / DWORD DefaultNonPagedPoolCharge; / * 02C * / NTPROC DumpProcedure; / * 030 * / NTPROC OpenProcedure; / * 034 * / NTPROC CloseProcedure; / * 038 * / NTPROC DeleteProcedure; / * 03C * / NTPROC_VOID ParseProcedure; / * 040 * / NTPROC_VOID SecurityProcedure; // SeDefaultObjectMethod / * 044 * / NTPROC_VOID QueryNameProcedure; / * 048 * / NTPROC_BOOLEAN OkayToCloseProcedure; / * 04C * /} OBJECT_TYPE_INITIALIZER ; / * 000 * / Word length; // 0x004c004c / * 002 * / boolean usdefaultObject; // Object_type.defaultObject00 / * 003 * / bool EAN Reserved1; 00 / * 004 * / DWORD InvalidAttributes; 00000100 / * 008 * / GENERIC_MAPPING GenericMapping; struct _GENERIC_MAPPING (sizeof = 16) 00 uint32 GenericRead 04 uint32 GenericWrite 08 uint32 GenericExecute 0c uint32 GenericAll00020003 0002000c / * 018 * / ACCESS_MASK ValidAccessMask; typedef ULONG ACCESS_MASK; 00020003 / * 01C * / BOOLEAN SecurityRequired; 0f / * 01D * / BOOLEAN MaintainHandleCount; // OBJECT_HANDLE_DB00 / * 01E * / BOOLEAN MaintainTypeList; // OBJECT_CREATOR_INFO0f / * 01F * / BYTE Reserved2; 00 / * 020 * / BOOL PagedPool; 00000000 / * 024 * / DWORD DefaultPagedPoolCharge; 00000000 / * 028 * / DWORD DefaultNonPagedPoolCharge; 000000d0 / * 02C * / NTPROC DumpProcedure; 00000000 / * 030 * / NTPROC OpenProcedure; 00000000 / * 034 * / NTPROC CloseProcedure ;
00000000 / * 038 * / NTPROC DeleteProcedure; 00000000 / * 03C * / NTPROC_VOID ParseProcedure; 00000000 / * 040 * / NTPROC_VOID SecurityProcedure; // SeDefaultObjectMethod804bfb34kd> u 804bfb34u 804bfb34ntoskrnl SeDefaultObjectMethod:! / * 044 * / NTPROC_VOID QueryNameProcedure; 00000000 / * 048 * / Ntproc_boolean okaytocloseprocedure; 00000000 You can see where the object_type_initializer in Type Object is used to save the function routine. The introduction of these functions can be referred to the Object Methods section in "Object Manager" in INSIDE Windows 2000 Third Edition "Chapter 3 System Mechanisms". The description of the object of Type Object is here. There are several questions about Type Object to pay attention to the same type of object, and their object headers point to the type of pointer, pointing to the same address. For example, for an object of type Directory, they point to the type of hands point Type Object "Directory" kd> object / Device / Harddiskdmvolumes object / Device / HarddiskdmvolumesObject:!! 813d2890 Type: (81452820) Directory // Note that the object / Device / Harddiskdmvolumes type pointer to 81452820kd> object / Device / Harddiskdmvolumes / physicaldmvolumes object / Device / Harddiskdmvolumes / physicaldmvolumesObject:!! 813d26d0 type: (81452820) Directory // attention object / Device / Harddiskdmvolumes / physicaldmvolumes type pointer to 81,452,820 so, if no new The type of type is added, and the type object is 27. All objectType in the object_header of all type objects point to Type Object named "Type". The name is "Type" Type Object, and it is Type Object, so its ObjectType in its object_header points to yourself. ! Kd> object 81452920 object 81452920Object:! 81452920 Type: (81452920) TypeObjectHeader: 81452908HandleCount: 0 PointerCount: 1Directory Object: 8141ebf0 Name: Type ObjectType pointer to an object that is the head of all the types of objects, the type of point objects 27 The one called "Type". The ObjectType pointer in the object head called "Type", points to yourself. All types of objects are placed in / ObjectTypes / under / ObjectTypes, we can find the "ObjectTypes" directory object in the "/" directory object to get the pointer to all type objects.
You can also pass the "ObjectTypes" directory object in this global variable through a global variable called ObptyPedirectoryObject. Use the first method insurance.
ObjectTypeIndex listed below and ObjectTypeTag #define OB_TYPE_INDEX_TYPE 1 // [ObjT] "Type" #define OB_TYPE_INDEX_DIRECTORY 2 // [Dire] "Directory" #define OB_TYPE_INDEX_SYMBOLIC_LINK 3 // [Symb] "SymbolicLink" #define OB_TYPE_INDEX_TOKEN 4 // [Toke ] "Token" #define OB_TYPE_INDEX_PROCESS 5 // [Proc] "Process" #define OB_TYPE_INDEX_THREAD 6 // [Thre] "Thread" #define OB_TYPE_INDEX_JOB 7 // [Job] "Job" #define OB_TYPE_INDEX_EVENT 8 // [Even] " Event "#define OB_TYPE_INDEX_EVENT_PAIR 9 // [Even]" EventPair "#define OB_TYPE_INDEX_MUTANT 10 // [Muta]" Mutant "#define OB_TYPE_INDEX_CALLBACK 11 // [Call]" Callback "#define OB_TYPE_INDEX_SEMAPHORE 12 // [Sema]" Semaphore " #define OB_TYPE_INDEX_TIMER 13 // [Time] "Timer" #define OB_TYPE_INDEX_PROFILE 14 // [Prof] "Profile" #define OB_TYPE_INDEX_WINDOW_STATION 15 // [Wind] "windowStation" #define OB_TYPE_INDEX_DESKTOP 16 // [Desk] "Desktop" #define OB_TYPE_INDEX_SECTION 17 // [SECT] "Section" #define ob_type_index_key 18 // [key] "key" #define ob_type_index_port 19 // [ Port] "Port" #define OB_TYPE_INDEX_WAITABLE_PORT 20 // [Wait] "WaitablePort" #define OB_TYPE_INDEX_ADAPTER 21 // [Adap] "Adapter" #define OB_TYPE_INDEX_CONTROLLER 22 // [Cont] "Controller" #define OB_TYPE_INDEX_DEVICE 23 // [Devi] "Device" #define OB_TYPE_INDEX_DRIVER 24 // [Driv] "Driver" #define OB_TYPE_INDEX_IO_COMPLETION 25 // [IoCo] "IoCompletion" #define OB_TYPE_INDEX_FILE 26 // [File] "File" #define OB_TYPE_INDEX_WMI_GUID 27 // [WmiG] "WmiGuid "#define ob_type_tag_type 'tjbo' // [objt]" Type "
#define OB_TYPE_TAG_DIRECTORY 'eriD' // [Dire] "Directory" #define OB_TYPE_TAG_SYMBOLIC_LINK 'bmyS' // [Symb] "SymbolicLink" #define OB_TYPE_TAG_TOKEN 'ekoT' // [Toke] "Token" #define OB_TYPE_TAG_PROCESS 'corP' // [Proc] "Process" #define OB_TYPE_TAG_THREAD 'erhT' // [Thre] "Thread" #define OB_TYPE_TAG_JOB 'boJ' // [Job] "Job" #define OB_TYPE_TAG_EVENT 'nevE' // [Even] "Event" #define OB_TYPE_TAG_EVENT_PAIR 'nevE' // [Even] "EventPair" #define OB_TYPE_TAG_MUTANT 'atuM' // [Muta] "Mutant" #define OB_TYPE_TAG_CALLBACK 'llaC' // [Call] "Callback" #define OB_TYPE_TAG_SEMAPHORE 'ameS' // [Sema ] "Semaphore" #define OB_TYPE_TAG_TIMER 'emiT' // [Time] "Timer" #define OB_TYPE_TAG_PROFILE 'forP' // [Prof] "Profile" #define OB_TYPE_TAG_WINDOW_STATION 'dniW' // [Wind] "windowStation" #define OB_TYPE_TAG_DESKTOP ' Ksed '// [Desk] "Desktop" #define ob_type_tag_section' tces' // [SECT] "Section" #define ob_type_tag_key 'yek' // [key] "key" #define ob_type_tag_port 'Trop' // [port] " Port "#define ob_type_tag_waitabl E_PORT 'tiaW' // [Wait] "WaitablePort" #define OB_TYPE_TAG_ADAPTER 'padA' // [Adap] "Adapter" #define OB_TYPE_TAG_CONTROLLER 'tnoC' // [Cont] "Controller" #define OB_TYPE_TAG_DEVICE 'iveD' // [Devi ] "Device" #define ob_type_tag_driver 'vird' // [Driv] "driver" #define ob_type_tag_io_completion 'ocoi' // [Ioco] "IOCOMPETION" #define ob_type_tag_file 'Elif'
// [file] "File" #define ob_type_tag_wmi_guid 'gimw' // [wmig] "Wmiguid" introduces the object of the Type type. OBJECT_HANDLE_DB OBJECT_HANDLE_DB structure is defined as one of the other alternative structure typedef struct _OBJECT_HANDLE_DB {/ * 000 * / union {/ * 000 * / struct _EPROCESS * Process; / * 000 * / struct _OBJECT_HANDLE_DB_LIST * HandleDBList; / * 004 * /}; / * 004 * / dword handlecount; / * 008 * /} Object_handle_db; typedef struct _object_handle_db_list {/ * 000 * / dword count; / * 004 * / Object_handle_db entries []; / * ??? * /}; if The OB_FLAG_SINGLE_PROCESS flag is set, and the .process in Union is valid and points to an eProcess. If there are multiple processes that have the handle (Handle) of this object, the OB_FLAG_SINGLE_PROCESS flag will not be set, then .HandBLIST is valid. kd> object / Windows / WindowStations / WinSta0 object / Windows / WindowStations / WinSta0Object:!! 810c9398 Type: (8141c5a0) WindowStationObjectHeader: 810c9380HandleCount: 29 PointerCount: 46Directory Object: 810e5930 Name: WinSta0 // object header address 810c9380, the object head c starting four bytes are NameOffset HandleDBOffset // QuotaChargesOffset ObjectFlagskd> db 810c9380 cl 4db 810c9380 cl 4810c938c 10 18 00 20 // HandleDBOffset not 0, indicating the presence of OBJECT_HANDLE_DB, and the offset 18, i.e. 810c9380- 18 = 810C9368, the size is 8 bytes. NameOffset is not 0, offset to 10. ObjectFlags is 20 (HEX) = 00100000 (bin) ie ob_flag_security, the flag bit ob_flag_single_process is not set, indicating that Object_handle_db's Union is valid.
kd> dd 810c9380-18 l 2dd 810c9380-18 l 2810c9368 e308ac48 00000002 / * 000 * / struct _OBJECT_HANDLE_DB_LIST * HandleDBList; e308ac48 / * 004 * / DWORD HandleCount; 00000002 // OBJECT_HANDLE_DB_LIST of Countkd> dd e308ac48 l 1dd e308ac48 l 1e308ac48 00000016 / / have 0x16 items kd> dd e308ac48 4 l 16 * 2dd e308ac48 4 l 16 * 2e308ac4c 810cc740 00000002 00000000 00000000e308ac5c 81054020 00000002 833eb1c0 00000002e308ac6c 81f9f020 00000002 824c65e0 00000002e308ac7c 80e68100 00000002 00000000 00000000e308ac8c 84f7a7e0 00000002 810e8020 00000002e308ac9c 00000000 00000000 00000000 00000000e308acac 00000000 00000000 00000000 00000000e308acbc 8352a620 0000000000000000000000000000000000000002 830F0A00 00000002E308ACDC 83084B00 00000002 817CB3C0 00000001E308ACEC 83589020 00000002 8345A440 00000002 // Try the first item to point to EPROCESS, ! Kd> process 810cc740 0 process 810cc740 0PROCESS 810cc740 SessionId:! 0 Cid: 00bc Peb: 7ffdf000 ParentCid: 008cDirBase: 075a7000 ObjectTable: 810cc6a8 TableSize: 357.Image: winlogon.exe // really points to a structure of one optional structure EPROCESS the structure is defined as OBJECT_QUOTA_CHARGESOBJECT_QUOTA_CHARGES #define OB_SECURITY_CHARGE 0x00000800typedef struct _OBJECT_QUOTA_CHARGES {/ * 000 * / DWORD PagedPoolCharge; / * 004 * / DWORD NonPagedPoolCharge; / * 008 * / DWORD SecurityCharge; / * 00C * / DWORD Reserved; / * 010 * /} Object_quota_charges; when the flag bit OB_FLAG_CREATE_INFO in the object head is 0, PQUOTA_BLOCK quotablock in the head is valid.
struct _EPROCESS_QUOTA_BLOCK (sizeof = 44) 00 uint32 QuotaLock 04 uint32 ReferenceCount 08 uint32 QuotaPeakPoolUsage [2] 10 uint32 QuotaPoolUsage [2] 18 uint32 QuotaPoolLimit [2] 20 uint32 PeakPagefileUsage 24 uint32 PagefileUsage 28 uint32 PagefileLimitkd>! object /KnownDlls/user32.dll!object /KnownDlls/user32.dllObject: e17c29e0 Type: (8141b760) SectionObjectHeader: e17c29c8HandleCount: 0 PointerCount: 1Directory Object: 810f63d0 Name: user32.dll // object header address e17c29c8, the object header c starting four bytes are NameOffset HandleDBOffset // QuotaChargesOffset ObjectFlags kd> db e17c29c8 cl 4db e17c29c8 cl 4e17c29d4 10 00 20 10 // QuotaChargesOffset not zero, indicating the presence of OBJECT_QUOTA_CHARGES, and the offset 20, i.e. e17c29c8- 20 = E17C29A8, the size is 8 bytes. NameOffset is not 0, offset to 10. Objectflags is 10 (HEX) = 00010000 (bin) ie ob_flag_permanent, ob_flag_create_info bit is 0.
// OBJECT_QUOTA_CHARGESkd> dd e17c29c8-20 l 4dd e17c29c8-20 l 4e17c29a8 000001b8 000000d8 00000800 00000000 / * 000 * / DWORD PagedPoolCharge; 000001b8 / * 004 * / DWORD NonPagedPoolCharge; 000000d8 / * 008 * / DWORD SecurityCharge; 00000800 / * 00C * / DWORD Reserved; 00000000 // head address e17c29c8, head QuotaBlock value 804699c0kd> dd e17c29c8 l 6dd e17c29c8 l 6e17c29c8 00000001 00000000 8141b760 10200010e17c29d8 804699c0 e17bb8d8 // EPROCESS_QUOTA_BLOCKkd> dd 804699c0 l 2c / 4dd 804699c0 l 2c / 4804699c0 00000000 000006b9 0008395c 001499e0804699d0 0007eebc 00139f6c ffffffff ffffffff804699e0 0000106e 00000f16 ffffffff 00 uint32 QuotaLock00000000 04 uint32 ReferenceCount000006b9 08 uint32 QuotaPeakPoolUsage [2] 0008395c 001499e0 10 uint32 QuotaPoolUsage [2] 0007eebc 00139f6c 18 uint32 QuotaPoolLimit [2] ffffffff ffffffff 20 uint32 PeakPagefileUsage0000106e 24 uint32 Pagefileusage00000F16 28 uint32 PageFileLimitffffffffObject_Header in / * 014 * / psecurity_descriptor ObjectCreateInfo If the OB_FLAG_Security flag in Object_Header is set up securityDesc Riptor is a pointer to Security_Descriptor. If the ob_flag_security flag is not set, SECURITYDESCRIPTOR is empty. The Security_Descriptor structure is defined in the following // KD! STRCT is obtained.
struct _SECURITY_DESCRIPTOR (sizeof = 20) 00 byte Revision 01 byte Sbz1 02 uint16 Control 04 void * Owner 08 void * Group 0c struct _ACL * Sacl 10 struct _ACL * Daclstruct _SID (sizeof = 12) 0 byte Revision 1 byte SubAuthorityCount 2 struct _SID_IDENTIFIER_AUTHORITY IdentifierAuthority 2 byte Value [6] 8 uint32 SubAuthority [1] struct _ACL (sizeof = 8) 0 byte AclRevision 1 byte Sbz1 2 uint16 AclSize 4 uint16 AceCount 6 uint16 Sbz2 // to "/" Example kd> object / object / Object:!! 8141ecd0 Type: (81452820) DirectoryObjectHeader: 8141ecb8kd> dd 8141ecb8 l 6dd 8141ecb8 l 68141ecb8 00000023 00000000 81452820 320000108141ecc8 00000001 e10010f8 // 32 (hex) = 00110010 (bin), OB_FLAG_KERNEL_MODE, OB_FLAG_PERMANENT, OB_FLAG_SECURITY This 3 bit is set. So E10010F8 points to SecurityDescriptor to Security_Descriptor. Security_descriptor Structures are 20 (DEC) bytes.
kd> dd e10010f8 l 5dd e10010f8 l 5e10010f8 80040001 00000070 00000080 00000000e1001108 00000014 00 byte Revision01 01 byte Sbz100 02 uint16 Control8004 04 void * Owner00000070 08 void * Group00000080 0c struct _ACL * Sacl00000000 // are empty, there is no SACL 10 STRUCT _ACL * DACL00000014 / / is not empty, indicating that there is DACL, and is offset from the beginning of SECURITY_DESCRIPTOR, that is, E10010F8 14KD> DB E10010F8 14 L 8DB E10010F8 14 L 8E100110C 02 00 5C 00 04 00 00 0 BYTE ACLREVISION02 1 BYTE SBZ100 2 UINT16 ACLSIZE005C 4 UINT16 ACECOUNT0004 6 UINT16 SBZ 20000 // Using KD! SD command to display security descriptor KD>! SD E10010F8! SD E10010F8-> Revision: 0x1 -> SBZ1: 0x0-> Control: 0x8004se_dacl_presentse_self_relarative-> Owner: S-1-5-32-544-> Group: S-1-5-18-> DAUP: -> Dacl: -> ACLREVISION: 0x2-> DACL : -> SBZ1: 0x0-> DACL: -> aclsize: 0x5c-> Dacl: -> acecount: 0x4-> Dacl: -> SBZ2: 0x0-> Dacl: -> ace [0]: -> acetype: Access_allowed_Ace_type- > DACL: -> ACE [0]: -> aceflags: 0x0-> dacl: -> ace [0]: -> acesize: 0x14-> dacl: -> ace [0]: -> mask: 0x00020003-> dacl : -> ace [0]: -> SID: S-1-1-0-> D ACL: -> ace [1]: -> acetype: access_allowed_ce_type-> dacl: -> ace [1]: -> aceflags: 0x0-> dacl: -> ace [1]: -> acesize: 0x14-> DACL: -> ace [1]: -> Mask: 0x000f000f-> DACL: -> ACE [1]: -> SID: S-1-5-18-> Dacl: -> ace [2]: -> acetype: access_allowed_Ace_type -> Dacl: -> ace [2]: -> aceflags: 0x0-> dacl: -> ace [2]: -> acesize: 0x18-> dacl: -> ace [2]: -> mask: 0x000f000f-> Dacl: -> ace [2]: -> SID: S-1-5-32-544-> DACL: -> ace [3]: -> acetype: access_allowed_ace_type-> dacl: ->