Search This Blog

Monday 15 September 2014

WinDbg : the !object Command & It's Usage

WinDbg : !object

The NT Kernel tries to maintain an object based environment. A core set of objects are exposed which are used by the NT Executive. A set of functions are also provided to act upon these objects.  The NT Executive uses these objects, to create even more complex objects, many of which are available to the user.

Note: The NT Kernel does not depend on the Object Manager (which forms part of the Executive) to manage the kernel defined object types.

Kernel Objects are of the following two types:

Dispatcher Objects : These are used to control the synchronization and dispatching of system threads. Examples include thread, event, timer, mutex etc. 

Control Objects : These objects affect the operation of Kernel-mode code, but do not affect synchronization or dispatching. Examples include Interrupt objects, process objects, APC and DPC objects etc.

Lets have a look at the list of kernel objects we can wait on in Windows. It is stored in an enum.


kd> dt nt!_KOBJECTS
   EventNotificationObject = 0n0
   EventSynchronizationObject = 0n1
   MutantObject = 0n2
   ProcessObject = 0n3
   QueueObject = 0n4
   SemaphoreObject = 0n5
   ThreadObject = 0n6
   GateObject = 0n7
   TimerNotificationObject = 0n8
   TimerSynchronizationObject = 0n9
   Spare2Object = 0n10
   Spare3Object = 0n11
   Spare4Object = 0n12
   Spare5Object = 0n13
   Spare6Object = 0n14
   Spare7Object = 0n15
   Spare8Object = 0n16
   Spare9Object = 0n17
   ApcObject = 0n18
   DpcObject = 0n19
   DeviceQueueObject = 0n20
   EventPairObject = 0n21
   InterruptObject = 0n22
   ProfileObject = 0n23
   ThreadedDpcObject = 0n24
   MaximumKernelObject = 0n25


An Object, in NT, is an opaque data structure, implemented, maintained and manipulated by the NT executive. Each such object, has a set of operations defined for it, example : 
  • Create an instance of the object
  • Delete a created instance of the object
  • Wait On an object instance for it to become signaled.
  • Signal an object instance.
The object manager provides us with :
  • A global naming hierarchy, much like that used in file systems.
  • Methods to create and delete object instances.
  • Methods to add security restrictions on objects.
  • Maintain reference counts for object instances.
  • Add new object types dynamically to the the system.
Note: The Object manager does not concern itself with the internal data structure of the object.  the object structure contains a header and then a body.

kd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : UChar
   +0x00d TraceFlags       : UChar
   +0x00e InfoMask         : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void

   +0x018 Body             : _QUAD

The global namespace maintained by the object manager contains all named objects in the system. The object name space is modeled like an inverted tree (much like a file system does) and the global root directory for this tree is called "\". This namespace is initialized during system boot up.

NT Executive can create sub-directories under root and create instances of already defined object types. 

Lets try to parse the object manager through the debugger. The !object extension command is extremely helpful in this case.


kd> !object \


Object: 874010e8  Type: (839b7e90) Directory
    ObjectHeader: 874010d0 (new version)
    HandleCount: 0  PointerCount: 42
    Directory Object: 00000000  Name: \

Hash Address Type Name
---- ------- ---- ----
0 8740bbe0 Directory ArcName
8470c9f0 Device Ntfs
1 84ccfde8 ALPC Port SeLsaCommandPort
83a2b658 Event UniqueInteractiveSessionIdEvent
3 87408d10 Key \REGISTRY
4 83a295f8 ALPC Port PowerPort
5 84f2bf00 ALPC Port ThemeApiPort
9 8745d920 Directory NLS
10 87405df0 SymbolicLink DosDevices
12 84f319a8 ALPC Port UxSmsApiPort
13 84938038 ALPC Port SeRmCommandPort
14 84d66380 Event LanmanServerAnnounceEvent
8756d6e0 SymbolicLink Dfs
8744a360 Directory UMDFCommunicationPorts
16 8744cf58 Directory Driver
18 846fd4d0 Device clfs
19 8740f030 Directory Device
20 8b21e580 Directory Windows
84f03810 ALPC Port MmcssApiPort
849056e0 Event CsrSbSyncEvent
21 8b249bc8 Directory Sessions
84cebb38 Event SAM_SERVICE_STARTED
22 8b2487f8 Directory RPC Control
84958048 ALPC Port SmApiPort
23 95e0ee30 Directory BaseNamedObjects
874054c0 Directory KernelObjects
83a16038 ALPC Port PowerMonitorPort
24 87408f58 Directory GLOBAL??
87468330 Directory FileSystem
25 84d169c0 Event DSYSDBG.Debug.Trace.Memory.208
95ee6318 Section LsaPerformance
26 84d8da18 ALPC Port SmSsWinStationApiPort
87405b80 Directory ObjectTypes
27 8740ae38 Directory Security
30 851c9c20 ALPC Port AELPort
31 875dbd70 SymbolicLink SystemRoot
32 87405aa8 Directory Callback
33 84c28298 Event UniqueSessionIdEvent
84bcd6b8 Event EFSInitEvent
35 8b265108 Directory KnownDlls
This displays all the object types with the hierarchy they are in the name space. So see a sub-tree we can give it's path as well. E.g. Drivers.

