def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype = 'physical') ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanSymlink().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm = address_space, offset = offset) ## We work out the object from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() link_obj = obj.Object("_OBJECT_SYMBOLIC_LINK", vm = address_space, offset = (offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_OBJECT_SYMBOLIC_LINK", pool_alignment)), native_vm = kernel_as) ## The _OBJECT_HEADER is immediately below the _OBJECT_SYMBOLIC_LINK object_obj = obj.Object( "_OBJECT_HEADER", vm = address_space, offset = link_obj.obj_offset - address_space.profile.get_obj_offset('_OBJECT_HEADER', 'Body'), native_vm = kernel_as ) if object_obj.get_object_type() != "SymbolicLink": continue yield object_obj, link_obj
def calculate(self): flat_space = utils.load_as(self._config, astype = 'physical') kernel_space = utils.load_as(self._config) # Scan for window station objects for offset in PoolScanWind().scan(flat_space): window_station = obj.Object("tagWINDOWSTATION", offset = offset, vm = flat_space) # Basic sanity checks are included here if not window_station.is_valid(): continue # Find an address space for this window station's session session = self.find_session_space( kernel_space, window_station.dwSessionId) if not session: continue # Reset the object's native VM so pointers are # dereferenced in session space window_station.set_native_vm(session.obj_vm) for winsta in window_station.traverse(): if winsta.is_valid(): yield winsta
def calculate(self): # Virtual kernel space for dereferencing pointers kernel_space = utils.load_as(self._config) # Physical space for scanning flat_space = utils.load_as(self._config, astype = 'physical') if not self.is_valid_profile(kernel_space.profile): debug.error("This command does not support the selected profile.") # Scan for TCP listeners also known as sockets for offset in PoolScanTcpListener().scan(flat_space): tcpentry = obj.Object('_TCP_LISTENER', offset = offset, vm = flat_space, native_vm = kernel_space) # Only accept IPv4 or IPv6 if tcpentry.AddressFamily not in (AF_INET, AF_INET6): continue # For TcpL, the state is always listening and the remote port is zero for ver, laddr, raddr in tcpentry.dual_stack_sockets(): yield tcpentry, "TCP" + ver, laddr, tcpentry.Port, raddr, 0, "LISTENING" # Scan for TCP endpoints also known as connections for offset in PoolScanTcpEndpoint().scan(flat_space): tcpentry = obj.Object('_TCP_ENDPOINT', offset = offset, vm = flat_space, native_vm = kernel_space) if tcpentry.AddressFamily == AF_INET: proto = "TCPv4" elif tcpentry.AddressFamily == AF_INET6: proto = "TCPv6" else: continue # These are our sanity checks if (tcpentry.State.v() not in tcpip_vtypes.TCP_STATE_ENUM or (not tcpentry.LocalAddress and (not tcpentry.Owner or tcpentry.Owner.UniqueProcessId == 0 or tcpentry.Owner.UniqueProcessId > 65535))): continue yield tcpentry, proto, tcpentry.LocalAddress, tcpentry.LocalPort, \ tcpentry.RemoteAddress, tcpentry.RemotePort, tcpentry.State # Scan for UDP endpoints for offset in PoolScanUdpEndpoint().scan(flat_space): udpentry = obj.Object('_UDP_ENDPOINT', offset = offset, vm = flat_space, native_vm = kernel_space) # Only accept IPv4 or IPv6 if udpentry.AddressFamily not in (AF_INET, AF_INET6): continue # For UdpA, the state is always blank and the remote end is asterisks for ver, laddr, _ in udpentry.dual_stack_sockets(): yield udpentry, "UDP" + ver, laddr, udpentry.Port, "*", "*", ""
def calculate(self): self.kernel_address_space = utils.load_as(self._config) self.flat_address_space = utils.load_as(self._config, astype = 'physical') if not(bool(self._config.DIR)): debug.error("--dir needs to be present") if not(bool(self._config.pid) ^ bool(self._config.eproc) ^ bool(self._config.fobj) ^ bool(self._config.pool)): if not(bool(self._config.pid) or bool(self._config.eproc) or bool(self._config.fobj) or bool(self._config.pool)): debug.error("exactly *ONE* of the options --pid, --eproc, --fobj or --pool must be specified (you have not specified _any_ of these options)") else: debug.error("exactly *ONE* of the options --pid, --eproc, --fobj or --pool must be specified (you have used _multiple_ such options)") if bool(self._config.pid): # --pid eproc_matches = [ eproc for eproc in tasks.pslist(self.kernel_address_space) if eproc.UniqueProcessId == self._config.pid ] if len(eproc_matches) != 1: debug.error("--pid needs to take a *VALID* PID argument (could not find PID {0} in the process listing for this memory image)".format(self._config.pid)) return self.dump_from_eproc(eproc_matches[0]) elif bool(self._config.eproc): # --eproc return self.dump_from_eproc(obj.Object("_EPROCESS", offset = self._config.eproc, vm = self.kernel_address_space)) elif bool(self._config.fobj): # --fobj try: file_object = obj.Object("_FILE_OBJECT", offset = self._config.fobj, vm = self.flat_address_space) if bool(self._config.reconstruct): # --reconstruct return [ (file_object, self.parse_string(file_object.FileName)) ] else: return filter(None, [ self.dump_file_object(file_object) ]) except ExportException as exn: debug.error(exn) else: # --pool return self.dump_from_pool()
def calculate(self): eproc = {} found = {} cmdline = {} pathname = {} # Brute force search for eproc blocks in pool memory address_space = utils.load_as(self._config) for eprocess in filescan.PSScan(self._config).calculate(): eproc[eprocess.obj_offset] = eprocess found[eprocess.obj_offset] = 1 # Walking the active process list. # Remove any tasks we find here from the brute force search if the --short option is set. # Anything left is something which was hidden/terminated/of interest. address_space = utils.load_as(self._config) for task in tasks.pslist(address_space): phys = address_space.vtop(task.obj_offset) if phys in eproc: if self._config.SHORT : del eproc[phys] del found[phys] else: found[phys] = 0 # Grab command line and parameters peb = task.Peb if peb: cmdline[phys] = peb.ProcessParameters.CommandLine pathname[phys] = peb.ProcessParameters.ImagePathName ret = [eproc, found, cmdline, pathname] return ret
def calculate(self): vspace = utils.load_as(self._config) pspace = utils.load_as(self._config, astype = 'physical') for offset in PoolScanTcpListener().scan(pspace): tcpentry = obj.Object('_TCP_LISTENER', offset, pspace) lport = socket.ntohs(tcpentry.Port) # For TcpL, the state is always listening and the remote port is zero state = "LISTENING" rport = 0 for ver, laddr, raddr, owner in self.enumerate_listeners(tcpentry, vspace): yield tcpentry.obj_offset, "TCP" + ver, laddr, lport, \ raddr, rport, state, owner, tcpentry.CreateTime for offset in PoolScanTcpEndpoint().scan(pspace): tcpentry = obj.Object('_TCP_ENDPOINT', offset, pspace) AddrInfo = obj.Object('_ADDRINFO', tcpentry.AddrInfo, vspace) InetAF = obj.Object('_INETAF', tcpentry.InetAF, vspace) Owner = obj.Object('_EPROCESS', tcpentry.Owner, vspace) lport = socket.ntohs(tcpentry.LocalPort) rport = socket.ntohs(tcpentry.RemotePort) try: state = tcp_states[tcpentry.State + 1] except IndexError: state = hex(tcpentry.State) l_inaddr = AddrInfo.Local.pData.dereference().dereference().v() r_inaddr = AddrInfo.Remote.dereference().v() if InetAF.AddressFamily == AF_INET: proto = "TCPv4" laddr = inet_ntop(socket.AF_INET, vspace.zread(l_inaddr, 4)) raddr = inet_ntop(socket.AF_INET, vspace.zread(r_inaddr, 4)) elif InetAF.AddressFamily == AF_INET6: proto = "TCPv6" laddr = inet_ntop(socket.AF_INET6, vspace.zread(l_inaddr, 16)) raddr = inet_ntop(socket.AF_INET6, vspace.zread(r_inaddr, 16)) else: continue yield tcpentry.obj_offset, proto, laddr, lport, raddr, \ rport, state, Owner, tcpentry.CreateTime for offset in PoolScanUdpEndpoint().scan(pspace): udpentry = obj.Object('_UDP_ENDPOINT', offset, pspace) lport = socket.ntohs(udpentry.Port) # For UdpA, the state is always blank and the remote end is asterisks state = "" raddr = rport = "*" for ver, laddr, _, owner in self.enumerate_listeners(udpentry, vspace): yield udpentry.obj_offset, "UDP" + ver, laddr, lport, \ raddr, rport, state, owner, udpentry.CreateTime
def calculate(self): """Determines the address space""" profilelist = [ p.__name__ for p in registry.get_plugin_classes(obj.Profile).values() ] encrypted_kdbg_profiles = [] proflens = {} maxlen = 0 origprofile = self._config.PROFILE for p in profilelist: self._config.update('PROFILE', p) buf = addrspace.BufferAddressSpace(self._config) if buf.profile.metadata.get('os', 'unknown') == 'windows': proflens[p] = str(obj.VolMagic(buf).KDBGHeader) maxlen = max(maxlen, len(proflens[p])) if (buf.profile.metadata.get('memory_model', '64bit') == '64bit' and (buf.profile.metadata.get('major', 0), buf.profile.metadata.get('minor', 0)) >= (6, 2)): encrypted_kdbg_profiles.append(p) self._config.update('PROFILE', origprofile) # keep track of the number of potential KDBGs we find count = 0 if origprofile not in encrypted_kdbg_profiles: scanner = KDBGScanner(needles = proflens.values()) aspace = utils.load_as(self._config, astype = 'any') suspects = [] for offset in scanner.scan(aspace): val = aspace.read(offset, maxlen + 0x10) for l in proflens: if val.find(proflens[l]) >= 0: kdbg = obj.Object("_KDDEBUGGER_DATA64", offset = offset, vm = aspace) suspects.append((l, kdbg)) count += 1 for p, k in suspects: if not self._config.FORCE: yield p, k continue self._config.update("PROFILE", p) nspace = utils.load_as(self._config, astype = "any") for offset in scanner.scan(nspace): val = nspace.read(offset, maxlen + 0x10) if val.find(proflens[p]) >= 0: kdbg = obj.Object("_KDDEBUGGER_DATA64", offset = offset, vm = nspace) yield p, kdbg self._config.update('PROFILE', origprofile) # only perform the special win8/2012 scan if we didn't find # any others and if a virtual x64 address space is available if count == 0: if origprofile in encrypted_kdbg_profiles: encrypted_kdbg_profiles = [origprofile] for profile in encrypted_kdbg_profiles: self._config.update('PROFILE', profile) aspace = utils.load_as(self._config, astype = 'any') if hasattr(aspace, 'vtop'): for kdbg in obj.VolMagic(aspace).KDBG.generate_suggestions(): yield profile, kdbg
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype="physical") kernel_as = utils.load_as(self._config) for offset in PoolScanProcess().scan(address_space): eprocess = obj.Object("_EPROCESS", vm=address_space, native_vm=kernel_as, offset=offset) yield eprocess
def calculate(self): ## Here we scan the physical address space address_space = utils.load_as(self._config, astype = 'physical') kernel_as = utils.load_as(self._config) scanner = PoolScanThreadFast() for found in scanner.scan(address_space): thread = obj.Object('_ETHREAD', vm = address_space, native_vm = kernel_as, offset = found) yield thread
def virtual_process_from_physical_offset(self, offset): pspace = utils.load_as(self._config, astype = 'physical') vspace = utils.load_as(self._config) task = obj.Object("task_struct", vm = pspace, offset = offset) parent = obj.Object("task_struct", vm = vspace, offset = task.parent) for child in parent.children.list_of_type("task_struct", "sibling"): if child.obj_vm.vtop(child.obj_offset) == task.obj_offset: return child return obj.NoneObject("Unable to bounce back from task_struct->parent->task_struct")
def calculate(self): ## Here we scan the physical address space address_space = utils.load_as(self._config, astype = 'physical') ## We need the kernel_address_space later kernel_as = utils.load_as(self._config) scanner = PoolScanModuleFast() for offset in scanner.scan(address_space): ldr_entry = obj.Object('_LDR_DATA_TABLE_ENTRY', vm = address_space, offset = offset, native_vm = kernel_as) yield ldr_entry
def calculate(self): # start with a physical space so we can find processes without a DTB addr_space = utils.load_as(self._config, astype = 'physical') meta = addr_space.profile.metadata win10 = (meta.get("major"), meta.get("minor")) == (6, 4) # if the user selected virtual space or if we're on win10, switch # to a virtual kernel space if self._config.VIRTUAL or win10: addr_space = utils.load_as(self._config) return self.scan_results(addr_space)
def __config(self): """Creates a volatility configuration.""" if self.config != None and self.addr_space != None: return self.config self.config = conf.ConfObject() self.config.optparser.set_conflict_handler("resolve") registry.register_global_options(self.config, commands.Command) base_conf = { "profile": "WinXPSP2x86", "use_old_as": None, "kdbg": None, "help": False, "kpcr": None, "tz": None, "pid": None, "output_file": None, "physical_offset": None, "conf_file": None, "dtb": None, "output": None, "info": None, "location": "file://" + self.memdump, "plugins": None, "debug": None, "cache_dtb": True, "filename": None, "cache_directory": None, "verbose": None, "write": False } if self.osprofile: base_conf["profile"] = self.osprofile for key, value in base_conf.items(): self.config.update(key, value) # Deal with Volatility support for KVM/qemu memory dump. # See: #464. try: self.addr_space = utils.load_as(self.config) except exc.AddrSpaceError as e: if self._get_dtb(): self.addr_space = utils.load_as(self.config) else: raise self.plugins = registry.get_plugin_classes(commands.Command, lower=True) return self.config
def calculate(self): # All scanners will share a kernel and physical space self.kern_space = utils.load_as(self._config) self.phys_space = utils.load_as(self._config, astype = 'physical') # We currently dont support x64 if not self.is_valid_profile(self.kern_space.profile): debug.error("This command does not support the selected profile.") # Get the OS version we're analyzing version = (self.kern_space.profile.metadata.get('major', 0), self.kern_space.profile.metadata.get('minor', 0)) modlist = list(modules.lsmod(self.kern_space)) mods = dict((self.kern_space.address_mask(mod.DllBase), mod) for mod in modlist) mod_addrs = sorted(mods.keys()) # First few routines are valid on all OS versions for info in self.get_fs_callbacks(): yield info, mods, mod_addrs for info in self.get_bugcheck_callbacks(): yield info, mods, mod_addrs for info in self.get_shutdown_callbacks(): yield info, mods, mod_addrs for info in self.get_generic_callbacks(): yield info, mods, mod_addrs for info in self.get_bugcheck_reason_callbacks(modlist[0]): yield info, mods, mod_addrs for info in self.get_kernel_callbacks(modlist[0]): yield info, mods, mod_addrs # Valid for Vista and later if version >= (6, 0): for info in self.get_dbgprint_callbacks(): yield info, mods, mod_addrs for info in self.get_registry_callbacks(): yield info, mods, mod_addrs for info in self.get_pnp_callbacks(): yield info, mods, mod_addrs # Valid for XP if version == (5, 1): for info in self.get_registry_callbacks_legacy(modlist[0]): yield info, mods, mod_addrs
def doProcessors(config): ''' Retrieve IDT data. ''' physical_address_space = utils.load_as(config) kernel_address_space = utils.load_as(config,astype='kernel') processors_obj = datastruct.rootType() proc_num = 0 for kpcr in FindKPCR(physical_address_space): processor_obj = processors_obj.Processor.add() processor_obj.ID = proc_num proc_num += 1 IdtBase = kpcr.IdtBase IDTs = obj.Array(None,physical_address_space.address_mask(IdtBase.v()),physical_address_space,count=256,target=IdtBase.target) for idt in IDTs: entry_obj = processor_obj.InterruptDescriptorTable.IDTEntry.add() iswin32 = not idt.m('OffsetMiddle') if iswin32: idttype = idt.Access & 0x1f if idt.Access >= 256 or (idt.Access & 0x80) != 0x80: entry_obj.InvalidGate = '' elif idttype==0x5: entry_obj.TaskGate = '' elif idttype==0x6 or idttype==0xe: entry_obj.InterruptGate = '' elif idttype==0x7 or idttype==0xf: entry_obj.TrapGate = '' else: entry_obj.InvalidGate = '' entry_obj.Address = (idt.ExtendedOffset << 16) | idt.Offset entry_obj.Attributes = idt.Access else: idttype = idt.Type if idt.Reserved0!=0 or idt.Reserved1!=0 or idt.Present==0: entry_obj.InvalidGate = '' elif idttype==0x5: entry_obj.TaskGate = '' elif idttype==0xe: entry_obj.InterruptGate = '' elif idttype==0xf: entry_obj.TrapGate = '' else: entry_obj.InvalidGate = '' entry_obj.Address = ((idt.OffsetHigh & 0xffffffff) << 32) | ((idt.OffsetMiddle & 0xffff) << 16) | (idt.OffsetLow & 0xffff) entry_obj.Attributes = (idt.IstIndex << 13) | (idt.Type << 3) | (idt.Dpl<<1) | idt.Present entry_obj.Selector = idt.Selector.v() module = find_module(config,entry_obj.Address) if module: entry_obj.Module = module.FullDllName.v() return processors_obj
def calculate(self): ## Just grab the AS and scan it using our scanner address_space = utils.load_as(self._config, astype="physical") ## Will need the kernel AS for later: kernel_as = utils.load_as(self._config) for offset in PoolScanDriver().scan(address_space): pool_obj = obj.Object("_POOL_HEADER", vm=address_space, offset=offset) ## We work out the _DRIVER_OBJECT from the end of the ## allocation (bottom up). pool_alignment = obj.VolMagic(address_space).PoolAlignment.v() extension_obj = obj.Object( "_DRIVER_EXTENSION", vm=address_space, offset=( offset + pool_obj.BlockSize * pool_alignment - common.pool_align(kernel_as, "_DRIVER_EXTENSION", pool_alignment) ), native_vm=kernel_as, ) ## The _DRIVER_OBJECT is immediately below the _DRIVER_EXTENSION driver_obj = obj.Object( "_DRIVER_OBJECT", vm=address_space, offset=extension_obj.obj_offset - common.pool_align(kernel_as, "_DRIVER_OBJECT", pool_alignment), native_vm=kernel_as, ) ## The _OBJECT_HEADER is immediately below the _DRIVER_OBJECT object_obj = obj.Object( "_OBJECT_HEADER", vm=address_space, offset=driver_obj.obj_offset - address_space.profile.get_obj_offset("_OBJECT_HEADER", "Body"), native_vm=kernel_as, ) ## Skip unallocated objects # if object_obj.Type == 0xbad0b0b0: # continue if object_obj.get_object_type() != "Driver": continue yield (object_obj, driver_obj, extension_obj)
def calculate(self): flat_space = utils.load_as(self._config, astype = 'physical') kernel_space = utils.load_as(self._config) # Scan for atom tables for offset in PoolScanAtom().scan(flat_space): # There's no way to tell which session or window station # owns an atom table by *just* looking at the atom table, # so we have to instantiate it from the default kernel AS. atom_table = obj.Object('_RTL_ATOM_TABLE', offset = offset, vm = flat_space, native_vm = kernel_space) if atom_table.is_valid(): yield atom_table
def calculate(self): addr_space = utils.load_as(self._config) if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") for objct in self.scan_results(addr_space): if isinstance(objct, _UDP_ENDPOINT): # For UdpA, the state is always blank and the remote end is asterisks for ver, laddr, _ in objct.dual_stack_sockets(): yield objct, "UDP" + ver, laddr, objct.Port, "*", "*", "" elif isinstance(objct, _TCP_ENDPOINT): if objct.AddressFamily == AF_INET: proto = "TCPv4" elif objct.AddressFamily == AF_INET6: proto = "TCPv6" yield objct, proto, objct.LocalAddress, objct.LocalPort, \ objct.RemoteAddress, objct.RemotePort, objct.State elif isinstance(objct, _TCP_LISTENER): # For TcpL, the state is always listening and the remote port is zero for ver, laddr, raddr in objct.dual_stack_sockets(): yield objct, "TCP" + ver, laddr, objct.Port, raddr, 0, "LISTENING"
def calculate(self): addr_space = utils.load_as(self._config) win7 = addr_space.profile.metadata.get('major', 0) == 6 and addr_space.profile.metadata.get('minor', 0) == 1 if not self._config.HIVE_OFFSET: hive_offsets = [(self.hive_name(h), h.obj_offset) for h in hivelist.HiveList.calculate(self)] else: hive_offsets = [("User Specified", self._config.HIVE_OFFSET)] for name, hoff in set(hive_offsets): h = hivemod.HiveAddressSpace(addr_space, self._config, hoff) root = rawreg.get_root(h) if not root: if self._config.HIVE_OFFSET: debug.error("Unable to find root key. Is the hive offset correct?") else: skey = "software\\microsoft\\windows\\currentversion\\explorer\\userassist\\" if win7: uakey = skey + "{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\\Count" yield win7, name, rawreg.open_key(root, uakey.split('\\')) uakey = skey + "{F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}\\Count" yield win7, name, rawreg.open_key(root, uakey.split('\\')) else: uakey = skey + "{75048700-EF1F-11D0-9888-006097DEACF9}\\Count" yield win7, name, rawreg.open_key(root, uakey.split('\\')) uakey = skey + "{5E6AB780-7743-11CF-A12B-00AA004AE837}\\Count" yield win7, name, rawreg.open_key(root, uakey.split('\\'))
def calculate(self): addr_space = utils.load_as(self._config) if not self.is_valid_profile(addr_space.profile): debug.error("This plugin only works on XP and 2003") ## When verbose is specified, we recalculate the list of SIDs for ## services in the registry. Otherwise, we take the list from the ## pre-populated dictionary in getservicesids.py if self._config.VERBOSE: ssids = getservicesids.GetServiceSids(self._config).calculate() for sid, service in ssids: self.extrasids[sid] = " (Service: " + service + ")" else: for sid, service in getservicesids.servicesids.items(): self.extrasids[sid] = " (Service: " + service + ")" ## Get the user's SIDs from the registry self.load_user_sids() for proc in tasks.pslist(addr_space): if str(proc.ImageFileName).lower() == "services.exe": for vad, process_space in proc.get_vads(vad_filter = proc._mapped_file_filter): if vad.FileObject.FileName: name = str(vad.FileObject.FileName).lower() if name.endswith(".evt"): ## Maybe check the length is reasonable, though probably there won't ## ever be event logs that are multiple GB or TB in size. data = process_space.zread(vad.Start, vad.Length) yield name, data
def calculate(self): """Calculate and carry out any processing that may take time upon the image""" # Load the address space addr_space = utils.load_as(self._config) # Call a subfunction so that it can be used by other plugins return self.get_image_time(addr_space)
def virtual_process_from_physical_offset(addr_space, offset): """ Returns a virtual process from a physical offset in memory """ # Since this is a physical offset, we find the process flat_addr_space = utils.load_as(addr_space.get_config(), astype = 'physical') flateproc = obj.Object("_EPROCESS", offset, flat_addr_space) # then use the virtual address of its first thread to get into virtual land # (Note: the addr_space and flat_addr_space use the same config, so should have the same profile) tleoffset = addr_space.profile.get_obj_offset("_ETHREAD", "ThreadListEntry") # start out with the member offset given to us from the profile offsets = [tleoffset] # if (and only if) we're dealing with 64-bit Windows 7 SP1 # then add the other commonly seen member offset to the list meta = addr_space.profile.metadata major = meta.get("major", 0) minor = meta.get("minor", 0) build = meta.get("build", 0) version = (major, minor, build) if meta.get("memory_model") == "64bit" and version == (6, 1, 7601): offsets.append(tleoffset + 8) ## use the member offset from the profile for ofs in offsets: ethread = obj.Object("_ETHREAD", offset = flateproc.ThreadListHead.Flink.v() - ofs, vm = addr_space) # and ask for the thread's process to get an _EPROCESS with a virtual address space virtual_process = ethread.owning_process() # Sanity check the bounce. See Issue 154. if virtual_process and offset == addr_space.vtop(virtual_process.obj_offset): return virtual_process return obj.NoneObject("Unable to bounce back from virtual _ETHREAD to virtual _EPROCESS")
def calculate(self): addr_space = utils.load_as(self._config) if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") return win32.network.determine_sockets(addr_space)
def render_text(self, outfd, data): profile = utils.load_as(self._config).profile # Get the OS version being analyzed version = (profile.metadata.get('major', 0), profile.metadata.get('minor', 0)) # Choose which USER handle enum to use if version >= (6, 1): handle_types = consts.HANDLE_TYPE_ENUM_SEVEN else: handle_types = consts.HANDLE_TYPE_ENUM self.table_header(outfd, [("Session", "8"), ("Type", "20"), ("Tag", "8"), ("fnDestroy", "[addrpad]"), ("Flags", ""), ]) for session in data: gahti = session.find_gahti() if gahti: for i, h in list(handle_types.items()): self.table_row(outfd, session.SessionId, h, gahti.types[i].dwAllocTag, gahti.types[i].fnDestroy, gahti.types[i].bObjectCreateFlags)
def calculate(self): """Calculates the physical to virtual address mapping""" if self._config.STRING_FILE is None or not os.path.exists(self._config.STRING_FILE): debug.error("Strings file not found") addr_space = utils.load_as(self._config) if self._config.OFFSET != None: tasks = [self.virtual_process_from_physical_offset(addr_space, self._config.OFFSET)] elif self._config.SCAN: procs = list(filescan.PSScan(self._config).calculate()) tasks = [] for task in procs: tasks.append(self.virtual_process_from_physical_offset(addr_space, task.obj_offset)) else: tasks = win32.tasks.pslist(addr_space) try: if self._config.PIDS is not None: pidlist = [int(p) for p in self._config.PIDS.split(',')] tasks = [t for t in tasks if int(t.UniqueProcessId) in pidlist] except (ValueError, TypeError): # TODO: We should probably print a non-fatal warning here pass return addr_space, tasks
def calculate(self): addr_space = utils.load_as(self._config) tag = self._config.TAG if tag == None: debug.error("You must enter a --tag to find") minsize = self._config.MIN_SIZE maxsize = self._config.MAX_SIZE poolsize = lambda x : x >= minsize and x <= maxsize if self._config.PAGED: paged = True non_paged = False else: paged = False non_paged = True scanner = GenericPoolScan() scanner.checks = [ ('PoolTagCheck', dict(tag = tag)), ('CheckPoolSize', dict(condition = poolsize)), ('CheckPoolType', dict(paged = paged, non_paged = non_paged)), ] for offset in scanner.scan(addr_space): pool = obj.Object("_POOL_HEADER", offset = offset, vm = addr_space) buf = addr_space.zread(offset, minsize) yield pool, buf
def calculate(self): kernel_space = utils.load_as(self._config) ## Select the tags to scan for. Always find visited URLs, ## but make freed and redirected records optional. tags = ["URL "] if self._config.LEAK: tags.append("LEAK") if self._config.REDR: tags.append("REDR") ## Define the record type based on the tag tag_records = { "URL " : "_URL_RECORD", "LEAK" : "_URL_RECORD", "REDR" : "_REDR_RECORD"} ## Enumerate processes based on the --pid and --offset for proc in self.filter_tasks(tasks.pslist(kernel_space)): ## Acquire a process specific AS ps_as = proc.get_process_address_space() for hit in proc.search_process_memory(tags): ## Get a preview of the data to see what tag was detected tag = ps_as.read(hit, 4) ## Create the appropriate object type based on the tag record = obj.Object(tag_records[tag], offset = hit, vm = ps_as) if record.is_valid(): yield proc, record
def calculate(self): addr_space = utils.load_as(self._config) seen = [] for wind in self.scan_results(addr_space): # Find an address space for this window station's session session = self.find_session_space( addr_space, wind.dwSessionId) if not session: continue # Reset the object's native VM so pointers are # dereferenced in session space wind.set_native_vm(session.obj_vm) for winsta in wind.traverse(): if winsta.is_valid(): offset = winsta.PhysicalAddress if offset in seen: continue seen.append(offset) yield winsta
def calculate(self): addr_space = utils.load_as(self._config) if self._config.REGEX: try: if self._config.IGNORE_CASE: mod_re = re.compile(self._config.REGEX, re.I) else: mod_re = re.compile(self._config.REGEX) except re.error as e: debug.error('Error parsing regular expression: %s' % e) mods = dict((mod.DllBase.v(), mod) for mod in modules.lsmod(addr_space)) # We need the process list to find spaces for some drivers. Enumerate them here # instead of inside the find_space function, so we only have to do it once. procs = list(tasks.pslist(addr_space)) if self._config.BASE: if self._config.BASE in mods: mod_name = mods[self._config.BASE].BaseDllName else: mod_name = "UNKNOWN" yield addr_space, procs, int(self._config.BASE), mod_name else: for mod in list(mods.values()): if self._config.REGEX: if not mod_re.search(str(mod.FullDllName or '')) and not mod_re.search(str(mod.BaseDllName or '')): continue yield addr_space, procs, mod.DllBase.v(), mod.BaseDllName
def calculate(self): """Begin carving and analysing""" #Check output dir is provided if self._config.DUMP_DIR == None: debug.error("Please specify a dump directory (--dump-dir)") if not os.path.isdir(self._config.DUMP_DIR): debug.error(self._config.DUMP_DIR + " is not a directory") #Carve packets from all mempages self.addr_space = utils.load_as(self._config) for mempage in self.addr_space.get_available_addresses(): self.carve_packets(self.addr_space.zread(mempage[0], mempage[1])) #Analyze the carved/parsed packets packet_stats = self.analyze_packets(self.parsed_packets) #Dump files to dump-dir self.dump_packets_to_pcap(self.hex_packets, os.path.abspath(os.path.join(self._config.DUMP_DIR, 'packets.pcap'))) with open(os.path.abspath(os.path.join(self._config.DUMP_DIR, 'ips.txt')), 'w') as fd: for ip_to_check in packet_stats['unique_public_ips']: fd.write(ip_to_check + '\n') return packet_stats
def calculate(self): regapi = registryapi.RegistryApi(self._config) addr_space = utils.load_as(self._config) tasks = win32.tasks.pslist(addr_space) registerKeys = open('/Users/Lunde/volatility_plugins/registerRunKeys.txt').read().splitlines() for locations in registerKeys: base =locations.split('\\')[0] search_location = locations.split('\\',2)[2] if base == 'HKLM': hive = 'software' if base == 'HKCU': hive = 'NTUSER.DAT' #regapi.set_current(hive_name= "software", user = "******") regapi.set_current(hive_name= hive) key_ = search_location for value, data in regapi.reg_yield_values(hive_name = str(hive), key = str(key_)): yield value, data, locations
def calculate(self): if not has_yara: debug.error("Yara must be installed for this plugin") addr_space = utils.load_as(self._config) os, memory_model = self.is_valid_profile(addr_space.profile) if not os: debug.error("This command does not support the selected profile.") rules = yara.compile(sources=cobaltstrike_sig) for task in self.filter_tasks(tasks.pslist(addr_space)): scanner = malfind.VadYaraScanner(task=task, rules=rules) for hit, address in scanner.scan(): vad_base_addr, end = self.get_vad_base(task, address) proc_addr_space = task.get_process_address_space() data = proc_addr_space.zread(vad_base_addr, end - vad_base_addr) config_data = [] for nw in CONF_PATTERNS: cfg_addr = data.find(nw['pattern']) if cfg_addr != -1: break else: continue cfg_blob = data[cfg_addr:cfg_addr + nw['cfg_size']] config_data.append( self.parse_config(self.decode_config(cfg_blob), nw)) yield task, vad_base_addr, end, hit, memory_model, config_data break
def calculate(self): if self._config.MACHINE != "": self._config.update("MACHINE", "{0} ".format(self._config.MACHINE)) offsets = [] address_space = utils.load_as(self._config, astype = 'physical') if self._config.OFFSET != None: items = [int(o, 16) for o in self._config.OFFSET.split(',')] for offset in items: mft_buff = address_space.read(offset, self._config.ENTRYSIZE) bufferas = addrspace.BufferAddressSpace(self._config, data = mft_buff) mft_entry = obj.Object('MFT_FILE_RECORD', vm = bufferas, offset = 0) offsets.append((offset, mft_entry)) else: scanner = poolscan.MultiPoolScanner(needles = ['FILE', 'BAAD']) print "Scanning for MFT entries and building directory, this can take a while" seen = [] for _, offset in scanner.scan(address_space): mft_buff = address_space.read(offset, self._config.ENTRYSIZE) bufferas = addrspace.BufferAddressSpace(self._config, data = mft_buff) mft_entry = obj.Object('MFT_FILE_RECORD', vm = bufferas, offset = 0) temp = mft_entry.advance_one(mft_entry.ResidentAttributes.STDInfo.obj_offset + mft_entry.ResidentAttributes.ContentSize, mft_buff, self._config.ENTRYSIZE) name = "" if temp != None: mft_entry.add_path(temp.FileName) name = temp.FileName.get_name() if (int(mft_entry.RecordNumber), name) in seen: continue else: seen.append((int(mft_entry.RecordNumber), name)) offsets.append((offset, mft_entry)) for offset, mft_entry in offsets: mft_buff = address_space.read(offset, self._config.ENTRYSIZE) if self._config.DEBUGOUT: print "Processing MFT Entry at offset:", hex(offset) attributes = mft_entry.parse_attributes(mft_buff, not self._config.NOCHECK, self._config.ENTRYSIZE) yield offset, mft_entry, attributes
def calculate(self): addr_space = utils.load_as(self._config) modlist = list(modules.lsmod(addr_space)) mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modlist) mod_addrs = sorted(mods.keys()) drivers = dtree.DriverIrp(self._config).calculate() found_driver = "UNKNOWN" if self._config.ADDR: find_address = self._config.ADDR found_module = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(find_address)) if found_module: found_module = found_module.BaseDllName or found_module.FullDllName else: found_module = "UNKNOWN" for driver in drivers: if driver.DriverStart <= find_address < driver.DriverStart + driver.DriverSize: header = driver.get_object_header() found_driver = header.NameInfo.Name break yield (found_module, found_driver) else: for driver in drivers: driver_name = driver.get_object_header().NameInfo.Name owning_module = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(driver.DriverStart)) if owning_module: module_name = owning_module.BaseDllName or owning_module.FullDllName else: module_name = "UNKNOWN" yield (module_name, driver_name)
def calculate(self): if self._config.OUTPUT == "xlsx" and not has_openpyxl: debug.error( "You must install OpenPyxl for xlsx format:\n\thttps://bitbucket.org/ericgazoni/openpyxl/wiki/Home" ) elif self._config.OUTPUT == "xlsx" and not self._config.OUTPUT_FILE: debug.error( "You must specify an output *.xlsx file!\n\t(Example: --output-file=OUTPUT.xlsx)" ) addr_space = utils.load_as(self._config) all_tasks = list(tasks.pslist(addr_space)) ps_sources = {} # The keys are names of process sources. The values # are dictionaries whose keys are physical process # offsets and the values are _EPROCESS objects. ps_sources['pslist'] = self.check_pslist(all_tasks) ps_sources['psscan'] = self.check_psscan() ps_sources['thrdproc'] = self.check_thrdproc(addr_space) ps_sources['csrss'] = self.check_csrss_handles(all_tasks) ps_sources['pspcid'] = self.check_pspcid(addr_space) ps_sources['session'] = self.check_sessions(addr_space) if addr_space.profile.metadata.get( 'major', 0) == 6 and addr_space.profile.metadata.get('minor', 0) >= 2: ps_sources['deskthrd'] = {} else: ps_sources['deskthrd'] = self.check_desktop_thread(addr_space) # Build a list of offsets from all sources seen_offsets = [] for source in ps_sources.values(): for offset in source.keys(): if offset not in seen_offsets: seen_offsets.append(offset) yield offset, source[offset], ps_sources
def calculate(self): addr_space = utils.load_as(self._config) self.regapi = registryapi.RegistryApi(self._config) result = {} if not self._config.HIVE_OFFSET: self.regapi.set_current("SYSTEM") else: name = obj.Object("_CMHIVE", vm=addr_space, offset=self._config.HIVE_OFFSET).get_name() self.regapi.all_offsets[self._config.HIVE_OFFSET] = name self.regapi.current_offsets[self._config.HIVE_OFFSET] = name self.regapi.reset_current() currentcs = self.regapi.reg_get_currentcontrolset() if currentcs == None: currentcs = "ControlSet001" shutdownkey = currentcs + "\\Control\\Windows" key = self.regapi.reg_get_key("system", shutdownkey) value = self.regapi.reg_get_value("system", shutdownkey, "ShutdownTime", given_root=key) result["key"] = key result["hive"] = "SYSTEM" result["valuename"] = "ShutdownTime" result["value"] = value try: bufferas = addrspace.BufferAddressSpace(self._config, data=value) result["timestamp"] = obj.Object("WinTimeStamp", vm=bufferas, offset=0, is_utc=True) except struct.error: result["timestamp"] = "" yield result
def calculate(self): if not has_yara: debug.error("Yara must be installed for this plugin") addr_space = utils.load_as(self._config) osversion, memory_model = self.is_valid_profile(addr_space.profile) if not osversion: debug.error("This command does not support the selected profile.") base = os.path.dirname(os.path.abspath(__file__)) rules = yara.compile(base + "/yara/rule.yara") for task in self.filter_tasks(tasks.pslist(addr_space)): scanner = malfind.VadYaraScanner(task=task, rules=rules) for hit, address in scanner.scan(): vad_base_addr, end = self.get_vad_base(task, address) malname = str(hit).lower() if str(hit) in ["Himawari", "Lavender", "Armadill", "zark20rk"]: malname = "redleaves" if str(hit) in "TSC_Loader": malname = "tscookie" if "Agenttesla" in str(hit): malname = "agenttesla" try: module = import_module("volatility.plugins.malware.utils.{name}scan".format(name=malname)) module_cls = getattr(module, malname + "Config") instance = module_cls(self._config) except: debug.error("Can't loading module volatility.plugins.malware.utils.{name}scan".format(name=malname)) for task, vad_base_addr, end, hit, memory_model, config_data in instance.calculate(): yield task, vad_base_addr, end, hit, memory_model, config_data break
def calculate(self): addr_space = utils.load_as(self._config) # Currently we only support x86. The x64 does still have a IDT # but hooking is prohibited and results in bugcheck. if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") mods = dict((mod.DllBase, mod) for mod in modules.lsmod(addr_space)) mod_addrs = sorted(mods.keys()) for kpcr in tasks.get_kdbg(addr_space).kpcrs(): # Get the GDT for access to selector bases gdt = dict((i * 8, sd.Base) for i, sd in kpcr.gdt_entries()) for i, entry in kpcr.idt_entries(): # Where the IDT entry points. Per MITRE, add the GDT selector # base if available. This allows us to detect sneaky attempts # to hook IDT entries by changing the entry's GDT selector. addr = entry.Address + gdt.get(entry.Selector.v(), 0) # Lookup the function's owner module = tasks.find_module(mods, mod_addrs, addr) yield i, entry, addr, module
def get_registry_keys(self): addr_space = utils.load_as(self._config) hl = hivelist.HiveList(self._config) if not self._config.HIVE_OFFSET: hive_offsets = [h.obj_offset for h in hl.calculate()] else: hive_offsets = [self._config.HIVE_OFFSET] for hoff in set(hive_offsets): h = hivemod.HiveAddressSpace(addr_space, self._config, hoff) name = obj.Object("_CMHIVE", vm = addr_space, offset = hoff).get_name() root = rawreg.get_root(h) if not root: if self._config.HIVE_OFFSET: self.console_print("Unable to find root key. Is the hive offset correct?") else: if self._config.KEY: yield name, rawreg.open_key(root, self._config.KEY.split('\\')) else: yield name, root
def __init__(self, config, *args, **kwargs): common.AbstractWindowsCommand.__init__(self, config, *args, **kwargs) # Plugin parameters self._config.add_option('DUMP-DIR', short_option='D', default=None, help='Directory to which to dump found text', action='store', type='str') self._config.add_option('NULLS', short_option='n', default=False, help='keep nulls when outputting to stdout', action='store_true') self._config.add_option('PID', short_option='p', default=None, help='This Process ID', action='store', type='int') self._config.add_option('MINIMAL', short_option='m', default=None, help='Process name and text only', action='store_true') self._config.add_option('EXPERIMENTAL', short_option='e', default=None, help='Enable experimental options', action='store_true') self._config.add_option('EXPERIMENTAL-ONLY', short_option='E', default=None, help='Only do experimental options', action='store_true') # Object variables self._addr_space = utils.load_as(self._config) self._profile_is_32bit = (self._addr_space.profile.metadata['memory_model'] == '32bit') self._tagWND_size = self._addr_space.profile.get_obj_size('tagWND')
def calculate(self): #The returned data will be passed as data to render_text if not has_re: debug.error("Please install re ") addr_space = utils.load_as(self._config) ###???? # maybe I should add kernel space ????????? if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") #check_addr_space(addr_space) base = getBaseAddress(addr_space) if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") # get a list of all all processes runing from the memory dump tasks = self.generateProcesses(addr_space) pids = self.filter_tasks(tasks) # HOW TO USE IT ??? if self._config.PID is not None: return pids, addr_space print "type tasks" + str(type(tasks)) # create a new generator : and add only the new elements return tasks, addr_space
def calculate(self): if not self.is_nasm(): debug.error("Please install nasm") if not self._config.IJSON: debug.error("Please provide the input JSON trace") self._addrspace = utils.load_as(self._config) self.md = self.init_capstone() self.md.detail = True print "[+] From gadget: %s" % self._config.SGADGET print "[+] To gadget: %s" % self._config.GLIMIT self.get_json_trace() self.follow_trace() if self._config.DEBUG: self.get_trace_asm() if self._config.DB or self._config.IDB: self.serialize_opcodes()
def calculate(self): addr_space = utils.load_as(self._config) if not has_yara: debug.error("You must install yara to use this plugin") if not self._config.DUMP_DIR: debug.error("You must supply a --dump-dir parameter") if self._config.PHYSICAL: # Find the FileAddressSpace while addr_space.__class__.__name__ != "FileAddressSpace": addr_space = addr_space.base scanner = malfind.DiscontigYaraScanner( address_space=addr_space, rules=DumpCerts.rules ) for hit, address in scanner.scan(): cert = obj.Object( DumpCerts.type_map.get(hit.rule), vm=scanner.address_space, offset=address, ) if cert.is_valid(): yield None, cert else: for process in self.filter_tasks(tasks.pslist(addr_space)): scanner = malfind.VadYaraScanner( task=process, rules=DumpCerts.rules ) for hit, address in scanner.scan(): cert = obj.Object( DumpCerts.type_map.get(hit.rule), vm=scanner.address_space, offset=address, ) if cert.is_valid(): yield process, cert
def render_text(self, outfd, data): addr_space = utils.load_as(self._config) syscalls = addr_space.profile.syscalls bits32 = addr_space.profile.metadata.get('memory_model', '32bit') == '32bit' # Print out the entries for each table for idx, table, n, vm, mods, mod_addrs in data: outfd.write("SSDT[{0}] at {1:x} with {2} entries\n".format( idx, table, n)) for i in range(n): if bits32: # These are absolute function addresses in kernel memory. syscall_addr = obj.Object('address', table + (i * 4), vm).v() else: # These must be signed long for x64 because they are RVAs relative # to the base of the table and can be negative. offset = obj.Object('long', table + (i * 4), vm).v() # The offset is the top 20 bits of the 32 bit number. syscall_addr = table + (offset >> 4) try: syscall_name = syscalls[idx][i] except IndexError: syscall_name = "UNKNOWN" syscall_mod = tasks.find_module(mods, mod_addrs, syscall_addr) if syscall_mod: syscall_modname = syscall_mod.BaseDllName else: syscall_modname = "UNKNOWN" outfd.write( " Entry {0:#06x}: {1:#x} ({2}) owned by {3}\n".format( idx * 0x1000 + i, syscall_addr, syscall_name, syscall_modname))
def calculate(self, use_heuristics=False): address_space = utils.load_as(self._config, astype="physical") # Special needle: the first field, "type", is always equal to "table" # for the entries we're looking for. # # You might think a better needle is looking for "CREATE TABLE" in the # "sql" field, but we can't count backwards over other text fields to # get to the beginning of the record. needle = sqlitetools.Needle( yara.compile( source='rule r1 { strings: $a = "table" condition: $a }'), size=5, varint_offset=-8, byte_offset=0, ) schema = sqlitetools.TableSchema.from_str( PREDEFINED_TABLES["sqlite_master"]) searcher = sqlitetools.RowSearch(schema, needle) for address, row_id, types, values in searcher.find_records( address_space): sql = values[4] try: table_name, table_schema = sqlitetools.TableSchema.from_sql( sql, use_heuristics) except sqlitetools.SqlParsingError as e: continue if table_name != values[2]: continue needle_size = sqlitetools.RowSearch(table_schema).needle.size if self._config.RAW_SQL: yield table_name, needle_size, sql else: yield table_name, needle_size, str(table_schema)
def calculate(self): addr_space = utils.load_as(self._config) addr_space.profile.add_types(evt_log_types) if addr_space.profile.metadata.get('major', 0) != 5: print "This plugin only works on XP and 2K3" return if self._config.VERBOSE: self.reset_current() self.set_current("SYSTEM") ssids = getservicesids.GetServiceSids.calculate(self) for sid, service in ssids: self.extrasids[sid] = " (Service: " + service + ")" else: for sid in self.extrasids: self.extrasids[sid] = " (Service: " + self.extrasids[sid] + ")" self.reset_current() self.set_current("SOFTWARE") for k1 in self.reg_enum_key( 'SOFTWARE', 'Microsoft\\Windows NT\\CurrentVersion\\ProfileList'): val = self.reg_get_value('SOFTWARE', k1, 'ProfileImagePath') sid = k1.split("\\")[-1] if val != None: self.extrasids[sid] = " (User: "******"\\")[-1] + ")" for proc in tasks.pslist(addr_space): if str(proc.ImageFileName).lower() == "services.exe": map = self.list_mapped_files(proc, pe_only=False, get_data=True) for key, (name, buf) in map.items(): if name and buf: name = str(name).lower() if name.endswith(".evt"): yield name, buf
def calculate(self): addr_space = utils.load_as(self._config) regapi = registryapi.RegistryApi(self._config) user_hive = "ntuser.dat" trustrecords = {"Software\\Microsoft\\Office\\14.0\\Word\\Security\\Trusted Documents\\TrustRecords", "Software\\Microsoft\\Office\\14.0\\Excel\\Security\\Trusted Documents\\TrustRecords", "Software\\Microsoft\\Office\\14.0\\PowerPoint\\Security\\Trusted Documents\\TrustRecords", "Software\\Microsoft\\Office\\14.0\\Access\\Security\\Trusted Documents\\TrustRecords", } hive_offsets = {} if not self._config.HIVE_OFFSET: for h in hivelist.HiveList.calculate(self): hive_name = self.hive_name(h) if user_hive in hive_name.lower(): hive_offsets[h.obj_offset] = hive_name else: hive_offsets = [("User Specified", self._config.HIVE_OFFSET)] found = False for hoff, name in hive_offsets.iteritems(): h = hivemod.HiveAddressSpace(addr_space, self._config, hoff) root = rawreg.get_root(h) if not root: if self._config.HIVE_OFFSET: debug.error("Unable to find root key. Is the hive offset correct?") else: for r in trustrecords: trustrecord_key = rawreg.open_key(root, r.split('\\')) if trustrecord_key: yield name, r, trustrecord_key found = True if not found: debug.error("The requested key could not be found in the hive(s) searched\n")
def collect_pe_info(self): addr_space = utils.load_as(self._config) if self._config.PID != None: for prc in tasks.pslist(addr_space): if prc.UniqueProcessId == self._config.PID: addr_space = prc.get_process_address_space() break dos_header = obj.Object("_IMAGE_DOS_HEADER", offset=self._config.BASE, vm=addr_space) nt_headers = dos_header.get_nt_header() sections = list(nt_headers.get_sections()) sections_data = [] for i in range(0, len(sections)): data = addr_space.zread( sections[i].VirtualAddress + self._config.BASE, sections[i].Misc.VirtualSize) sections_data.append(data) return dos_header, nt_headers, sections, sections_data
def calculate(self): image_name = os.path.basename(self._config.LOCATION) self.log(image_name) self.kernel_address_space = utils.load_as(self._config) available_pages = self.kernel_address_space.get_available_pages() #self.log('Get continuous pages') #dict_page_addr_to_size = self.get_continuous_pages(available_pages) dict_page_addr_to_size = {} for addr, size in available_pages: if addr > 0x80000000: dict_page_addr_to_size[addr] = size with open(PAGES_OUTPUT_PATH + 'pages.' + image_name, 'w') as output: list_addr = dict_page_addr_to_size.keys() list_addr.sort() for addr in list_addr: size = dict_page_addr_to_size[addr] physical_addr = self.kernel_address_space.vtop(addr) output.write( str(addr) + '\t' + str(physical_addr) + '\t' + str(size) + '\n') self.log('Finish')
def calculate(self): addr_space = utils.load_as(self._config) all_tasks = list(tasks.pslist(addr_space)) ps_sources = {} # The keys are names of process sources. The values # are dictionaries whose keys are physical process # offsets and the values are _EPROCESS objects. ps_sources['pslist'] = self.check_pslist(all_tasks) ps_sources['psscan'] = self.check_psscan() ps_sources['thrdproc'] = self.check_thrdproc(addr_space) ps_sources['csrss'] = self.check_csrss_handles(all_tasks) ps_sources['pspcid'] = self.check_pspcid(addr_space) ps_sources['session'] = self.check_sessions(addr_space) ps_sources['deskthrd'] = self.check_desktop_thread(addr_space) # Build a list of offsets from all sources seen_offsets = [] for source in ps_sources.values(): for offset in source.keys(): if offset not in seen_offsets: seen_offsets.append(offset) yield offset, source[offset], ps_sources
def calculate(self): addr_space = utils.load_as(self._config) regapi = registryapi.RegistryApi(self._config) hiveset = set() if not self._config.HIVE_OFFSET: hive_offsets = [ h.obj_offset for h in hivelist.HiveList.calculate(self) ] else: hive_offsets = [self._config.HIVE_OFFSET] for hoff in set(hive_offsets): h = hivemod.HiveAddressSpace(addr_space, self._config, hoff) name = obj.Object("_CMHIVE", vm=addr_space, offset=hoff).get_name() print "[debug]", name root = rawreg.get_root(h) hive = name.split("\\")[-1] hiveset.add(hive) print hiveset for hive in hiveset: print "\n========================", hive for regtime, keyname in regapi.reg_get_last_modified(hive, count=5): print "\n", regtime, keyname regapi.set_current(hive_name=hive) k = keyname.split('\\')[1:] k = '\\'.join(k) print k + "\n" for value, tp, data in self.reg_yield_values_type( regapi, hive_name=hive, key=k): yield value, tp, data regapi.reset_current()
def generator(self, data): profile = utils.load_as(self._config).profile # Get the OS version being analyzed version = (profile.metadata.get('major', 0), profile.metadata.get('minor', 0)) # Choose which USER handle enum to use if version >= (6, 1): handle_types = consts.HANDLE_TYPE_ENUM_SEVEN else: handle_types = consts.HANDLE_TYPE_ENUM for session in data: gahti = session.find_gahti() if gahti: for i, h in handle_types.items(): yield (0, [ str(session.SessionId), str(h), str(gahti.types[i].dwAllocTag), Address(gahti.types[i].fnDestroy), str(gahti.types[i].bObjectCreateFlags) ])
def calculate(self): """Determines the address space""" profilelist = [ p.__name__ for p in registry.get_plugin_classes(obj.Profile).values() ] proflens = {} maxlen = 0 origprofile = self._config.PROFILE for p in profilelist: self._config.update('PROFILE', p) buf = addrspace.BufferAddressSpace(self._config) proflens[p] = str(obj.VolMagic(buf).KDBGHeader) maxlen = max(maxlen, len(proflens[p])) self._config.update('PROFILE', origprofile) scanner = KDBGScanner(needles = proflens.values()) aspace = utils.load_as(self._config, astype = 'any') for offset in scanner.scan(aspace): val = aspace.read(offset, maxlen + 0x10) for l in proflens: if val.find(proflens[l]) >= 0: kdbg = obj.Object("_KDDEBUGGER_DATA64", offset = offset, vm = aspace) yield l, kdbg
def calculate(self): addr_space = utils.load_as(self._config) regapi = registryapi.RegistryApi(self._config) regapi.reset_current() currentcs = regapi.reg_get_currentcontrolset() if currentcs == None: currentcs = "ControlSet001" version = (addr_space.profile.metadata.get('major', 0), addr_space.profile.metadata.get('minor', 0)) xp = False if version <= (5, 1): key = currentcs + '\\' + "Control\\Session Manager\\AppCompatibility" xp = True else: key = currentcs + '\\' + "Control\\Session Manager\\AppCompatCache" data_raw = regapi.reg_get_value('system', key, "AppCompatCache") if data_raw == None or len(data_raw) < 0x1c: debug.warning("No ShimCache data found") return bufferas = addrspace.BufferAddressSpace(self._config, data=data_raw) shimdata = obj.Object("ShimRecords", offset=0, vm=bufferas) if shimdata == None: debug.warning("No ShimCache data found") return for e in shimdata.Entries: if xp: yield e.Path, e.LastModified, e.LastUpdate else: yield self.remove_unprintable( bufferas.read(int(e.PathOffset), int(e.Length))), e.LastModified, None
def calculate(self): addr_space = utils.load_as(self._config) win7 = addr_space.profile.metadata.get( 'major', 0) == 6 and addr_space.profile.metadata.get('minor', 0) >= 1 skey = "software\\microsoft\\windows\\currentversion\\explorer\\userassist" if not self._config.HIVE_OFFSET: self.regapi.set_current("ntuser.dat") else: name = obj.Object("_CMHIVE", vm=addr_space, offset=self._config.HIVE_OFFSET).get_name() self.regapi.all_offsets[self._config.HIVE_OFFSET] = name self.regapi.current_offsets[self._config.HIVE_OFFSET] = name for key, name in self.regapi.reg_yield_key(None, skey): for guidkey in self.regapi.reg_get_all_subkeys(None, None, given_root=key): for count in self.regapi.reg_get_all_subkeys( None, None, given_root=guidkey): if count.Name == "Count": yield win7, name, count
def calculate(self): self.get_dll_list() self.regapi = registryapi.RegistryApi(self._config) self.currentcs = self.regapi.reg_get_currentcontrolset() or "ControlSet001" asep_list = ['autoruns', 'services', 'appinit', 'winlogon', 'tasks', 'activesetup', 'sdb'] os_major = utils.load_as(self._config).profile.metadata.get('major', 0) # If all_offsets is empty then regapi was unable to find # hive offsets and we exit with an error message if not self.regapi.all_offsets: debug.error('Unable to find registry hives.') if self._config.ASEP_TYPE: debug.debug('Config: {}'.format(self._config.ASEP_TYPE)) asep_list = [s for s in self._config.ASEP_TYPE.replace(' ', '').split(',')] # Scan for ASEPs and populate the lists if 'autoruns' in asep_list: self.autoruns = self.get_autoruns() if 'services' in asep_list: self.services = self.get_services() if 'appinit' in asep_list: self.appinit_dlls = self.get_appinit_dlls() if 'winlogon' in asep_list: self.winlogon = self.get_winlogon() if os_major == 5: self.winlogon_registrations = self.get_winlogon_registrations() if 'tasks' in asep_list: self.tasks = self.get_tasks() if 'activesetup' in asep_list: self.activesetup = self.get_activesetup() if 'sdb' in asep_list: self.sdb = self.get_sdb() #Returns a generator to generator() that generates the unified output data return self.get_unified_output_data()
def calculate(self): if not has_yara: debug.error("Yara must be installed for this plugin") addr_space = utils.load_as(self._config) rules = yara.compile(sources=sigs) for task in self.filter_tasks(tasks.pslist(addr_space)): scanner = malfind.VadYaraScanner(task=task, rules=rules) config = False start_add = False stop_add = False for hit, address in scanner.scan(): if str(hit) == 'darkcomet_config': config = hit start_add = address if str(hit) == 'darkcomet_config_stop': stop_add = address + 0x20 #Add 0x20 to address to get all of EOF statement #if we have a hit on all three sigs lets yield if config and start_add and stop_add: yield task, config, start_add, stop_add else: pass
def calculate(self): addr_space = utils.load_as(self._config) if self._config.DUMP_DIR == None: debug.error("Please specify a dump directory (--dump-dir)") if not os.path.isdir(self._config.DUMP_DIR): debug.error(self._config.DUMP_DIR + " is not a directory") if self._config.OFFSET != None: data = [ self.virtual_process_from_physical_offset( addr_space, self._config.OFFSET) ] else: data = self.filter_tasks(tasks.pslist(addr_space)) if self._config.REGEX: try: if self._config.IGNORE_CASE: mod_re = re.compile(self._config.REGEX, re.I) else: mod_re = re.compile(self._config.REGEX) except re.error, e: debug.error('Error parsing regular expression: %s' % e)
def calculate(self): if not has_yara: debug.error("Yara must be installed for this plugin") addr_space = utils.load_as(self._config) if not self.is_valid_profile(addr_space.profile): debug.error("This command does not support the selected profile.") # For each process in the list for task in self.filter_tasks(tasks.pslist(addr_space)): # print task.ImageFileName for vad, address_space in task.get_vads( vad_filter=task._injection_filter): # Injected code detected if there's values returned rules = yara.compile(sources=signatures) scanner = malfind.VadYaraScanner(task=task, rules=rules) # print 'before' for hit, address in scanner.scan(): vad_base_addr = self.get_vad_base(task, address) # Get a chuck of memory of size 2048 next to where the string was detected content = address_space.zread(address, 2048) yield task, address, vad_base_addr, content break
def __guessProfile(self): self.__steps += 1 bestguess = None profiles = [ p.__name__ for p in registry.get_plugin_classes(obj.Profile).values() ] scan_kdbg = kdbgscan.KDBGScan(self._config) suglist = [] suglist = [s for s, _ in scan_kdbg.calculate()] if suglist: bestguess = suglist[0] if bestguess in profiles: profiles = [bestguess] + profiles chosen = 'none' profcount = len(profiles) count = 1 for profile in profiles: self.stateinfo = "Step {:<2d} / {:<2d} -- Guessing profile: trying profile {:<20s} ({:<2d} / {:<2d})".format( self.__step, self.__steps, profile, count, profcount) self._config.updateCtx('profile', profile) addr_space = utils.load_as(self._config, astype='any') if hasattr(addr_space, 'dtb'): chosen = profile break count += 1 if debug and bestguess != chosen: print bestguess, chosen volmagic = obj.VolMagic(addr_space) kdbgoffset = volmagic.KDBG.v() self._kdbg = obj.Object("_KDDEBUGGER_DATA64", offset=kdbgoffset, vm=addr_space) self._config.updateCtx('kdbg', self._kdbg.obj_offset) self._aspace = addr_space self.__step += 1