Skip to content

Commit

Permalink
More work on volatility - Now ssdt module uses object2.py
Browse files Browse the repository at this point in the history
darcs-hash:20090127030352-f1522-0ca9722fa03b83f388f1a0462274096eb790eb38.gz
  • Loading branch information
scudette committed Jan 27, 2009
1 parent 1057c2c commit bcf00b3
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ def is_valid(self):
def dereference(self):
return None

def dereference_as(self, castType):
return None
def dereference_as(self, derefType):
return NewObject(derefType, self.v(), \
self.vm, parent=self ,profile=self.profile)

def cast(self, castString):
return Object(castString, self.offset, self.vm, None, self.profile)
Expand Down Expand Up @@ -225,7 +226,7 @@ def size(self):

def value(self):
(val, ) = struct.unpack(self.format_string, \
self.vm.read(self.offset, self.size()))
self.vm.read(self.offset, self.size()))
return val

def cdecl(self):
Expand Down Expand Up @@ -273,16 +274,13 @@ def is_valid(self):

def dereference(self):
offset = self.v()

result = self.target(offset=offset, vm=self.vm, parent=self,
profile=self.profile, name=self.name)

if not result.is_valid(): return None

return result

def dereference_as(self, derefType):
return NewObject(derefType, self.v(), \
self.vm, parent=self ,profile=self.profile)

def cdecl(self):
return "Pointer %s" % self.v()

Expand All @@ -305,7 +303,8 @@ def __getattribute__(self, attr):
#if isinstance(result, CType):
# return result.m(attr)

return result
if result:
return result.__getattribute__(attr)

class CTypeMember:
""" A placeholder for a type in a struct.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,11 @@ def find_psactiveprocesshead(addr_space, types):
return None

KdVersionBlock = info_kdversionblock(addr_space, types, kpcr_addr)

if not addr_space.is_valid_address(KdVersionBlock):
print "Unable to find PsActiveProcessHead"
return None

DebuggerDataList = info_debuggerdatalist(addr_space, types, KdVersionBlock)

if addr_space.is_valid_address(DebuggerDataList):
current = read_value(addr_space, 'unsigned long', DebuggerDataList)
PsActiveProcessHead = info_psactiveprocesshead64(addr_space, types, current)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,33 @@

from forensics.object import *
from forensics.win32.info import *
from forensics.object2 import NewObject

def lsmod(addr_space, profile):
""" A Generator for modules (uses _KPCR symbols) """
## Locate the kpcr struct - this is hard coded right now
kpcr = NewObject("_KPCR", kpcr_addr, addr_space, profile=profile)

## Try to dereference the KdVersionBlock as a 64 bit struct
DebuggerDataList = kpcr.KdVersionBlock.dereference_as("_DBGKD_GET_VERSION64").DebuggerDataList

if DebuggerDataList.is_valid():
offset = DebuggerDataList.dereference().v()
## This is a pointer to a _KDDEBUGGER_DATA64 struct. We only
## care about the PsActiveProcessHead entry:
tmp = NewObject("_KDDEBUGGER_DATA64", offset,
addr_space, profile=profile).PsLoadedModuleList

if not tmp.is_valid():
## Ok maybe its a 32 bit struct
tmp = NewObject("_KDDEBUGGER_DATA32", offset,
addr_space, profile=profile).PsLoadedModuleList

## Try to iterate over the process list in PsActiveProcessHead
## (its really a pointer to a _LIST_ENTRY)
for l in tmp.dereference_as("_LIST_ENTRY").list_of_type(
"_LDR_MODULE", "InLoadOrderModuleList"):
yield l

def modules_list(addr_space, types, symbol_table):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ def process_list(addr_space, types, symbol_table=None):

PsActiveProcessHead = find_psactiveprocesshead(addr_space,types)

print "head is %s" % PsActiveProcessHead

if not PsActiveProcessHead is None:
(offset, tmp) = get_obj_offset(types, ['_EPROCESS', 'ActiveProcessLinks'])

Expand Down Expand Up @@ -133,7 +131,6 @@ def find_dtb(addr_space, types):
try:
flat_address_space = FileAddressSpace(addr_space.name,fast=True)
except Exception,e:
print e
op.error("Unable to open image file %s" % (filename))

offset = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ def list_of_type(self, type, member, forward=True):
yield obj

def __iter__(self):
print self.parent, self.name
return self.list_of_type(self.parent, self.name)

class String(NativeType):
Expand All @@ -94,7 +93,7 @@ def __init__(self, type, offset, vm=None,
def __str__(self):
data = self.v()
## Make sure its null terminated:
return data.strip("\x00")
return data.split("\x00")[0]

class WinTimeStamp(NativeType):
def __init__(self, type, offset, vm=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,20 @@ def calculate(self):
task_info['process_id'] = task.UniqueProcessId or -1
task_info['active_threads'] = task.ActiveThreads or -1
task_info['inherited_from'] = task.InheritedFromUniqueProcessId.v() or -1
task_info['handle_count'] = task.ObjectTable.HandleCount.v() or -1
task_info['handle_count'] = task.ObjectTable.HandleCount or -1
task_info['create_time'] = task.CreateTime

## Get the Process Environment Block - Note that _EPROCESS
## will automatically switch to process address space by
## itself.
peb = task.Peb
if peb:
task_info['command_line'] = peb.ProcessParameters.dereference().CommandLine.v()
task_info['ImagePathName'] = peb.ProcessParameters.dereference().ImagePathName
if self.opts.verbose:
peb = task.Peb
if peb:
task_info['command_line'] = peb.ProcessParameters.CommandLine
task_info['ImagePathName'] = peb.ProcessParameters.ImagePathName

task_info['Audit ImageFileName'] = task.SeAuditProcessCreationInfo.ImageFileName.dereference().Name or 'UNKNOWN'

## Thats the tedious way:
##process_ad = get_process_address_space(task)
## if process_ad:
## peb = NewObject("_PEB", task.m("Peb").offset, vm=process_ad,profile=self.profile)

## if peb.is_valid():
## task_info['command_line'] = peb.ProcessParameters.CommandLine
## task_info['ImagePathName'] = peb.ProcessParameters.ImagePathName

#self.find_command_line(addr_space,types, task, task_info)
#self.find_se_audit(addr_space, types, task, task_info)

task_info['Audit ImageFileName'] = task.SeAuditProcessCreationInfo.ImageFileName.Name or 'UNKNOWN'

result[task] = task_info
self.pids[task_info['process_id']] = task

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
from bisect import bisect_right

from forensics.object2 import *
from forensics.win32.tasks import process_list
from forensics.win32.modules import modules_list
from forensics.win32.tasks import pslist
from forensics.win32.modules import lsmod
from forensics.win32.lists import list_entry
from forensics.object import get_obj_offset
from vutils import *
Expand Down Expand Up @@ -1006,11 +1006,6 @@
],
]

def get_threads(proc):
return list_entry(proc.vm, types, proc.profile,
proc.ThreadListHead.v(), "_ETHREAD",
fieldname="ThreadListEntry")

def find_module(modlist, mod_addrs, addr):
"""Uses binary search to find what module a given address resides in.
Expand All @@ -1029,18 +1024,16 @@ def find_module(modlist, mod_addrs, addr):
return None

