The Object Manager (Ob) in Windows provides and excellent feature called object tracking, which causes the Ob to maintain a list of every active object in the system. When activated, it allows you to find every driver object, event object, file object, mutex object, etc. at any point in time via the !object command. While the overhead of this is likely to be unacceptable for everyday use, in certain debugging situations it can be immensely helpful. For example, I recently debugged an issue where autochk would not run when our file system filter was installed on the system. I suspected that a rogue file object was preventing NTFS from dismounting, so I turned on object tracking in order to quickly find the file object causing the problem (turned out to be multiple file objects).
Unfortunately things have changed in Windows 7 and the debugging tools haven’t caught up so this no longer works, but I’ll provide a solution to that once I get there…
Enabling Object Tracking
Object tracking is enabled via the FLG_MAINTAIN_OBJECT_TYPELIST GFlags option. You can enable this via the GFlags utility on the target machine, but I prefer to do it via the debugger on a per-boot basis so that I don’t have to remember to shut it off:
1: kd> !gflag + otl Current NtGlobalFlag contents: 0x00004000 otl - Maintain a list of objects for each type
Important note: This must be done very early in the boot process before the Ob initializes. I recommend setting an initial break in the debugger by using the WinDBG command CTRL+ALT+K and using the !gflag command at the initial break.
Once you’ve enabled the command, just hit Go and proceed to run whatever tests or do whatever you like. Once you’re ready to start inspecting objects, the path you will take will differ on Vista (and earlier) and Windows 7.
Dumping Objects Prior To Win7
Prior to Win7, life is fairly straightforward as the !object command supports walking the object list. The syntax for the command is:
!object 0 Name
Where Name is documented to be:
So, for example:
!object 0 File
!object 0 Event
!object 0 Semaphore
!object 0 Device
!object 0 Driver
Any of these will dump out all of the objects of that particular type and you can then pick through and do whatever it is you do with that information.
Dumping Objects on Win7
Now for the fun part. If you attempt to run any of the above !object commands on a Win7 target, you’ll get the following error:
1: kd> !object 0 File Scanning 723 objects of type 'File' WARNING: Object header 83d8bb48 flag (42) does not have OB_FLAG_CREATOR_INFO (4) set
The problem is that starting with Win7, that flag no longer exists. Instead, the object header tracks whether or not this feature is enabled via another field in the header. So, unfortunately, the Ob changed but the !object command wasn’t updated to reflect the changes.
We can get this back though from a gratuitously complicated debugger command that walks the list starting at an entry. Finding the starting entry could be simplified, but I’ll make you find it manually because that’s how I did it when I wrote the script and I don’t want to make it too easy on you
Also, I’ll apologize in advance for the script being on a single line and thus guaranteeing that it will require some sort of WinDBG Rosetta Stone in order to decipher (again, because that’s how I did it when I wrote it…Job security!).
First, you’ll need to dump the global type variable for the type of objects you want to see. Examples of these are IoFileObjectType, ExEventObjectType, IoDriverObjectType, etc. (if you’re having trouble finding the name of the one you want just let me know). I’ll pick the file object type:
1: kd> x nt!iofileobjecttype 82775a54 nt!IoFileObjectType = 0x83d656e0 1: kd> dt nt!_object_type 0x83d656e0 +0x000 TypeList : _LIST_ENTRY [ 0x83d8bb38 - 0x846022d0 ] +0x008 Name : _UNICODE_STRING "File" +0x010 DefaultObject : 0x0000005c Void +0x014 Index : 0x1c '' +0x018 TotalNumberOfObjects : 0x2d3 +0x01c TotalNumberOfHandles : 0xaa +0x020 HighWaterNumberOfObjects : 0x691 +0x024 HighWaterNumberOfHandles : 0xb6 +0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER +0x078 TypeLock : _EX_PUSH_LOCK +0x07c Key : 0x656c6946 +0x080 CallbackList : _LIST_ENTRY [ 0x83d65760 - 0x83d65760 ]
Note the TypeList field. That’s the list of currently valid objects for that type in the system in the form of OBJECT_HEADER_CREATOR_INFO structures, which currently exist directly before the object header. So, TypeList entry address + sizeof(OBJECT_HEADER_CREATOR_INFO) + FIELD_OFFSET(OBJECT_HEADER, Body) is where the actual object address is. I’ll put that all together into the following command (I’m going to break it up C style with “\” characters so you can see it, please remove before actually using and make into a single line):
r @$t0 = @@(sizeof(nt!_object_header_creator_info) \
+ #FIELD_OFFSET(nt!_object_header, Body)); \
!list "-x \".block {as /x Res @$extret+@$t0} ;\
.block{.echo ${Res}; !object ${Res}} ; \
ad /q Res\" 0x83d8bb38"
Note that the address used at the end of the command is from the dt output above in bold. Also remember that it’s written to occupy a single line, so it needs to get pasted into the KD prompt with no newlines and those backslashes removed. Running the command should provide you with relatively the same output at the old !object command on previous O/S releases.
If you’d like to clean up the script or, even better, turn it into a debugger extension that takes a name like !object, please let me know or send along the results. Right now it’s on my ever increases prioritized list of things to do and I’d like to take it off










