[~] 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
This commit is contained in:
SND\EreTIk_cp 2011-04-19 21:58:03 +00:00
parent a95d0c23c5
commit 3e9951b63b

View File

@ -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=<True|False>, 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):
def main():
"""
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))
Print content of object table (handle table)
Usage:
!py ntobj [table= <ADDR>] [type= <ADDR>] [headers= <BOOL>]
When (options can be specified in any order):
table= <ADDR> : table of handle address. F.e. address object table
contained in field ObjectTable structure nt!_EPROCESS
default: nt!_EPROCESS.ObjectTable of current processes
type= <ADDR> : address of object type. If specified (!= 0) then print
object of target type only.
default: 0
headers= <BOOL> : 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:
<link cmd=\"!py ntobj\">!py ntobj</link>
Print object table of current process
<link cmd=\"!py ntobj type= poi(nt!IoFileObjectType)\">!py ntobj type= poi(nt!IoFileObjectType)</link>
Print object table (only _FILE_OBJECT *) of current process
<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>
Print object table for SYSTEM process.
<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>
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 (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("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=<link cmd=\"" + viewCommand + " 0x%x\">" % object + viewCommand + " 0x%x</link>" % object, True)
objectName = buildObjectName(object)
if len(objectName):
dprintln( ", name=`" + objectName + "'" )
elif typedVar("nt", "_OBJECT_TYPE", getType(object)).TypeInfo.QueryNameProcedure:
dprintln(", <i>custom</i> name", True)
else:
dprintln(" , <_unnamed_>")
dprint("\ttype is `" + getObjectName(objectType) + "' (<link cmd=\"!object 0x%x\">0x%x</link>)" % (objectType, objectType), True)
dprintln( "\n" )
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)
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=<True|False>, by default is True]")
dprintln("\n<link cmd=\"!py " + sys.argv[0] + " ?\" \">View help for ntobj</link>", True)
if __name__ == "__main__":
main()