def generator(self, data): for task in data: pid = task.UniqueProcessId if task.Peb: for m in task.get_load_modules(): yield (0, [int(pid), Address(m.DllBase), Hex(m.SizeOfImage), Hex(m.LoadCount), str(m.FullDllName or '')]) else: yield (0, [int(pid), Address(0), Hex(0), Hex(0), "Error reading PEB for pid"])
def generator(data): for object_type in data: yield (0, [ Address(object_type.obj_offset), Hex(object_type.TotalNumberOfObjects), Hex(object_type.TotalNumberOfHandles), str(object_type.Key), str(object_type.Name or ''), str(object_type.TypeInfo.PoolType) ])
def update_proc_vad_info(self, proc_peb_info): """Builds a dictionary of process executable information from VAD""" self.proc_vad_info = {} for pid in proc_peb_info: self.proc_vad_info[pid] = [] proc = proc_peb_info[pid][0] if proc.Peb: # gets process information for the process executable from VAD and updates the dictionary for vad, addr_space in proc.get_vads( vad_filter=proc._mapped_file_filter): ext = "" vad_found = False if obj.Object("_IMAGE_DOS_HEADER", offset=vad.Start, vm=addr_space).e_magic != 0x5A4D: continue if str(vad.FileObject.FileName or ''): ext = os.path.splitext(str( vad.FileObject.FileName))[1].lower() if (ext == ".exe") or (vad.Start == proc.Peb.ImageBaseAddress): vad_filename = vad.FileObject.FileName vad_baseaddr = vad.Start vad_size = vad.End - vad.Start vad_protection = vadinfo.PROTECT_FLAGS.get( vad.VadFlags.Protection.v()) vad_tag = vad.Tag self.proc_vad_info[pid].extend([ str(vad_filename or ''), Address(vad_baseaddr), Hex(vad_size), str(vad_protection or ''), str(vad_tag or '') ]) vad_found = True break if vad_found == False: self.proc_vad_info[pid].extend( ["NA", Address(0), Hex(0), "NA", "NA"]) else: self.proc_vad_info[pid].extend( ["No VAD", Address(0), Hex(0), "No VAD", "No VAD"])
def generator(self, data): for process, module, hook in data: if not self._config.NO_WHITELIST: process_name = "" if process: process_name = str(process.ImageFileName) if self.whitelist(hook.hook_mode | hook.hook_type, process_name, hook.VictimModule, hook.HookModule, hook.Function): continue procname = "N/A" pid = -1 if process: procname = str(process.ImageFileName) pid = int(process.UniqueProcessId) for n, info in enumerate(hook.disassembled_hops): (address, data) = info yield (0, [str(hook.Mode), str(hook.Type), procname, pid, str(module.BaseDllName or '') or ntpath.basename(str(module.FullDllName or '')), Address(module.DllBase), Hex(module.DllBase + module.SizeOfImage), str(hook.Detail), Address(hook.hook_address), str(hook.HookModule), Address(address), Bytes(data)])
def generator(self, data): for atom_table in data: # This defeats the purpose of having a generator, but # its required if we want to be able to sort. We also # filter string atoms here. atoms = [a for a in atom_table.atoms() if a.is_string_atom()] if self._config.SORT_BY == "atom": attr = "Atom" elif self._config.SORT_BY == "refcount": attr = "ReferenceCount" else: attr = "obj_offset" for atom in sorted(atoms, key = lambda x: getattr(x, attr)): yield (0, [Address(atom_table.obj_offset), Address(atom.obj_offset), Hex(atom.Atom), int(atom.ReferenceCount), int(atom.Pinned), str(atom.Name or "")] )
def generator(self, data): for memory_offset, file_offset, length in data.get_runs(): yield ( 0, [Address(file_offset), Address(memory_offset), Hex(length)], )
def generator(data): for ldr_entry in data: yield (0, [Address(ldr_entry.obj_offset), str(ldr_entry.BaseDllName or ''), Address(ldr_entry.DllBase), Hex(ldr_entry.SizeOfImage), str(ldr_entry.FullDllName or '')])
def generator(self, data): seen = [] for window_station in data: for desktop in window_station.desktops(): offset = desktop.PhysicalAddress if offset in seen: continue seen.append(offset) name = "{0}\\{1}".format(desktop.WindowStation.Name, desktop.Name) for thrd in desktop.threads(): yield (0, [ Address(offset), name, Hex(desktop.rpdeskNext.v()), int(desktop.dwSessionId), Hex(desktop.pDeskInfo.v()), int(desktop.DeskInfo.fsHooks), Hex(desktop.DeskInfo.spwnd), int(len(list(desktop.windows( desktop.DeskInfo.spwnd)))), Hex(desktop.pheapDesktop.v()), Hex(desktop.DeskInfo.pvDesktopLimit - desktop.DeskInfo.pvDesktopBase), Hex(desktop.DeskInfo.pvDesktopBase), Hex(desktop.DeskInfo.pvDesktopLimit), int(thrd.pEThread.Cid.UniqueThread), str(thrd.ppi.Process.ImageFileName), int(thrd.ppi.Process.UniqueProcessId), int(thrd.ppi.Process.InheritedFromUniqueProcessId) ])
def update_proc_peb_info(self, psdata): self.proc_peb_info = {} # Builds a dictionary of process executable information from PEB for proc in psdata: pid = int(proc.UniqueProcessId) self.proc_peb_info[pid] = [ proc, pid, proc.ImageFileName, int(proc.InheritedFromUniqueProcessId), str(proc.CreateTime) ] if proc.Peb: # gets process information for the process executable from PEB and updates the dictionary mods = proc.get_load_modules() for mod in mods: ext = os.path.splitext(str(mod.FullDllName))[1].lower() if (ext == ".exe"): proc_cmd_line = proc.Peb.ProcessParameters.CommandLine proc_image_pathname = proc.Peb.ProcessParameters.ImagePathName proc_image_baseaddr = proc.Peb.ImageBaseAddress mod_baseaddr = mod.DllBase mod_size = mod.SizeOfImage mod_basename = mod.BaseDllName mod_fullname = mod.FullDllName break self.proc_peb_info[pid].extend([ str(proc_cmd_line), str(proc_image_pathname), Address(proc_image_baseaddr), Address(mod_baseaddr), Hex(mod_size), str(mod_basename), str(mod_fullname or "") ]) else: self.proc_peb_info[pid].extend([ "NoPEB", "NoPEB", Address(0), Address(0), Hex(0), "NoPEB", "NoPEB" ])
def generator(self, data): for n, entry, addr, module in data: if addr == 0: module_name = "NOT USED" sect_name = "" elif module: module_name = str(module.BaseDllName or "") sect_name = self.get_section_name(module, addr) else: module_name = "UNKNOWN" sect_name = "" # The parent is IDT. The grand-parent is _KPCR. cpu_number = entry.obj_parent.obj_parent.ProcessorBlock.Number yield (0, [Hex(cpu_number), Hex(n), Address(entry.Selector), Address(addr), str(module_name), str(sect_name)])
def generator(self, data): for module in data: if not self._config.PHYSICAL_OFFSET: offset = module.obj_offset else: offset = module.obj_vm.vtop(module.obj_offset) yield (0, [Address(offset), str(module.BaseDllName or ''), Address(module.DllBase), Hex(module.SizeOfImage), str(module.FullDllName or '')])
def generator(self, data): if self._config.OBJECT_TYPE: object_list = [s for s in self._config.OBJECT_TYPE.split(',')] else: object_list = [] for pid, handle, object_type, name in data: if object_list and object_type not in object_list: continue if self._config.SILENT: if len(name.replace("'", "")) == 0: continue if not self._config.PHYSICAL_OFFSET: offset = handle.Body.obj_offset else: offset = handle.obj_vm.vtop(handle.Body.obj_offset) yield (0, [ Address(offset), int(pid), Hex(handle.HandleValue), Hex(handle.GrantedAccess), str(object_type), str(name) ])
def generator(self, data): for atom_table, window_station in data: for atom in atom_table.atoms(): ## Filter string atoms if not atom.is_string_atom(): continue yield (0, [Address(atom_table.PhysicalAddress), int(window_station.dwSessionId), str(window_station.Name or ''), Hex(atom.Atom), int(atom.ReferenceCount), int(atom.HandleIndex), int(atom.Pinned), str(atom.Name or "")] )
def generator(self, data): for session, wndsta, clip, handle in data: # If no tagCLIP is provided, we do not know the format if not clip: fmt = obj.NoneObject("Format unknown") else: # Try to get the format name, but failing that, print # the format number in hex instead. if clip.fmt.v() in consts.CLIPBOARD_FORMAT_ENUM: fmt = str(clip.fmt) else: fmt = hex(clip.fmt.v()) # Try to get the handle from tagCLIP first, but # fall back to using _HANDLEENTRY.phead. Note: this can # be a value like DUMMY_TEXT_HANDLE (1) etc. if clip: handle_value = clip.hData else: handle_value = handle.phead.h clip_data = "" if handle: try: clip_data = ''.join( [chr(c) for c in handle.reference_object().abData]) except AttributeError: pass yield ( 0, [ int(session.SessionId), str(wndsta.Name), str(fmt), Hex(handle_value), Address(handle.phead.v()), Bytes(clip_data), ], )
def generator(self, tasks): for task in tasks: wnf_process_context = task.WnfContext.dereference_as('_WNF_PROCESS_CONTEXT') for subscriber in wnf_process_context.SubscriptionListHead.list_of_type("_WNF_SUBSCRIPTION_CONTEXT", "SubscriptionContexts"): # case of subscriber head if subscriber.Header.NodeTypeCode != 0x905: continue # sometimes reference a not in memory object (explorer.exe) # very strange... if subscriber.NameInstance.Header.NodeTypeCode != 0x903: clear = subscriber.WnfId ^ 0x41C64E6DA3BC0074 else: clear = subscriber.NameInstance.WnfId ^ 0x41C64E6DA3BC0074 if self._config.WNFID and int(self._config.wnfid, 16) != clear: continue if self._config.Scope and int(self._config.scope, 16) != subscriber.NameInstance.ScopeInstance.v(): continue yield (0, [ Address(subscriber.v()), task.UniqueProcessId.v(), str(task.ImageFileName), Address(subscriber.NameInstance), Hex(clear), int(clear & 0xf), int(clear >> 4 & 0x3), int(clear >> 6 & 0xf), int(clear >> 0xa & 0x1), Address(subscriber.NameInstance.ScopeInstance.get_scope_map_instance().v()), Address(subscriber.NameInstance.ScopeInstance), int(subscriber.NameInstance.ScopeInstance.Scope), str(bool(subscriber.NameInstance.WnfData)), int(subscriber.NameInstance.WnfData.DataSize) ])
def generator(self, data): # Determine which filters the user wants to see if self._config.FILTER: filters = set(self._config.FILTER.split(',')) else: filters = set() for thread, addr_space, mods, mod_addrs, \ instances, hooked_tables, system_range, owner_name in data: # If the user didn't set filters, display all results. If # the user set one or more filters, only show threads # with matching results. tags = set([t for t, v in instances.items() if v.check()]) if filters and not filters & tags: continue values = [] values.append(Address(thread.obj_offset)) values.append(int(thread.Cid.UniqueProcess)) values.append(int(thread.Cid.UniqueThread)) values.append(','.join(tags)) values.append(str(thread.CreateTime)) if thread.ExitTime > 0: values.append(str(thread.ExitTime)) else: values.append('') values.append(str(thread.owning_process().ImageFileName)) values.append(str(thread.attached_process().ImageFileName)) # Lookup the thread's state state = str(thread.Tcb.State) # Find the wait reason if state == 'Waiting': state_reason = str(thread.Tcb.WaitReason) else: state_reason = '' values.append(state) values.append(state_reason) values.append(int(thread.Tcb.BasePriority)) values.append(int(thread.Tcb.Priority)) values.append(Address(thread.Tcb.Teb)) values.append(Address(thread.StartAddress)) values.append(owner_name) # Check the flag which indicates whether Win32StartAddress is valid if thread.SameThreadApcFlags & 1: values.append(Address(thread.Win32StartAddress)) else: values.append(Address(-1)) values.append(Address(thread.Tcb.Win32Thread)) values.append(str(thread.CrossThreadFlags)) # Disasemble the start address if possible dis = '' process_space = thread.owning_process().get_process_address_space() if process_space.is_valid_address(thread.StartAddress): buf = process_space.zread(thread.StartAddress, 24) mode = "32bit" if self.bits32 else "64bit" dis += "\n".join(["{0:#x} {1:<16} {2}".format(o, h, i) for o, i, h in malfind.Disassemble(buf, thread.StartAddress.v(), mode)]) if self.bits32: # Print the registers if possible trapframe = thread.Tcb.TrapFrame.dereference_as("_KTRAP_FRAME") if trapframe: for r in trapframe.Eip, trapframe.Eax, trapframe.Ebx, \ trapframe.Ecx, trapframe.Edx, trapframe.Esi, \ trapframe.Edi, trapframe.HardwareEsp, \ trapframe.Ebp, trapframe.ErrCode, trapframe.SegCs, \ trapframe.HardwareSegSs, trapframe.SegDs, \ trapframe.SegEs, trapframe.SegGs, trapframe.SegFs, \ trapframe.EFlags, trapframe.Dr0, trapframe.Dr1, \ trapframe.Dr2, trapframe.Dr3, trapframe.Dr6, \ trapframe.Dr7 : values.append(Hex(r)) else: values.extend( [Hex(-1)] * 23 ) values.append(Address(thread.Tcb.ServiceTable)) ssdt_obj = obj.Object("_SERVICE_DESCRIPTOR_TABLE", offset = thread.Tcb.ServiceTable, vm = addr_space ) if ssdt_obj != None: for i, desc in enumerate(ssdt_obj.Descriptors): if desc.is_valid(): service_table = Address(desc.KiServiceTable.v()) else: service_table = Address(-1) # Show exactly which functions are hooked table = desc.KiServiceTable.v() if table not in hooked_tables.keys(): yield (0, values + [i, service_table, -1, '', Address(-1), '', dis]) continue yielded=False for (j, func_name, func_addr, mod_name) in hooked_tables[table]: yielded=True yield(0, values + [i, service_table, j, func_name, Address(func_addr), mod_name, dis]) if not yielded: yield (0, values + [i, service_table, -1, '', Address(-1), '', dis]) else: values.extend([ -1, Address(-1), -1, '', Address(-1), '', dis ]) yield (0, values) else: # registers values.extend( [Hex(-1)] * 23 ) # ssdt values.extend([ Address(-1), -1, Address(-1), -1, '', Address(-1), '', dis ]) yield (0, values)
def create_ps_node(task): proc = { 'pid': int(task.UniqueProcessId), 'ppid': int(task.InheritedFromUniqueProcessId), 'name': str(task.ImageFileName), 'ctime': str(task.CreateTime), 'proc': task, 'children': [] } peb = { 'cmdline': None, 'image_baseaddr': Address(0), 'baseaddr': Address(0), 'size': Hex(0), 'basename': None, 'fullname': None } vad = { 'filename': '<No VAD>', 'baseaddr': Address(0), 'size': Hex(0), 'protection': '<No VAD>', 'tag': '<No VAD>' } if task.Peb: peb['cmdline'] = task.Peb.ProcessParameters.CommandLine mods = task.get_load_modules() for mod in mods: ext = os.path.splitext(str(mod.FullDllName))[1].lower() if ext == '.exe': peb['image_baseaddr'] = Address(task.Peb.ImageBaseAddress) peb['baseaddr'] = Address(mod.DllBase) peb['size'] = Hex(0) peb['basename'] = str(mod.BaseDllName) peb['fullname'] = str(mod.FullDllName) break vads = task.get_vads(vad_filter=task._mapped_file_filter) for entry, addr_space in vads: ext = "" vad_found = False if obj.Object("_IMAGE_DOS_HEADER", offset=entry.Start, vm=addr_space).e_magic != 0x5A4D: continue if str(entry.FileObject.FileName or ''): ext = os.path.splitext(str(entry.FileObject.FileName))[1] ext = ext.lower() tmp_peb_iba = task.Peb.ImageBaseAddress if (ext == ".exe") or (entry.Start == tmp_peb_iba): vad['filename'] = str(entry.FileObject.FileName) vad['baseaddr'] = Address(entry.Start) vad['size'] = Hex(entry.End - entry.Start) tmp_vad_fp = entry.VadFlags.Protection.v() tmp_vad_fp = vadinfo.PROTECT_FLAGS.get(tmp_vad_fp) vad['protection'] = str(tmp_vad_fp or '') vad['tag'] = str(entry.Tag or '') vad_found = True break if not vad_found: vad['filename'] = 'NA' vad['protection'] = 'NA' vad['tag'] = 'NA' proc['peb'] = peb proc['vad'] = vad return proc
def generator(self, data): if self._config.DISOFFSET: dis = self._config.DISOFFSET for offset, PARTITION_TABLE, boot_code in data: entry1 = PARTITION_TABLE.Entry1.dereference_as('PARTITION_ENTRY') entry2 = PARTITION_TABLE.Entry2.dereference_as('PARTITION_ENTRY') entry3 = PARTITION_TABLE.Entry3.dereference_as('PARTITION_ENTRY') entry4 = PARTITION_TABLE.Entry4.dereference_as('PARTITION_ENTRY') have_bootable = entry1.is_bootable_and_used( ) or entry2.is_bootable_and_used() or entry3.is_bootable_and_used( ) or entry4.is_bootable_and_used() if not self._config.NOCHECK and not have_bootable: # it doesn't really make sense to have a partition that is bootable, but empty or invalid # but we only skip MBRs with these types of partitions if we are checking continue distance = 0 h = hashlib.md5() f = hashlib.md5() h.update(self.code_data) f.update(boot_code) if self._config.HASH: hash = "{0}".format(h.hexdigest()) if hash.lower() != self._config.HASH.lower(): continue elif self._config.FULLHASH: hash = "{0}".format(f.hexdigest()) if hash.lower() != self._config.FULLHASH.lower(): continue if self.disk_mbr: distance = self.levenshtein( self._get_instructions(self.disk_mbr), self._get_instructions(boot_code)) if self._config.MAXDISTANCE != None and distance > self._config.MAXDISTANCE: continue disksig = "{0:02x}-{1:02x}-{2:02x}-{3:02x}".format( PARTITION_TABLE.DiskSignature[0], PARTITION_TABLE.DiskSignature[1], PARTITION_TABLE.DiskSignature[2], PARTITION_TABLE.DiskSignature[3]) yield (0, [ Address(offset), disksig, str(h.hexdigest()), str(f.hexdigest()), int(distance), "{0:#x} {1}".format( entry1.get_value(entry1.BootableFlag), "(Bootable)" if entry1.is_bootable() else ""), "{0:#x} ({1})".format(entry1.get_value(entry1.PartitionType), entry1.get_type()), Hex(entry1.StartingLBA), "Cylinder: {0} Head: {1} Sector: {2}".format( entry1.StartingCylinder(), entry1.StartingCHS[0], entry1.StartingSector()), "Cylinder: {0} Head: {1} Sector: {2}".format( entry1.EndingCylinder(), entry1.EndingCHS[0], entry1.EndingSector()), Hex(entry1.SizeInSectors), "{0:#x} {1}".format( entry2.get_value(entry2.BootableFlag), "(Bootable)" if entry2.is_bootable() else ""), "{0:#x} ({1})".format(entry2.get_value(entry2.PartitionType), entry2.get_type()), Hex(entry2.StartingLBA), "Cylinder: {0} Head: {1} Sector: {2}".format( entry2.StartingCylinder(), entry2.StartingCHS[0], entry2.StartingSector()), "Cylinder: {0} Head: {1} Sector: {2}".format( entry2.EndingCylinder(), entry2.EndingCHS[0], entry2.EndingSector()), Hex(entry2.SizeInSectors), "{0:#x} {1}".format( entry3.get_value(entry3.BootableFlag), "(Bootable)" if entry3.is_bootable() else ""), "{0:#x} ({1})".format(entry3.get_value(entry3.PartitionType), entry3.get_type()), Hex(entry3.StartingLBA), "Cylinder: {0} Head: {1} Sector: {2}".format( entry3.StartingCylinder(), entry3.StartingCHS[0], entry3.StartingSector()), "Cylinder: {0} Head: {1} Sector: {2}".format( entry3.EndingCylinder(), entry3.EndingCHS[0], entry3.EndingSector()), Hex(entry3.SizeInSectors), "{0:#x} {1}".format( entry4.get_value(entry4.BootableFlag), "(Bootable)" if entry4.is_bootable() else ""), "{0:#x} ({1})".format(entry4.get_value(entry4.PartitionType), entry4.get_type()), Hex(entry4.StartingLBA), "Cylinder: {0} Head: {1} Sector: {2}".format( entry4.StartingCylinder(), entry4.StartingCHS[0], entry4.StartingSector()), "Cylinder: {0} Head: {1} Sector: {2}".format( entry4.EndingCylinder(), entry4.EndingCHS[0], entry4.EndingSector()), Hex(entry4.SizeInSectors), Bytes(boot_code) ])