kd> !object \Driver
Object: 8744cf58  Type: (839b7e90) Directory
    ObjectHeader: 8744cf40 (new version)
    HandleCount: 0  PointerCount: 87
    Directory Object: 874010e8  Name: Driver

Hash Address Type Name
---- ------- ---- ----
0 8470c4a0 Driver KSecDD
8474c3b8 Driver NDIS
8494b878 Driver Beep
8492d3b0 Driver rdpbus
1 847bfa58 Driver storflt
848df5d0 Driver SynthVid
848de030 Driver mouclass
2 8475c3b8 Driver KSecPkg
3 848a2db8 Driver kbdclass
4 839e87f0 Driver msisadrv
846aa940 Driver vmbus
8494b980 Driver VgaSave
84be2e28 Driver NDProxy
5 846ecdb8 Driver mountmgr
6 8474bb98 Driver pcw
8 85029960 Driver PEAUTH
846ec770 Driver atapi
847ddc38 Driver hwpolicy
8490c438 Driver blbdrive
9 846aae90 Driver volmgrx
10 848d7188 Driver Psched
11 84904600 Driver Win32k
846f8970 Driver amdxata
84981960 Driver mouhid
12 848d23a8 Driver tunnel
848e92e0 Driver netvsc
8492b4f0 Driver RasSstp
84949dc8 Driver swenum
13 8.48E+34 Driver HTTP
848816b0 Driver RDPCDD
8.49E+303 Driver RasPppoe
14 848903b8 Driver TermDD
15 848e8c20 Driver fdc
848cf150 Driver VMBusHID
84931f38 Driver Rasl2tp
16 8470c5e8 Driver CNG
8488ce38 Driver RDPREFMP
17 84951f38 Driver umbus
8491b1c0 Driver s3cap
18 84837de0 Driver secdrv
83a42da8 Driver ACPI_HAL
83a42670 Driver WMIxWDM
83a51338 Driver CLFS
848de250 Driver Serenum
8492ea18 Driver PptpMiniport
19 8.47E+102 Driver storvsc
847bf7b8 Driver spldr
21 8509d080 Driver tcpipreg
848d80c0 Driver NetBT
22 8484f4e0 Driver RDPENCDD
848a4030 Driver cdrom
84a515f0 Driver mssmbios
23 84f34b90 Driver rspndr
84856a80 Driver tdx
84967680 Driver WfpLwf
24 84fd1160 Driver mpsdrv
847613b8 Driver Tcpip
847ab530 Driver fvevol
25 839b7580 Driver 0000149
84307240 Driver volmgr
847c4d48 Driver volsnap
84891948 Driver nsiproxy
26 849194d0 Driver intelppm
27 84f38158 Driver lltdio
84890660 Driver Wanarpv6
28 848a4778 Driver Null
84a51b38 Driver discache
29 839e8508 Driver pci
847dd9a8 Driver Disk
848d6c40 Driver CSC
30 84307928 Driver partmgr
849134a0 Driver Serial
84932188 Driver NdisTapi
848da530 Driver NdisWan
32 852541a0 Driver MYFAULT
839ca1a0 Driver Wdf01000
842b71c8 Driver ACPI
33 83a31c18 Driver PnpManager
84964d08 Driver flpydisk
34 842fc318 Driver vdrvroot
848a4cf0 Driver AFD
84915750 Driver CompositeBus
36 846aa838 Driver intelide
847aa4c0 Driver rdyboost
848cf790 Driver i8042prt
849316b0 Driver RasAgileVpn
Strangely, we do not see the name of NTFS, one of the mandatory drivers for Windows, in this list. The reason is that, NTFS is a file system, and Windows treats file systems separately. Infact, none of the file system drivers are to be seen here. They are all in the \Filesystem hive. Lets have a look:

