From 3e9951b63b5bdd00d13fe1d0dcef90c40ade1f5a Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Tue, 19 Apr 2011 21:58:03 +0000 Subject: [PATCH] [~] add dml output [~] add funtion for get object name [~] add funtion for build full name [~] cast to camel case style git-svn-id: https://pykd.svn.codeplex.com/svn@64247 9b283d60-5439-405e-af05-b73fd8c4d996 --- snippets/ntobj.py | 313 +++++++++++++++++++++++++++++++++------------- 1 file changed, 228 insertions(+), 85 deletions(-) diff --git a/snippets/ntobj.py b/snippets/ntobj.py index 42aacf8..b360252 100644 --- a/snippets/ntobj.py +++ b/snippets/ntobj.py @@ -1,39 +1,122 @@ -# -# Work with NT Object tree manager -# -# To use: -# -# ntobj.getType(p) -# query object type by object pointer -# -# ntobj.getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True) -# build object list from handle table -# +""" +Work with NT Object tree manager + + getType(p) + Return object type address by object address + + getObjectNameInfo(p) + Return typedVar of nt!_OBJECT_HEADER_NAME_INFO or None + + getObjectName(p) + Return string of object name. If can not get name - empty string + + buildObjectName(p) + Return string of full object name. If can not get name - empty string + + def getListByHandleTable(tableHandles=None, objTypeAddr=0, containHeaders=True) + Return list of objects from table of handles +""" from pykd import * + + def getTypeWin7(p): """ Get object header by object pointer Implementation for Win7+ """ - pHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") - pTypeIndexTable = getOffset("nt", "ObTypeIndexTable") - return ptrPtr(pTypeIndexTable + (ptrSize() * pHeader.TypeIndex)) + objHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") + tableTypeIndex = getOffset("nt", "ObTypeIndexTable") + return ptrPtr(tableTypeIndex + (ptrSize() * objHeader.TypeIndex)) def getTypeLegacy(p): """ Get object header by object pointer Implementation for before Win7 """ - pHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") - return pHeader.Type + objHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") + return objHeader.Type # Select platform-specific function for getting object header +# Select key body type: nt!CmpKeyObjectType or nt!CmKeyObjectType if (ptrWord(getOffset("nt", "NtBuildNumber")) >= 7600): getType = getTypeWin7 + # _kcbObjectType = expr("poi(nt!CmKeyObjectType)") else: getType = getTypeLegacy + # _kcbObjectType = expr("poi(nt!CmpKeyObjectType)") + + +def getObjectNameInfoFromHeader(p): + """ + Get object name information from field NameInfoOffset of object header + """ + objHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") + if (0 == objHeader.NameInfoOffset): + return None + return typedVar("nt", "_OBJECT_HEADER_NAME_INFO", objHeader.getAddress() - objHeader.NameInfoOffset) + +def getObjectNameInfoFromInfoMask(p): + """ + Get object name information from field NameInfoOffset of object header + """ + objHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body") + if (0 == (objHeader.InfoMask & 2)): + return None + offsetNameInfo = ptrByte( getOffset("nt", "ObpInfoMaskToOffset") + (objHeader.InfoMask & 3) ) + if (0 == offsetNameInfo): + return None + return typedVar("nt", "_OBJECT_HEADER_NAME_INFO", objHeader.getAddress() - offsetNameInfo) + + +# Select platform-specific function for getting name of object +getObjectNameInfo = None +try: + getTypeClass("nt", "_OBJECT_HEADER").NameInfoOffset + getObjectNameInfo = getObjectNameInfoFromHeader +except AttributeError: + getObjectNameInfo = getObjectNameInfoFromInfoMask + + +def getObjectName(p): + """ + Get object name by name information + """ + nameInfo = getObjectNameInfo(p) + if (None == nameInfo): + return "" + return loadUnicodeString(nameInfo.Name.getAddress()) + +def buildObjectName(p): + """ + Get object name by name information (parent directory handled) + """ + objectFullName = "" + + nameInfo = getObjectNameInfo(p) + if None == nameInfo: + return objectFullName + namePart = loadUnicodeString(nameInfo.Name.getAddress()) + if namePart != "\\": + objectFullName = namePart + "\\" + objectFullName + else: + objectFullName = "\\" + objectFullName + + while (0 != nameInfo.Directory): + p = nameInfo.Directory + nameInfo = getObjectNameInfo(p) + if (None == nameInfo): + return "...\\" + objectFullName + namePart = loadUnicodeString(nameInfo.Name.getAddress()) + if namePart != "\\": + objectFullName = namePart + "\\" + objectFullName + else: + objectFullName = "\\" + objectFullName + + return objectFullName + + HANDLE_VALUE_INC = 4 HT_PAGE_SIZE = 4096 @@ -41,26 +124,26 @@ HT_ENTRY_SIZE = (2 * ptrSize()) HT_LOWLEVEL_COUNT = HT_PAGE_SIZE // HT_ENTRY_SIZE HT_MIDLEVEL_COUNT = HT_PAGE_SIZE // ptrSize() -def getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True): +def getListByHandleTable(tableHandles=None, objTypeAddr=0, containHeaders=True): """ Build list of objects from target handle table - Parameter pType if not 0 used for getting object of specific type, + Parameter objTypeAddr if not 0 used for getting object of specific type, otherwise get object of all types - Parameter bContainHeaders used to interpret table contents: - if bContainHeaders=True then table contains pointers to nt!_OBJECT_HEADER, + Parameter containHeaders used to interpret table contents: + if containHeaders=True then table contains pointers to nt!_OBJECT_HEADER, otherwise table contains pointers to objects """ - def getByHandleEntry(hEntry, bContainHeader): + def getByHandleEntry(entryHandle, containHeader): """ Query object pointer by handle entry from handle table """ - if (0 == hEntry): + if (0 == entryHandle): return 0 - HandleEntry = typedVar("nt", "_HANDLE_TABLE_ENTRY", hEntry) + HandleEntry = typedVar("nt", "_HANDLE_TABLE_ENTRY", entryHandle) if (0xFFFFFFFE == HandleEntry.NextFreeTableEntry): return 0 @@ -68,12 +151,12 @@ def getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True): if (0 == p): return 0 - if (bContainHeader): - pHeader = typedVar("nt", "_OBJECT_HEADER", p) - p = pHeader.Body.getAddress() + if (containHeader): + objHeader = typedVar("nt", "_OBJECT_HEADER", p) + p = objHeader.Body.getAddress() return p - def getListByHandleTableL0(pTableContent, nMaxHandleIndex, pType, bContainHeaders): + def getListByHandleTableL0(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders): """ Build list of objects from target handle table level 0 """ @@ -82,20 +165,20 @@ def getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True): for HandleEntryIndex in range(nTableLevel0Count): pHandleEntry = pTableContent + (HT_ENTRY_SIZE * HandleEntryIndex) - p = getByHandleEntry(pHandleEntry, bContainHeaders) + p = getByHandleEntry(pHandleEntry, containHeaders) if (0 == p): continue - if (0 == pType): + if (0 == objTypeAddr): lstObjects.append(p) else: pCurrentType = getType(p) - if (addr64(pType) == addr64(pCurrentType)): + if (addr64(objTypeAddr) == addr64(pCurrentType)): lstObjects.append(p) return lstObjects - def getListByHandleTableL1(pTableContent, nMaxHandleIndex, pType, bContainHeaders): + def getListByHandleTableL1(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders): """ Build list of objects from target handle table level 1 """ @@ -103,11 +186,11 @@ def getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True): nTableLevel1Count = (nMaxHandleIndex // HANDLE_VALUE_INC) // HT_LOWLEVEL_COUNT for Index in range(nTableLevel1Count): pTableLevel0 = ptrPtr(pTableContent + (Index * ptrSize())) - lstObjects += getListByHandleTableL0(pTableLevel0, HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, pType, bContainHeaders) + lstObjects += getListByHandleTableL0(pTableLevel0, HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, objTypeAddr, containHeaders) return lstObjects - def getListByHandleTableL2(pTableContent, nMaxHandleIndex, pType, bContainHeaders): + def getListByHandleTableL2(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders): """ Build list of objects from target handle table level 2 """ @@ -115,76 +198,136 @@ def getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True): nTableLevel2Count = ((nMaxHandleIndex // HANDLE_VALUE_INC) // HT_LOWLEVEL_COUNT) // HT_MIDLEVEL_COUNT for Index in range(nTableLevel2Count): pTableLevel1 = ptrPtr(pTableContent + (Index * ptrSize())) - lstObjects += getListByHandleTableL1(pTableLevel1, HT_MIDLEVEL_COUNT * HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, pType, bContainHeaders) + lstObjects += getListByHandleTableL1(pTableLevel1, HT_MIDLEVEL_COUNT * HT_LOWLEVEL_COUNT * HANDLE_VALUE_INC, objTypeAddr, containHeaders) return lstObjects - pHandleTable = typedVar("nt", "_HANDLE_TABLE", pHandleTable) - nMaxHandleIndex = pHandleTable.NextHandleNeedingPool & 0xFFFFFFFF - nTableLevel = (pHandleTable.TableCode & 3) - pTableContent = pHandleTable.TableCode - nTableLevel + if (None == tableHandles): + currProcess = typedVar("nt", "_EPROCESS", getCurrentProcess()) + if (None == currProcess): + dprintln("Get current process failed") + return + tableHandles = currProcess.ObjectTable + + tableHandles = typedVar("nt", "_HANDLE_TABLE", tableHandles) + nMaxHandleIndex = tableHandles.NextHandleNeedingPool & 0xFFFFFFFF + nTableLevel = (tableHandles.TableCode & 3) + pTableContent = tableHandles.TableCode - nTableLevel if (0 == nTableLevel): - return getListByHandleTableL0(pTableContent, nMaxHandleIndex, pType, bContainHeaders) + return getListByHandleTableL0(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders) elif (1 == nTableLevel): - return getListByHandleTableL1(pTableContent, nMaxHandleIndex, pType, bContainHeaders) + return getListByHandleTableL1(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders) elif (2 == nTableLevel): - return getListByHandleTableL2(pTableContent, nMaxHandleIndex, pType, bContainHeaders) + return getListByHandleTableL2(pTableContent, nMaxHandleIndex, objTypeAddr, containHeaders) dprintln("ERROR: Unknown handle table level: %u" % nTableLevel) return list() import sys -if __name__ == "__main__": - # - # Print content of object table (handle table) - # - # Usage: - # - # !py ntobj [ObjectTableAddr] [ContainHeaders=, by default is True] - # - # Examples: - # - # !py ntobj.py - # Print object table of current process - # - # !py ntobj.py aabbccee - # Print object table by address 0xaabbccee. F.e. address object table - # contained in field ObjectTable structure nt!_EPROCESS - # - # !py ntobj.py eeccbbaa False - # When 0xeeccbbaa is poi(nt!PspCidTable) - # Print all thread and process - # +# Display object kd-command +ViewObjectCommand = { + addr64( expr("poi(nt!IoFileObjectType)") ) : "!fileobj", + addr64( expr("poi(nt!PsProcessType)") ) : "!process", + addr64( expr("poi(nt!PsThreadType)") ) : "!thread", + addr64( expr("poi(nt!IoDeviceObjectType)") ) : "!devobj", + addr64( expr("poi(nt!SeTokenObjectType)") ) : "!token", + # addr64( _kcbObjectType ) : "!reg kcb", + addr64( expr("poi(nt!IoDriverObjectType)") ) : "!drvobj 7" +} - def printObjectTable(pObjectTable, bHeaders): - """ - Print content of object table - """ - lstObjects = getListByHandleTable(pObjectTable, bContainHeaders=bHeaders) - dprintln("%u objects:" % len(lstObjects)) - for obj in lstObjects: - dprintln("obj: 0x%X" % obj + " type: 0x%X" % getType(obj)) +def main(): + """ + Print content of object table (handle table) + + Usage: + !py ntobj [table= ] [type= ] [headers= ] + When (options can be specified in any order): + table= : table of handle address. F.e. address object table + contained in field ObjectTable structure nt!_EPROCESS + default: nt!_EPROCESS.ObjectTable of current processes + + type= : address of object type. If specified (!= 0) then print + object of target type only. + default: 0 + + headers= : table of handles format: contain pointer to object or to + object header (nt!_OBJECT_HEADER): True or Flase + F.e. poi(nt!PspCidTable) contains objects (processes and + threads), and nt!_EPROCESS.ObjectTable contains headers + default: True + Examples: + !py ntobj + Print object table of current process + + !py ntobj type= poi(nt!IoFileObjectType) + Print object table (only _FILE_OBJECT *) of current process + + !py ntobj table= poi(poi(nt!PsInitialSystemProcess)+@@C++(#FIELD_OFFSET(nt!_EPROCESS,ObjectTable))) + Print object table for SYSTEM process. + + !py ntobj table= poi(nt!PspCidTable) headers= False type= poi(nt!PsProcessType) + Print all process objects from nt!PspCidTable + """ if not isWindbgExt(): print "Script is launch out of WinDBG" - quit(0) + return + + if not isKernelDebugging(): + dprintln("This script for kernel debugging only") + return argc = len(sys.argv) - if (1 == argc): - process = typedVar("nt", "_EPROCESS", getCurrentProcess()) - printObjectTable(process.ObjectTable, True) - elif (2 == argc): - printObjectTable(int(sys.argv[1], 16), True) - elif (3 == argc): - bHeaders = True - if (sys.argv[2].lower() == "true"): - printObjectTable(int(sys.argv[1], 16), True) - elif (sys.argv[2].lower() == "false"): - printObjectTable(int(sys.argv[1], 16), False) + + if (2 == argc) and ("help" == sys.argv[1] or "?" == sys.argv[1]): + dprintln(main.__doc__, True) + return + + if (0 == (argc % 2)): + dprintln("Invalid number of comand line arguments") + dprintln(main.__doc__, True) + return + + tableHandles = None + objTypeAddr = 0 + containHeaders = True + + for i in range(1, argc, 2): + if ("table=" == sys.argv[i]): + tableHandles = expr(sys.argv[i + 1]) + elif ("type=" == sys.argv[i]): + objTypeAddr = expr(sys.argv[i + 1]) + elif ("headers=" == sys.argv[i]): + containHeaders = ("True" == sys.argv[i + 1]) else: - dprintln("Invalid command line, usage: " + sys.argv[0] + " [ObjectTableAddr] [ContainHeaders=True|False, by default is True]") - else: - dprintln("Invalid command line, usage: " + sys.argv[0] + " [ObjectTableAddr] [ContainHeaders=, by default is True]") + dprintln("Unknown option `" + sys.argv[i] + "'") + dprintln(main.__doc__, True) + return + + lstObjects = getListByHandleTable(tableHandles, objTypeAddr, containHeaders) + dprintln("%u objects:" % len(lstObjects)) + for object in lstObjects: + objectType = getType(object) + if objectType in ViewObjectCommand: + viewCommand = ViewObjectCommand[objectType] + else: + viewCommand = "!object" + dprint("\tobject=" % object + viewCommand + " 0x%x" % object, True) + objectName = buildObjectName(object) + if len(objectName): + dprintln( ", name=`" + objectName + "'" ) + elif typedVar("nt", "_OBJECT_TYPE", getType(object)).TypeInfo.QueryNameProcedure: + dprintln(", custom name", True) + else: + dprintln(" , <_unnamed_>") + dprint("\ttype is `" + getObjectName(objectType) + "' (0x%x)" % (objectType, objectType), True) + dprintln( "\n" ) + + if (1 == argc): + dprintln("\nView help for ntobj", True) + +if __name__ == "__main__": + main()