2010-12-23 19:10:08 +08:00
|
|
|
#
|
|
|
|
# Work with NT Object tree manager
|
|
|
|
#
|
|
|
|
# To use:
|
|
|
|
#
|
|
|
|
# ntobj.getType(p)
|
|
|
|
# query object header by object pointer
|
|
|
|
#
|
|
|
|
# ntobj.getListByHandleTable(pHandleTable, pType=0, bContainHeaders=True)
|
|
|
|
# build object list from handle table
|
|
|
|
#
|
|
|
|
|
|
|
|
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")
|
2010-12-23 19:56:03 +08:00
|
|
|
return ptrPtr(pTypeIndexTable + (ptrSize() * pHeader.TypeIndex))
|
2010-12-23 19:10:08 +08:00
|
|
|
|
|
|
|
def getTypeLegacy(p):
|
|
|
|
"""
|
|
|
|
Get object header by object pointer
|
|
|
|
Implementation for before Win7
|
|
|
|
"""
|
|
|
|
pHeader = containingRecord(p, "nt", "_OBJECT_HEADER", "Body")
|
2010-12-23 19:56:03 +08:00
|
|
|
return addr64(pHeader.Type)
|
2010-12-23 19:10:08 +08:00
|
|
|
|
|
|
|
# Select platform-specific function for getting object header
|
|
|
|
if (ptrWord(getOffset("nt", "NtBuildNumber")) >= 7600):
|
|
|
|
getType = getTypeWin7
|
|
|
|
else:
|
|
|
|
getType = getTypeLegacy
|
|
|
|
|
|
|
|
HANDLE_VALUE_INC = 4
|
|
|
|
HT_PAGE_SIZE = 4096
|
|
|
|
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):
|
|
|
|
"""
|
|
|
|
Build list of objects from target handle table
|
|
|
|
|
|
|
|
Parameter pType 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,
|
|
|
|
otherwise table contains pointers to objects
|
|
|
|
"""
|
|
|
|
|
|
|
|
def getByHandleEntry(hEntry, bContainHeader):
|
|
|
|
"""
|
|
|
|
Query object pointer by handle entry from handle table
|
|
|
|
"""
|
|
|
|
if (0 == hEntry):
|
|
|
|
return 0
|
|
|
|
|
|
|
|
HandleEntry = typedVar("nt", "_HANDLE_TABLE_ENTRY", addr64(hEntry))
|
|
|
|
if (0xFFFFFFFE == HandleEntry.NextFreeTableEntry):
|
|
|
|
return 0
|
|
|
|
|
|
|
|
p = ptrPtr(HandleEntry.getAddress()) & 0xFFFFFFFFFFFFFFF8
|
|
|
|
if (0 == p):
|
|
|
|
return 0
|
|
|
|
|
|
|
|
if (bContainHeader):
|
|
|
|
pHeader = typedVar("nt", "_OBJECT_HEADER", addr64(p))
|
|
|
|
p = pHeader.Body.getAddress()
|
|
|
|
return p
|
|
|
|
|
|
|
|
def getListByHandleTableL0(pTableContent, nMaxHandleIndex, pType, bContainHeaders):
|
|
|
|
"""
|
|
|
|
Build list of objects from target handle table level 0
|
|
|
|
"""
|
|
|
|
lstObjects = list()
|
|
|
|
nTableLevel0Count = nMaxHandleIndex // HANDLE_VALUE_INC
|
|
|
|
for HandleEntryIndex in range(nTableLevel0Count):
|
|
|
|
|
|
|
|
pHandleEntry = pTableContent + (HT_ENTRY_SIZE * HandleEntryIndex)
|
|
|
|
p = getByHandleEntry(pHandleEntry, bContainHeaders)
|
|
|
|
if (0 == p):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if (0 == pType):
|
|
|
|
lstObjects.append(p)
|
|
|
|
else:
|
|
|
|
pCurrentType = getType(p)
|
|
|
|
if (addr64(pType) == pCurrentType):
|
|
|
|
lstObjects.append(p)
|
|
|
|
|
|
|
|
return lstObjects
|
|
|
|
|
|
|
|
def getListByHandleTableL1(pTableContent, nMaxHandleIndex, pType, bContainHeaders):
|
|
|
|
"""
|
|
|
|
Build list of objects from target handle table level 1
|
|
|
|
"""
|
|
|
|
lstObjects = list()
|
|
|
|
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)
|
|
|
|
|
|
|
|
return lstObjects
|
|
|
|
|
|
|
|
def getListByHandleTableL2(pTableContent, nMaxHandleIndex, pType, bContainHeaders):
|
|
|
|
"""
|
|
|
|
Build list of objects from target handle table level 2
|
|
|
|
"""
|
|
|
|
lstObjects = list()
|
|
|
|
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)
|
|
|
|
|
|
|
|
return lstObjects
|
|
|
|
|
|
|
|
pHandleTable = typedVar("nt", "_HANDLE_TABLE", pHandleTable)
|
|
|
|
nMaxHandleIndex = pHandleTable.NextHandleNeedingPool & 0xFFFFFFFF
|
|
|
|
nTableLevel = (pHandleTable.TableCode & 3)
|
|
|
|
pTableContent = pHandleTable.TableCode - nTableLevel
|
|
|
|
|
|
|
|
if (0 == nTableLevel):
|
|
|
|
return getListByHandleTableL0(pTableContent, nMaxHandleIndex, pType, bContainHeaders)
|
|
|
|
elif (1 == nTableLevel):
|
|
|
|
return getListByHandleTableL1(pTableContent, nMaxHandleIndex, pType, bContainHeaders)
|
|
|
|
elif (2 == nTableLevel):
|
|
|
|
return getListByHandleTableL2(pTableContent, nMaxHandleIndex, pType, bContainHeaders)
|
|
|
|
|
|
|
|
dprintln("ERROR: Unknown handle table level: %u" % nTableLevel)
|
|
|
|
return list()
|