kd> !object \Filesystem
Object: 87468330  Type: (839b7e90) Directory
    ObjectHeader: 87468318 (new version)
    HandleCount: 0  PointerCount: 27
    Directory Object: 874010e8  Name: FileSystem

Hash Address Type Name
---- ------- ---- ----
0 846d9b98 Driver srvnet
8470cb18 Driver Ntfs
1 84913250 Driver NetBIOS
3 84755378 Device ExFatRecognizer
5 846edac8 Driver rdbss
10 84fd3600 Driver bowser
15 849d7ce8 Driver Msfs
17 84c39a88 Driver mrxsmb
18 84750378 Device UdfsCdRomRecognizer
19 84fe6530 Driver srv
23 848d6ea8 Driver DfsC
24 848f2718 Driver srv2
847bf570 Driver Mup
842b41b8 Driver RAW
25 8488c2d0 Driver Npfs
8474e360 Driver Fs_Rec
26 8744eb50 Directory Filters
30 84fd1a88 Driver mrxsmb10
32 84753378 Device FatCdRomRecognizer
8474f378 Device CdfsRecognizer
846f8878 Driver FltMgr
33 84fd5848 Driver mrxsmb20
34 84752378 Device FatDiskRecognizer
8470d578 Driver FileInfo
36 84d4b030 Driver luafv
84751378 Device UdfsDiskRecognizer

To see details of a named object we can give the name of the object. Example for details of the C: (which is a symbolic link) we can use the following command.

kd> !object \Global??\c:
Object: 875dbd28  Type: (839b7dc8) SymbolicLink
    ObjectHeader: 875dbd10 (new version)
    HandleCount: 0  PointerCount: 1
    Directory Object: 87408f58  Name: C:
    Target String is '\Device\HarddiskVolume2'
    Drive Letter Index is 3 (C:)

We had discussed object types in a previous section, to see all the object types currently supported we can use:

kd> !object \ObjectTypes
Object: 87405b80  Type: (839b7e90) Directory
    ObjectHeader: 87405b68 (new version)
    HandleCount: 0  PointerCount: 44
    Directory Object: 874010e8  Name: ObjectTypes

Hash Address Type Name
---- ------- ---- ----
0 83a28c58 Type TpWorkerFactory
839b7e90 Type Directory
1 83a25418 Type Mutant
839b78b0 Type Thread
3 846ff870 Type FilterCommunicationPort
4 83a31eb0 Type TmTx
5 83a28ac8 Type Controller
6 83a43f78 Type EtwRegistration
7 83a28f78 Type Profile
83a33420 Type Event
839b7f58 Type Type
9 83a31b50 Type Section
83a2f3f8 Type EventPair
839b7dc8 Type SymbolicLink
10 83a28d20 Type Desktop
839b77e8 Type UserApcReserve
11 83a43eb0 Type EtwConsumer
83a26350 Type Timer
12 83a287a8 Type File
83a28de8 Type WindowStation
14 8474b298 Type PcwObject
15 83a31d20 Type TmEn
16 83a28938 Type Driver
18 83a42528 Type WmiGuid
83a28eb0 Type KeyedEvent
19 83a28a00 Type Device
839b7b80 Type Token
20 83a298f0 Type ALPC Port
839af878 Type DebugObject
21 83a28870 Type IoCompletion
22 839b7978 Type Process
23 83a31de8 Type TmRm
24 83a28b90 Type Adapter
26 83a16f18 Type PowerRequest
83a2d388 Type Key
28 839b7a40 Type Job
30 83a317b0 Type Session
83a31f78 Type TmTm
31 839afef8 Type IoCompletionReserve
32 83a25350 Type Callback
33 846ec158 Type FilterConnectionPort
34 83a26418 Type Semaphore




