mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-29 11:53:23 +08:00
[~] 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:
parent
a95d0c23c5
commit
3e9951b63b
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user