class ssdt(forensics.commands.command):

# Declare meta information associated with this plugin
meta_info = {
'author': 'Brendan Dolan-Gavitt',
'copyright': 'Copyright (c) 2007,2008 Brendan Dolan-Gavitt',
'contact': '[email protected]',
'license': 'GNU General Public License 2.0 or later',
'url': 'http://moyix.blogspot.com/',
'os': 'WIN_32_XP_SP2',
'version': '1.0'}

meta_info = forensics.commands.command.meta_info
meta_info['author'] = 'Brendan Dolan-Gavitt'
meta_info['copyright'] = 'Copyright (c) 2007,2008 Brendan Dolan-Gavitt'
meta_info['contact'] = '[email protected]'
meta_info['license'] = 'GNU General Public License 2.0 or later'
meta_info['url'] = 'http://moyix.blogspot.com/'
meta_info['os'] = 'WIN_32_XP_SP2'
meta_info['version'] = '1.0'

def help(self):
return "Display SSDT entries"

Expand All @@ -1055,21 +1048,15 @@ def execute(self):

(addr_space, symtab, types) = load_and_identify_image(self.op,
self.opts)

pslist = process_list(addr_space, types, symtab)
procs = [ NewObject("_EPROCESS", p, addr_space, profile=profile)
for p in pslist ]

modlist = modules_list(addr_space, types, symtab)
mods = [ NewObject("_LDR_MODULE", m, addr_space, profile=profile)
for m in modlist ]
mods = dict( (mod.BaseAddress.v(),mod) for mod in mods )
## Get a sorted list of module addresses
mods = dict( (mod.BaseAddress.v(),mod) for mod in lsmod(addr_space, profile) )
mod_addrs = sorted(mods.keys())

# Gather up all SSDTs referenced by threads
print "Gathering all referenced SSDTs from KTHREADs..."
ssdts = set()
for proc in procs:
for proc in pslist(addr_space, profile):
for thread in proc.ThreadListHead.list_of_type("_ETHREAD", "ThreadListEntry"):
ssdt = thread.Tcb.ServiceTable.dereference()
ssdts.add(ssdt)
Expand All @@ -1086,15 +1073,19 @@ def execute(self):
tables_with_vm = []
for idx, table, n in tables:
found = False
for p in procs:
if p.vm.is_valid_address(table):
tables_with_vm.append( (idx, table, n, p.vm) )
for p in pslist(addr_space, profile):
## This is the process address space
ps_ad = p.get_process_address_space()
## Is the table accessible from the process AS?
if ps_ad.is_valid_address(table):
tables_with_vm.append( (idx, table, n, ps_ad) )
found = True
break
## If not we use the kernel address space
if not found:
# Any VM is equally bad...
tables_with_vm.append( (idx, table, n, addr_space) )

# Print out the entries for each table
for idx,table,n,vm in sorted(tables_with_vm, key=itemgetter(0)):
print "SSDT[%d] at %x with %d entries" % (idx,table, n)
Expand All @@ -1117,4 +1108,4 @@ def execute(self):
syscall_name,
syscall_modname)
else:
print " [SSDT not resident]"
print " [SSDT not resident at 0x%08X ]" % table
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
'WorkingSetLock' : [ 0xcc, ['_FAST_MUTEX']], \
'AddressCreationLock' : [ 0xf0, ['_FAST_MUTEX']], \
'VadRoot' : [ 0x11c, ['pointer', ['void']]], \
'InheritedFromUniqueProcessId' : [ 0x14c, ['pointer', ['void']]], \
# 'InheritedFromUniqueProcessId' : [ 0x14c, ['pointer', ['void']]], \
'InheritedFromUniqueProcessId' : [ 0x14c, ['unsigned int']], \
# 'ImageFileName' : [ 0x174, ['array', 16,['unsigned char']]], \
'ImageFileName' : [ 0x174, ['String', dict(length=16)]], \
'ThreadListHead' : [ 0x190, ['_LIST_ENTRY']], \
Expand Down

0 comments on commit bcf00b3

Please sign in to comment.