NT maintains a data structure called the OBJECT_TYPE which contains all relevant information about any object. We will be using the dt command. To read more about what dt is, read here.

kd> dt nt!_OBJECT_TYPE
   +0x000 TypeList         : _LIST_ENTRY
   +0x008 Name             : _UNICODE_STRING
   +0x010 DefaultObject    : Ptr32 Void
   +0x014 Index            : UChar
   +0x018 TotalNumberOfObjects : Uint4B
   +0x01c TotalNumberOfHandles : Uint4B
   +0x020 HighWaterNumberOfObjects : Uint4B
   +0x024 HighWaterNumberOfHandles : Uint4B
   +0x028 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x078 TypeLock         : _EX_PUSH_LOCK
   +0x07c Key              : Uint4B
   +0x080 CallbackList     : _LIST_ENTRY

The TypeInfo structure will reveal information like the memory pool where this object is allocated from, several function pointers which will act upon the object, counts of handles etc. 

kd> dt nt!_OBJECT_TYPE TypeInfo.
   +0x028 TypeInfo  : 
      +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
      +0x004 ObjectTypeCode : Uint4B
      +0x008 InvalidAttributes : Uint4B
      +0x00c GenericMapping : _GENERIC_MAPPING
      +0x01c ValidAccessMask : Uint4B
      +0x020 RetainAccess : Uint4B
      +0x024 PoolType  : _POOL_TYPE
      +0x028 DefaultPagedPoolCharge : Uint4B
      +0x02c DefaultNonPagedPoolCharge : Uint4B
      +0x030 DumpProcedure : Ptr32        void 
      +0x034 OpenProcedure : Ptr32        long 
      +0x038 CloseProcedure : Ptr32        void 
      +0x03c DeleteProcedure : Ptr32        void 
      +0x040 ParseProcedure : Ptr32        long 
      +0x044 SecurityProcedure : Ptr32        long 
      +0x048 QueryNameProcedure : Ptr32        long 
      +0x04c OkayToCloseProcedure : Ptr32        unsigned char 

Note: Observe the . (dot) after the TypeInfo in the above command. It is used to expand structure fields.

Lets use this to see the values for an actual Object. Processes are also objects inside NT. So lets use our favorite process lsass.exe for this example.

kd> !process 0 0 lsass.exe
PROCESS 84cdc860  SessionId: 0  Cid: 0208    Peb: 7ffda000  ParentCid: 018c
    DirBase: 1eed30e0  ObjectTable: 95f00d18  HandleCount: 513.
    Image: lsass.exe

Passing this process address to the !object extension we extract information about it.

kd> !object 84cdc860  
Object: 84cdc860  Type: (839b7978) Process
    ObjectHeader: 84cdc848 (new version)
    HandleCount: 10  PointerCount: 254

Lets try to typecast this address to OBJECT_TYPE.

kd> dt nt!_OBJECT_TYPE 839b7978
   +0x000 TypeList         : _LIST_ENTRY [ 0x839b7978 - 0x839b7978 ]
   +0x008 Name             : _UNICODE_STRING "Process"
   +0x010 DefaultObject    : (null)
   +0x014 Index            : 0x7 ''
   +0x018 TotalNumberOfObjects : 0x1f
   +0x01c TotalNumberOfHandles : 0xaf
   +0x020 HighWaterNumberOfObjects : 0x22
   +0x024 HighWaterNumberOfHandles : 0xbd
   +0x028 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x078 TypeLock         : _EX_PUSH_LOCK
   +0x07c Key              : 0x636f7250
   +0x080 CallbackList     : _LIST_ENTRY [ 0x839b79f8 - 0x839b79f8 ]

Notice that the Name of this Object is 'Process'.

...and extract the TypeInfo sub structure fields....

