Debugger commands (!sd) that make my life easier (part 3.1)

Peter Wieland informed me that you can actually find the security descriptor (SD) using !object, you just have to work harder to get at it. It relies on an undocumented structure, but since this is not being used at runtime and !object also uses it, I think it is OK to show. Once you have the SD, you can use the !sd command to view the SD's contents.

What we want to look at is the object header. The header is given when you run !object on any valid path or name. Not all objects have a security descriptor; I picked an object (the \Device directory object) that I knew had an SD assigned to it. While the header pointer is supplied, its type is not. The header's type is nt!_OBJECT_HEADER.

0: kd> !object \Device
Object: e1011670 Type: (822f91f0) Directory
ObjectHeader: e1011658
HandleCount: 0 PointerCount: 206
Directory Object: e10023e0 Name: Device
12 symbolic links snapped through this directory

Hash Address Type Name
---- ------- ---- ----
00 8228a9c0 Device KsecDD
820d94f0 Device Beep

0: kd> dt e1011658 nt!_OBJECT_HEADER
+0x000 PointerCount : 0xce
+0x004 HandleCount : 0
+0x004 NextToFree : (null)
+0x008 Type : 0x822f91f0 _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 : 0xe1008f71
+0x018 Body : _QUAD

The SecurityDescriptor pointer value 0xe1008f71 cannot be used as is. The kernel uses the bottom three bits for other purposes (this works because all allocations are at least 8 byte aligned, so the bottom three bits will always be 0x0), so we must mask of the bottom three bits with the inverse of 0x7. To do this I use the C++ expression evaluator command "@@." @@ is the same as ?? except that you can use it in the middle of an expression. We will pass that masked off address to !sd to see the contents. Unfortunately !sd does not map well known SIDs to their canonical names, but I can live with that.

0: kd> !sd @@(0xe1008f71 & ~0x7)
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8004
->Owner : S-1-5-32-544
->Group : S-1-5-18
->Dacl :
->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

->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_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 : ->Ace[3]: ->AceFlags: 0x0
->Dacl : ->Ace[3]: ->AceSize: 0x14
->Dacl : ->Ace[3]: ->Mask : 0x00020003
->Dacl : ->Ace[3]: ->SID: S-1-5-12

->Sacl : is NULL

Comments (2)

  1. Today I am going to write about !object. One of the tools you can get from sysinternals is WinObj.exe….

  2. Alex Ionescu says:

    The structure is EX_FAST_REF, and is part of the Object Manager Fast-Referencing implementation (ObFastReferenceObject, etc).

    It allows the kernel to encode the reference count as a pointer bias, so that the object is actually only truly "referenced" once with the Object Manager, and every other additional time inside the EX_FAST_REF structure itself. The bias towards the 8-byte alignment is the number of fast references an object can have.  When the last fast-reference is removed, the Object Manager actually gets the real ObDereferenceObject call.

    This is also used in EPROCESS->Token, and anywhere else where you see _EX_FAST_REF.

Skip to main content