def collect_inline_hooks(self): for function, _, destination in self.detect_inline_hooks(): hook_detected = False # Try to resolve the destination into a name. destination_name = self.reported_access(destination) # We know about it. We suppress the output for jumps that go into a # known module. These should be visible using the regular vad # module. if destination_name: hook_detected = True # Skip non hooked results if verbosity is too low. if self.plugin_args.verbosity < 10 and not hook_detected: continue # Only highlight results if verbosity is high. highlight = "" if hook_detected and self.plugin_args.verbosity > 1: highlight = "important" yield dict(Type="Inline", source_name=utils.FormattedAddress( self.session.address_resolver, function.deref(), max_count=1), target_name=utils.FormattedAddress( self.session.address_resolver, destination, max_count=1), source_func=function.deref(), target_func=self.session.profile.Function(destination), highlight=highlight)
def collect(self): """Render output.""" count = 0 for run in self.generate_memory_ranges(): for rule, address in self.generate_hits(run): count += 1 if count >= self.plugin_args.hits: break # Result hit the physical memory - Get some context on this hit. if run.data.get("type") == "PhysicalAS": symbol = pfn.PhysicalAddressContext(self.session, address) else: symbol = utils.FormattedAddress( self.session.address_resolver, address, max_distance=2**64) yield dict( Owner=run.data.get("task") or run.data.get("type"), Rule=rule, Offset=address, hexdump=utils.HexDumpedString( run.address_space.read( address - self.plugin_args.pre_context, self.plugin_args.context + self.plugin_args.pre_context)), Context=symbol, # Provide the address space where the hit is reported. address_space=run.address_space, run=run)
def get_generic_callbacks(self, renderer): resolver = self.session.address_resolver for table, table_length in [ ("nt!PspLoadImageNotifyRoutine", "nt!PspLoadImageNotifyRoutineCount"), ("nt!PspCreateThreadNotifyRoutine", "nt!PspCreateThreadNotifyRoutineCount"), ("nt!PspCreateProcessNotifyRoutine", "nt!PspCreateProcessNotifyRoutineCount")]: array_length = resolver.get_constant_object( table_length, "unsigned long long") array = resolver.get_constant_object( table, target="Array", count=array_length, target_args=dict( target="_EX_FAST_REF", target_args=dict( target="_GENERIC_CALLBACK" ) ) ) for callback in array: function = callback.Callback renderer.table_row( table, callback, function, utils.FormattedAddress(resolver, function))
def collect(self): # Print kuser_shared things. kuser_shared = self.profile.get_constant_object( "KI_USER_SHARED_DATA", "_KUSER_SHARED_DATA") interrupt_time = ((kuser_shared.InterruptTime.High1Time << 32) + kuser_shared.InterruptTime.LowPart) now = kuser_shared.SystemTime.as_windows_timestamp() - interrupt_time seen = set() for i, timer in self.timers(): if timer in seen: continue seen.add(timer) if timer.Header.SignalState.v(): signaled = "Yes" else: signaled = "-" yield (i, timer, # Due time in InterruptTime (100ns). "0x%0.20x" % timer.DueTime.QuadPart, self.profile.WinFileTime(value=now+timer.DueTime.QuadPart, is_utc=True), timer.Period, signaled, timer.Dpc.DeferredRoutine, utils.FormattedAddress(self.session.address_resolver, timer.Dpc.DeferredRoutine))
def _render_x86_table(self, table, renderer): resolver = self.session.address_resolver for j, function_address in enumerate(table): renderer.table_row( j, function_address, utils.FormattedAddress(resolver, function_address))
def render(self, renderer): for session in self.session_spaces(): renderer.section() processes = list( session.ProcessList.list_of_type("_EPROCESS", "SessionProcessLinks")) renderer.format("Session(V): {0:addrpad} ID: {1} Processes: {2}\n", session.obj_offset, session.SessionId, len(processes)) renderer.format( "PagedPoolStart: {0:addrpad} PagedPoolEnd {1:addrpad}\n", session.PagedPoolStart, session.PagedPoolEnd) for process in processes: renderer.format(" Process: {0} @ {1}\n", process, process.CreateTime) # Follow the undocumented _IMAGE_ENTRY_IN_SESSION list to find the # kernel modules loaded in this session. for image in session.ImageIterator: symbol = utils.FormattedAddress(self.session.address_resolver, image.ImageBase) renderer.format( " Image: {0:addrpad}, Address {1:addrpad}, Name: {2}\n", image.obj_offset, image.ImageBase, symbol)
def column_types(self): return dict(name="", mib="101.101.104", perms="RWL", handler=self.session.profile.Pointer(), symbol=utils.FormattedAddress( self.session.address_resolver, 0), value="")
def _render_x64_table(self, table, renderer): resolver = self.session.address_resolver for j, entry in enumerate(table): function_address = table.v() + (entry >> 4) renderer.table_row( j, function_address, utils.FormattedAddress(resolver, function_address))
def _render_x86_table(self, table): resolver = self.session.address_resolver for j, function_address in enumerate(table): yield dict(entry=j, target=function_address, symbol=utils.FormattedAddress(resolver, function_address))
def _render_x64_table(self, table): resolver = self.session.address_resolver for j, entry in enumerate(table): function_address = table.v() + (entry >> 4) yield dict(entry=j, target=function_address, symbol=utils.FormattedAddress(resolver, function_address))
def collect(self): cc = self.session.plugins.cc() with cc: for task in self.filter_processes(): # Resolve names in the process context. cc.SwitchProcessContext(process=task) for thread in task.ThreadListHead.list_of_type( "_ETHREAD", "ThreadListEntry"): yield (thread, thread.Cid.UniqueProcess, thread.Cid.UniqueThread, thread.StartAddress, utils.FormattedAddress( self.session.address_resolver, thread.StartAddress), task.ImageFileName, thread.Win32StartAddress, utils.FormattedAddress( self.session.address_resolver, thread.Win32StartAddress))
def collect_eat_hooks(self): for function_name, func_address in self.detect_EAT_hooks(): yield dict(Type="EAT", source_name=function_name, target_name=utils.FormattedAddress( self.session.address_resolver, func_address, max_count=1, hex_if_unknown=True), target_func=self.session.profile.Function(func_address))
def render(self, renderer): renderer.table_header([("Type", "type", "36"), ("Callback", "callback", "[addrpad]"), ("Symbol", "symbol", "50"), ("Details", "details", ""), ]) for (sym, cb, detail) in self.generate_hits(): symbol_name = utils.FormattedAddress( self.session.address_resolver, cb) renderer.table_row(sym, cb, symbol_name, detail)
def collect(self): with self.session.plugins.cc() as cc: for run in self.generate_memory_ranges(): scanner = PoolScanThreadFast( profile=self.profile, session=self.session, address_space=run.address_space) for pool_obj in scanner.scan(run.start, run.length): thread = pool_obj.GetObject("Thread").Body.cast("_ETHREAD") if not thread: continue if (thread.Cid.UniqueProcess.v() != 0 and thread.StartAddress == 0): continue try: # Check the Semaphore Type. if thread.Tcb.SuspendSemaphore.Header.Type != 0x05: continue if thread.KeyedWaitSemaphore.Header.Type != 0x05: continue except AttributeError: pass # Resolve the thread back to an owning process if possible. task = thread.Tcb.ApcState.Process.dereference_as( "_EPROCESS", vm=self.session.kernel_address_space) # Try to switch to the tasks address space in order to # resolve symbols. start_address = thread.Win32StartAddress.v() if start_address < self.session.GetParameter( "highest_usermode_address"): if task != self.session.GetParameter("process_context"): cc.SwitchProcessContext(task) else: cc.SwitchProcessContext() yield (thread.obj_offset, thread.Cid.UniqueProcess, thread.Cid.UniqueThread, thread.Win32StartAddress.v(), thread.CreateTime, thread.ExitTime, task.ImageFileName, utils.FormattedAddress( self.session.address_resolver, start_address))
def get_bugcheck_callbacks(self): resolver = self.session.address_resolver for list_head_name, type in [("nt!KeBugCheckCallbackListHead", "_KBUGCHECK_CALLBACK_RECORD"), ("nt!KeBugCheckReasonCallbackListHead", "_KBUGCHECK_REASON_CALLBACK_RECORD")]: list_head = resolver.get_constant_object(list_head_name, "_LIST_ENTRY") for record in list_head.list_of_type(type, "Entry"): function = record.CallbackRoutine yield (list_head_name, record, function, utils.FormattedAddress(resolver, function), record.Component)
def collect(self): for oid in self.CheckSysctl(): # Format the value nicely. value = oid.arg if isinstance(value, obj.Pointer): value = "@ 0x%X" % int(value) elif not value == None: try: value = int(value) value = "0x%X (%d)" % (value, value) except (ValueError, AttributeError): pass yield (oid.name, oid.number, oid.perms, oid.oidp.oid_handler, utils.FormattedAddress(self.session.address_resolver, oid.oidp.oid_handler), value)
def render(self, renderer): for driver_obj in self.generate_hits(): driver_name = driver_obj.DriverName.v(vm=self.kernel_address_space) # Continue if a regex was supplied and it doesn't match if self.plugin_args.regex: if not driver_name: continue # Continue if a regex was supplied and it doesn't match if not self.plugin_args.regex.search(driver_name): continue # Write the standard header for each driver object renderer.section() renderer.format("DriverName: {0}\n", driver_name) renderer.format("DriverStart: {0:addrpad}\n", driver_obj.DriverStart) renderer.format("DriverSize: {0:addrpad}\n", driver_obj.DriverSize) renderer.format("DriverStartIo: {0:addrpad}\n", driver_obj.DriverStartIo) renderer.table_header([('', "index", ">4"), ('Func Name', "function", "36"), ('Func Addr', "func_addres", '[addrpad]'), ('Module', "name", '')]) # Write the address and owner of each IRP function for i, function in enumerate(driver_obj.MajorFunction): # Make sure this is in the kernel address space. function = driver_obj.MajorFunction[i].dereference( vm=self.kernel_address_space) symbol = utils.FormattedAddress(self.session.address_resolver, function) renderer.table_row(i, function.obj_name, function.obj_offset, symbol) # For verbose we print a bit about the function # (e.g. disassembly if available.). if self.plugin_args.verbosity > 1: renderer.format("{0}\n\n", function)
def render(self, renderer): renderer.table_header([("Table", "", ">3"), ("Offset", "offset", "[addrpad]"), ("DueTime(H)", "due_high", "22"), ("DueTime", "due", "24"), ("Period(ms)", "period", ">11"), ("Signaled", "signaled", ">10"), ("Routine", "routine", "[addrpad]"), ("Module", "module", "")]) # Print kuser_shared things. kuser_shared = self.profile._KUSER_SHARED_DATA( self.profile.get_constant("KI_USER_SHARED_DATA")) interrupt_time = ((kuser_shared.InterruptTime.High1Time << 32) + kuser_shared.InterruptTime.LowPart) now = kuser_shared.SystemTime.as_windows_timestamp() - interrupt_time seen = set() for i, timer in self.timers(): if timer in seen: continue seen.add(timer) if timer.Header.SignalState.v(): signaled = "Yes" else: signaled = "-" renderer.table_row( i, timer, # Due time in InterruptTime (100ns). "0x%0.20x" % timer.DueTime.QuadPart, self.profile.WinFileTime(value=now + timer.DueTime.QuadPart, is_utc=True), timer.Period, signaled, timer.Dpc.DeferredRoutine, utils.FormattedAddress(self.session.address_resolver, timer.Dpc.DeferredRoutine))
def collect(self): invalid_address = self.session.address_resolver.get_constant_object( "nt!IopInvalidDeviceRequest", "Function").obj_offset for driver_obj in self.generate_hits(): driver_name = driver_obj.DriverName.v(vm=self.kernel_address_space) # Continue if a regex was supplied and it doesn't match if self.plugin_args.regex: if not driver_name: continue # Continue if a regex was supplied and it doesn't match if not self.plugin_args.regex.search(driver_name): continue driver_start = driver_obj.DriverStart.v() driver_end = driver_obj.DriverStart.v() + driver_obj.DriverSize interesting = False functions = [] # Write the address and owner of each IRP function for i, function in enumerate(driver_obj.MajorFunction): # Make sure this is in the kernel address space. function = driver_obj.MajorFunction[i].dereference( vm=self.kernel_address_space) func_addres = function.obj_offset if func_addres == None: continue symbol = utils.FormattedAddress(self.session.address_resolver, func_addres) # Suppress function pointers which point at the default invalid # address function. if (self.plugin_args.verbosity < 5 and func_addres == invalid_address): continue highlight = None # Functions residing within the driver are not suspicious. if not (driver_start <= func_addres <= driver_end): interesting = True # Extra important if we have no idea where it came from. if not self.session.address_resolver.format_address( func_addres): highlight = "important" functions.append( dict(driver=driver_obj, idx=i, function=function.obj_name, func_addres=func_addres, name=symbol, highlight=highlight)) # By default only show interesting drivers. if (self.plugin_args.verbosity < 2 and not interesting): continue # Write the standard header for each driver object divider = "DriverName: %s %#x-%#x" % (driver_name, driver_start, driver_end) yield dict(divider=divider) for x in functions: yield x