kd> dt nt!_OBJECT_TYPE 839b7978 TypeInfo.
   +0x028 TypeInfo  :
      +0x000 Length    : 0x50
      +0x002 ObjectTypeFlags : 0x4a 'J'
      +0x002 CaseInsensitive : 0y0
      +0x002 UnnamedObjectsOnly : 0y1
      +0x002 UseDefaultObject : 0y0
      +0x002 SecurityRequired : 0y1
      +0x002 MaintainHandleCount : 0y0
      +0x002 MaintainTypeList : 0y0
      +0x002 SupportsObjectCallbacks : 0y1
      +0x004 ObjectTypeCode : 0
      +0x008 InvalidAttributes : 0xb0
      +0x00c GenericMapping : _GENERIC_MAPPING
      +0x01c ValidAccessMask : 0x1fffff
      +0x020 RetainAccess : 0x101000
      +0x024 PoolType  : 0 ( NonPagedPool )
      +0x028 DefaultPagedPoolCharge : 0x1000
      +0x02c DefaultNonPagedPoolCharge : 0x2f0
      +0x030 DumpProcedure : (null)
      +0x034 OpenProcedure : 0x82819ccb        long  nt!PspProcessOpen+0
      +0x038 CloseProcedure : 0x82879d2e        void  nt!PspProcessClose+0
      +0x03c DeleteProcedure : 0x8287c5f5        void  nt!PspProcessDelete+0
      +0x040 ParseProcedure : (null)
      +0x044 SecurityProcedure : 0x8286e5b6        long  nt!SeDefaultObjectMethod+0
      +0x048 QueryNameProcedure : (null)
      +0x04c OkayToCloseProcedure : (null) 

We had discussed before about the object having a header and a body. Lets see if we can extract the appropriate fields displayed by the !object extension ourselves.

kd> dt nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int4B
   +0x004 HandleCount      : Int4B
   +0x004 NextToFree       : Ptr32 Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : UChar
   +0x00d TraceFlags       : UChar
   +0x00e InfoMask         : UChar
   +0x00f Flags            : UChar
   +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : Ptr32 Void
   +0x014 SecurityDescriptor : Ptr32 Void
   +0x018 Body             : _QUAD

In my version of Windows the body starts at offset 0x18, which means to get the header we need to move the pointer by 0x18. using the address of lsass.ee from the output of !process above...

kd> !process 0 0 lsass.exe
PROCESS 84cdc860  SessionId: 0  Cid: 0208    Peb: 7ffda000  ParentCid: 018c
    DirBase: 1eed30e0  ObjectTable: 95f00d18  HandleCount: 513.
    Image: lsass.exe

kd> dt nt!_OBJECT_HEADER 84cdc860-18
   +0x000 PointerCount     : 0n254
   +0x004 HandleCount      : 0n10
   +0x004 NextToFree       : 0x0000000a Void
   +0x008 Lock             : _EX_PUSH_LOCK
   +0x00c TypeIndex        : 0x7 ''
   +0x00d TraceFlags       : 0 ''
   +0x00e InfoMask         : 0x8 ''
   +0x00f Flags            : 0 ''
   +0x010 ObjectCreateInfo : 0x8273ecc0 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x8273ecc0 Void
   +0x014 SecurityDescriptor : 0x87405f79 Void
   +0x018 Body             : _QUAD

Which are the same as given by the !object extension.

kd> !object 84cdc860
Object: 84cdc860  Type: (839b7978) Process
    ObjectHeader: 84cdc848 (new version)
    HandleCount: 10  PointerCount: 254

Note: The Object header structure has changed from the previous versions of Windows. Earlier the _OBJECT_TYPE pointer used to be available in the header itself. Hre is an output from an older version of Windows.

kd>dt_object_header  8a4ce650
nt!_OBJECT_HEADER
  +0x000PointerCount     : 79
  +0x004HandleCount      : 2
  +0x004NextToFree       : 0x00000002
  +0x008 Type            : 0x8a4ceca0
  +0x00cNameInfoOffset   : 0''
  +0x00dHandleInfoOffset : 0''
  +0x00eQuotaInfoOffset  : 0''
  +0x00fFlags            : 0x22'"'
  +0x010ObjectCreateInfo : 0x80545620
  +0x010QuotaBlockCharged : 0x80545620
  +0x014SecurityDescriptor : 0xe10001dc
  +0x018Body             : _QUAD

We will revisit the object manager again later on when we see how names are resolved in Windows.

No comments:

Post a Comment