2
Work with NT Object tree manager
5
Return object type address by object address
8
Return typedVar of nt!_OBJECT_HEADER_NAME_INFO or None
11
Return string of object name. If can not get name - empty string
14
Return string of full object name. If can not get name - empty string
16
getListByHandleTable(tableHandles=None, objTypeAddr=0, containHeaders=True)
17
Return list of objects from table of handles
19
getListByDirectoryObject(p, objTypeAddr=0)
20
Return list of objects from object directory
22
getObjectByName(name, caseSensitive=False)
23
Return address of object by full name. If error (f.e. not exist) - None
32
OBJECT_HEADER = nt.type("_OBJECT_HEADER")
33
HANDLE_TABLE_ENTRY = nt.type("_HANDLE_TABLE_ENTRY")
34
OBJECT_DIRECTORY_ENTRY = nt.type("_OBJECT_DIRECTORY_ENTRY")
35
OBJECT_HEADER_NAME_INFO = nt.type("_OBJECT_HEADER_NAME_INFO")
41
Get object header by object pointer
42
Implementation for Win7+
44
objHeader = containingRecord(p, OBJECT_HEADER, "Body")
45
tableTypeIndex = nt.ObTypeIndexTable
46
return ptrPtr(tableTypeIndex + (ptrSize() * objHeader.TypeIndex))
50
Get object header by object pointer
51
Implementation for before Win7
53
objHeader = containingRecord(p, OBJECT_HEADER, "Body")
56
# Select platform-specific function for getting object header
57
# Select key body type: nt!CmpKeyObjectType or nt!CmKeyObjectType
58
if (ptrWord( nt.NtBuildNumber ) >= 7600):
60
# _kcbObjectType = expr("poi(nt!CmKeyObjectType)")
62
getType = getTypeLegacy
63
# _kcbObjectType = expr("poi(nt!CmpKeyObjectType)")
66
def getObjectNameInfoFromHeader(p):
68
Get object name information from field NameInfoOffset of object header
70
objHeader = containingRecord(p, OBJECT_HEADER, "Body")
71
if (0 == objHeader.NameInfoOffset):
73
return typedVar(OBJECT_HEADER_NAME_INFO, objHeader.getAddress() - objHeader.NameInfoOffset)
75
def getObjectNameInfoFromInfoMask(p):
77
Get object name information from field NameInfoOffset of object header
79
objHeader = containingRecord(p, OBJECT_HEADER, "Body")
80
if (0 == (objHeader.InfoMask & 2)):
82
offsetNameInfo = ptrByte( nt.ObpInfoMaskToOffset + (objHeader.InfoMask & 3) )
83
if (0 == offsetNameInfo):
85
return typedVar(OBJECT_HEADER_NAME_INFO, objHeader.getAddress() - offsetNameInfo)
88
# Select platform-specific function for getting name of object
89
getObjectNameInfo = None
91
OBJECT_HEADER.NameInfoOffset
92
getObjectNameInfo = getObjectNameInfoFromHeader
94
getObjectNameInfo = getObjectNameInfoFromInfoMask
99
Get object name by name information
101
nameInfo = getObjectNameInfo(p)
102
if (None == nameInfo):
104
return loadUnicodeString(nameInfo.Name.getAddress())
106
def buildObjectName(p):
108
Get object name by name information (parent directory handled)
112
nameInfo = getObjectNameInfo(p)
114
return objectFullName
115
namePart = loadUnicodeString(nameInfo.Name.getAddress())
117
objectFullName = namePart + "\\" + objectFullName
119
objectFullName = "\\" + objectFullName
121
while (0 != nameInfo.Directory):
122
p = nameInfo.Directory
123
nameInfo = getObjectNameInfo(p)
124
if (None == nameInfo):
125
return "...\\" + objectFullName
126
namePart = loadUnicodeString(nameInfo.Name.getAddress())
128
objectFullName = namePart + "\\" + objectFullName
130
objectFullName = "\\" + objectFullName
132
return objectFullName
137
HT_ENTRY_SIZE = (2 * ptrSize())
138
HT_LOWLEVEL_COUNT = HT_PAGE_SIZE // HT_ENTRY_SIZE
139
HT_MIDLEVEL_COUNT = HT_PAGE_SIZE // ptrSize()
141
def getListByHandleTable(tableHandles=None, objTypeAddr=0, containHeaders=True):
143
Build list of objects from target handle table
145
Parameter objTypeAddr if not 0 used for getting object of specific type,
146
otherwise get object of all types
148
Parameter containHeaders used to interpret table contents:
149
if containHeaders=True then table contains pointers to nt!_OBJECT_HEADER,
150
otherwise table contains pointers to objects
153
def getByHandleEntry(entryHandle, containHeader):
155
Query object pointer by handle entry from handle table
157
if (0 == entryHandle):
160
HandleEntry = typedVar( HANDLE_TABLE_ENTRY, entryHandle)
161
if (0xFFFFFFFE == HandleEntry.NextFreeTableEntry):
164
p = ptrPtr(HandleEntry.getAddress()) & 0xFFFFFFFFFFFFFFF8
169
objHeader = typedVar( OBJECT_HEADER, p)
170
p = objHeader.Body.getAddress()
173
def getListByHandleTableL0(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders):
175
Build list of objects from target handle table level 0
178
nTableLevel0Count = nMaxHandleIndex // HANDLE_VALUE_INC
179
for HandleEntryIndex in range(nTableLevel0Count):
181
pHandleEntry = pTableContent + (HT_ENTRY_SIZE * HandleEntryIndex)
182
p = getByHandleEntry(pHandleEntry, containHeaders)
186
if (0 == objTypeAddr):
187
lstObjects.append( ( p, HandleEntryIndex*HANDLE_VALUE_INC) )
189
pCurrentType = getType(p)
190
if (addr64(objTypeAddr) == addr64(pCurrentType)):
191
lstObjects.append( ( p, HandleEntryIndex*HANDLE_VALUE_INC) )
195
def getListByHandleTableL1(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders):
197
Build list of objects from target handle table level 1
200
nTableLevel1Count = (nMaxHandleIndex // HANDLE_VALUE_INC) // HT_LOWLEVEL_COUNT
201
for Index in range(nTableLevel1Count):
202
pTableLevel0 = ptrPtr(pTableContent + (Index * ptrSize()))
203
lstObjects += getListByHandleTableL0(pTableLevel0, HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, objTypeAddr, containHeaders)
207
def getListByHandleTableL2(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders):
209
Build list of objects from target handle table level 2
212
nTableLevel2Count = ((nMaxHandleIndex // HANDLE_VALUE_INC) // HT_LOWLEVEL_COUNT) // HT_MIDLEVEL_COUNT
213
for Index in range(nTableLevel2Count):
214
pTableLevel1 = ptrPtr(pTableContent + (Index * ptrSize()))
215
lstObjects += getListByHandleTableL1(pTableLevel1, HT_MIDLEVEL_COUNT * HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, objTypeAddr, containHeaders)
219
if (None == tableHandles):
220
currProcess = nt.typedVar("_EPROCESS", getCurrentProcess())
221
if (None == currProcess):
222
dprintln("Get current process failed")
224
tableHandles = currProcess.ObjectTable
226
tableHandles = nt.typedVar("_HANDLE_TABLE", tableHandles)
227
nMaxHandleIndex = tableHandles.NextHandleNeedingPool & 0xFFFFFFFF
228
nTableLevel = (tableHandles.TableCode & 3)
229
pTableContent = tableHandles.TableCode - nTableLevel
231
if (0 == nTableLevel):
232
return getListByHandleTableL0(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders)
233
elif (1 == nTableLevel):
234
return getListByHandleTableL1(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders)
235
elif (2 == nTableLevel):
236
return getListByHandleTableL2(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders)
238
dprintln("ERROR: Unknown handle table level: %u" % nTableLevel)
243
NUMBER_HASH_BUCKETS = 37
245
def getListByDirectoryObject(p, objTypeAddr=0):
247
Build list of objects from object directory
249
Parameter objTypeAddr if not 0 used for getting object of specific type,
250
otherwise get object of all types
253
if getType(p) != ptrPtr( nt.ObpDirectoryObjectType ):
258
for i in range(0, NUMBER_HASH_BUCKETS):
259
bucket = ptrPtr( p + (i * ptrSize()) )
261
bucketVar = typedVar( OBJECT_DIRECTORY_ENTRY, bucket)
262
if objTypeAddr and (getType(bucketVar.Object) == objTypeAddr):
263
result.append(bucketVar.Object)
264
elif (not objTypeAddr):
265
result.append(bucketVar.Object)
266
bucket = bucketVar.ChainLink
270
def getObjectByName(name, caseSensitive=False):
272
Query address of object by full name
275
def cmpCase(s1, s2): return s1 == s2
276
def cmpNoCase(s1, s2): return s1.lower() == s2.lower()
284
object = ptrPtr( nt.ObpRootDirectoryObject )
295
tok = name.find("\\")
297
namePart = name[:tok]
302
if 0 == len(namePart):
305
# FIXME: use name/index hash
306
lstObjects = getListByDirectoryObject(object)
307
if None == lstObjects:
312
objName = getObjectName(p)
313
if len(objName) and cmpFunc( namePart, objName ):
329
# Display object kd-command
331
addr64( expr("poi(nt!IoFileObjectType)") ) : "!fileobj",
332
addr64( expr("poi(nt!PsProcessType)") ) : "!process",
333
addr64( expr("poi(nt!PsThreadType)") ) : "!thread",
334
addr64( expr("poi(nt!IoDeviceObjectType)") ) : "!devobj",
335
addr64( expr("poi(nt!SeTokenObjectType)") ) : "!token",
336
# addr64( _kcbObjectType ) : "!reg kcb",
337
addr64( expr("poi(nt!IoDriverObjectType)") ) : "!drvobj 7"
342
Print content of object table (handle table)
345
!py ntobj [table= <ADDR>] [type= <ADDR>] [headers= <BOOL>]
347
When (options can be specified in any order):
348
table= <ADDR> : table of handle address. F.e. address object table
349
contained in field ObjectTable structure nt!_EPROCESS
350
default: nt!_EPROCESS.ObjectTable of current processes
352
type= <ADDR> : address of object type. If specified (!= 0) then print
353
object of target type only.
356
headers= <BOOL> : table of handles format: contain pointer to object or to
357
object header (nt!_OBJECT_HEADER): True or Flase
358
F.e. poi(nt!PspCidTable) contains objects (processes and
359
threads), and nt!_EPROCESS.ObjectTable contains headers
362
<link cmd=\"!py ntobj\">!py ntobj</link>
363
Print object table of current process
365
<link cmd=\"!py ntobj type= poi(nt!IoFileObjectType)\">!py ntobj type= poi(nt!IoFileObjectType)</link>
366
Print object table (only _FILE_OBJECT *) of current process
368
<link cmd=\"!py ntobj table= poi(poi(nt!PsInitialSystemProcess)+@@C++(#FIELD_OFFSET(nt!_EPROCESS,ObjectTable)))\">!py ntobj table= poi(poi(nt!PsInitialSystemProcess)+@@C++(#FIELD_OFFSET(nt!_EPROCESS,ObjectTable)))</link>
369
Print object table for SYSTEM process.
371
<link cmd=\"!py ntobj table= poi(nt!PspCidTable) headers= False type= poi(nt!PsProcessType)\">!py ntobj table= poi(nt!PspCidTable) headers= False type= poi(nt!PsProcessType)</link>
372
Print all process objects from nt!PspCidTable
375
if not isWindbgExt():
376
print "Script is launch out of WinDBG"
379
if not isKernelDebugging():
380
dprintln("This script for kernel debugging only")
385
if (2 == argc) and ("help" == sys.argv[1] or "?" == sys.argv[1]):
386
dprintln(main.__doc__, True)
389
if (0 == (argc % 2)):
390
dprintln("Invalid number of comand line arguments")
391
dprintln(main.__doc__, True)
396
containHeaders = True
398
for i in range(1, argc, 2):
399
if ("table=" == sys.argv[i]):
400
tableHandles = expr(sys.argv[i + 1])
401
elif ("type=" == sys.argv[i]):
402
objTypeAddr = expr(sys.argv[i + 1])
403
elif ("headers=" == sys.argv[i]):
404
containHeaders = ("True" == sys.argv[i + 1])
406
dprintln("Unknown option `" + sys.argv[i] + "'")
407
dprintln(main.__doc__, True)
410
ObjectHandlePairs = [ (p[0], p[1]) for p in getListByHandleTable(tableHandles, objTypeAddr, containHeaders) ]
412
dprintln("%u objects:" % len(ObjectHandlePairs))
413
for objectHandle in ObjectHandlePairs:
414
objectType = getType(objectHandle[0])
415
if objectType in ViewObjectCommand:
416
viewCommand = ViewObjectCommand[objectType]
418
viewCommand = "!object"
420
dprint("\t<link cmd=\"" + viewCommand + " 0x%x\">" % objectHandle[0] + viewCommand + " 0x%x</link>" % objectHandle[0], True)
421
objectName = buildObjectName(objectHandle[0])
423
dprint( ", name=`" + objectName + "'" )
424
elif nt.typedVar("_OBJECT_TYPE", getType(objectHandle[0])).TypeInfo.QueryNameProcedure:
425
dprint(", <i>custom</i> name", True)
427
dprint(" , <_unnamed_>")
429
dprint(", <link cmd=\"!handle 0x%x\">!handle 0x%x</link>\n" % (objectHandle[1], objectHandle[1]), True)
431
dprint("\ttype is `" + getObjectName(objectType) + "' (<link cmd=\"!object 0x%x\">0x%x</link>)" % (objectType, objectType), True)
436
dprintln("\n<link cmd=\"!py " + sys.argv[0] + " ?\" \">View help for ntobj</link>", True)
438
if __name__ == "__main__":