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): """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 get_processes(self, addr_space): """Enumerate processes based on user options. :param addr_space | <addrspace.AbstractVirtualAddressSpace> :returns <list> """ bounce_back = taskmods.DllList.virtual_process_from_physical_offset if self._config.OFFSET != None: tasks = [bounce_back(addr_space, self._config.OFFSET)] elif self._config.SCAN: procs = list(filescan.PSScan(self._config).calculate()) tasks = [] for task in procs: tasks.append(bounce_back(addr_space, task.obj_offset)) else: tasks = win32.tasks.pslist(addr_space) try: if self._config.PID is not None: pidlist = [int(p) for p in self._config.PID.split(',')] tasks = [t for t in tasks if int(t.UniqueProcessId) in pidlist] except (ValueError, TypeError): debug.error("Invalid PID {0}".format(self._config.PID)) return tasks
def calculate(self): addr_space = utils.load_as(self._config) tasklist = [] modslist = [] if self._config.SCAN: if not self._config.KERNEL_ONLY: for t in filescan.PSScan(self._config).calculate(): v = self.virtual_process_from_physical_offset(addr_space, t.obj_offset) if v: tasklist.append(v) if not self._config.PROCESS_ONLY: modslist = [m for m in modscan.ModScan(self._config).calculate()] else: if not self._config.KERNEL_ONLY: tasklist = [t for t in tasks.pslist(addr_space)] if not self._config.PROCESS_ONLY: modslist = [m for m in modules.lsmod(addr_space)] for task in tasklist: for mod in task.get_load_modules(): yield task, mod for mod in modslist: yield None, mod
def _get_dtb(self): ps = filescan.PSScan(self.config) for ep in ps.calculate(): if str(ep.ImageFileName) == 'System': self.config.update('dtb', ep.Pcb.DirectoryTableBase) return True return False
def _get_dtb(self): """Use psscan to get system dtb and apply it.""" ps = filescan.PSScan(self.config) for ep in ps.calculate(): if str(ep.ImageFileName) == "System": self.config.update("dtb", ep.Pcb.DirectoryTableBase) return True return False
def execute(self): tasks = [] self.addr_space = utils.load_as(self._config) page_size = 0x1000 try: procs = list(filescan.PSScan(self._config).calculate()) tasks = [] for task in procs: tasks.append( self.virtual_process_from_physical_offset( self.addr_space, task.obj_offset)) except: # not properly tested print 'trying with pslist..' tasks = win32.tasks.pslist(self.addr_space) if self._config.VERBOSE: print 'Found %d tasks' % len(tasks) print("kernel mapping...") available_pages = self.addr_space.get_available_pages() if self._config.VERBOSE: print("Calculating task mappings...") for task in tasks: if self._config.VERBOSE: print " Process: %s\tPPID: %d\tPid: %d" % ( str(task.ImageFileName), int(task.InheritedFromUniqueProcessId), int(task.UniqueProcessId)) #obj_offset if (self._config.PNAME is None and self._config.PID is None) or ( self._config.PNAME is not None and task.ImageFileName.startswith(self._config.PNAME)) or ( self._config.PID is not None and int(task.UniqueProcessId) == self._config.PID): task_space = task.get_process_address_space() available_pages = task_space.get_available_pages() for (vpage, vpage_size) in available_pages: physpage = task_space.vtop(vpage) for i in xrange(0, vpage_size, page_size): pagedump = task_space.read( vpage, vpage_size + 0x30) # +0x30 prevents boundaries breaks result = self.get_type_of( pagedump, self._config.FILTERS, analyze=True, uuid_search=self._config.UUIDS) if result is not None: if self._config.VERBOSE: print "=> at offset Virtual: 0x%-10x\tPhysical: 0x%-10x\t Size: 0x%-12x" % ( vpage, physpage, vpage_size) print self.show(result[0], result[1]) #except: # return False return True
def calculate(self): address_space = utils.load_as(self._config) for process in tasks.pslist(address_space): pslist_offset = process.obj_offset for p in filescan.PSScan(self._config).calculate(): psscan_offset = p.obj_offset if pslist_offset != psscan_offset: tasks_hidden = [ taskmods.DllList.virtual_process_from_physical_offset( address_space, psscan_offset) ] return tasks_hidden
def calculate(self): # setting the address space addr_space = utils.load_as(self._config) # initalte pslist and get the results pl = tasks.pslist(addr_space) # initialte psscan and get the results ps = filescan.PSScan(self._config).calculate() # list to store pid s pids = [] #store the pid s of processes for process in pl: pids.append(int(process.UniqueProcessId)) # compare the results from psscan and pslist, yield the hidden process for process in ps: if int(process.UniqueProcessId) not in pids: yield process
def check_psscan(self): """Enumerate processes with pool tag scanning""" return dict((p.obj_offset, p) for p in filescan.PSScan(self._config).calculate())
def check_psscan(self): """Enumerate processes with pool tag scanning""" return dict((PsXview.get_file_offset(p), p) for p in filescan.PSScan(self._config).calculate())
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)" ) if (self._config.HIVE or self._config.USER) and not (self._config.REGISTRY): debug.error( "You must use -R/--registry in conjuction with -H/--hive and/or -U/--user" ) addr_space = utils.load_as(self._config) version = (addr_space.profile.metadata.get('major', 0), addr_space.profile.metadata.get('minor', 0)) pids = {} #dictionary of process IDs/ImageFileName offsets = [] #process offsets im = imageinfo.ImageInfo(self._config).get_image_time(addr_space) body = False if self._config.OUTPUT == "body": body = True if not body: event = "{0}|[END LIVE RESPONSE]\n".format(im['ImageDatetime']) else: event = "0|[END LIVE RESPONSE]|0|---------------|0|0|0|{0}|{0}|{0}|{0}\n".format( im['ImageDatetime'].v()) yield event # Get EPROCESS psscan = filescan.PSScan(self._config).calculate() for eprocess in psscan: if eprocess.obj_offset not in offsets: offsets.append(eprocess.obj_offset) if not body: line = "{0}|{1}|{2}|{3}|{4}|{5}|0x{6:08x}||\n".format( eprocess.CreateTime or '-1', "[PROCESS]", eprocess.ImageFileName, eprocess.UniqueProcessId, eprocess.InheritedFromUniqueProcessId, eprocess.ExitTime or '', eprocess.obj_offset) else: line = "0|[PROCESS] {2}/PID: {3}/PPID: {4}/POffset: 0x{5:08x}|0|---------------|0|0|0|{0}|{1}|{0}|{0}\n".format( eprocess.CreateTime.v(), eprocess.ExitTime.v(), eprocess.ImageFileName, eprocess.UniqueProcessId, eprocess.InheritedFromUniqueProcessId, eprocess.obj_offset) pids[eprocess.UniqueProcessId.v()] = eprocess.ImageFileName yield line # Get Sockets and Evtlogs XP/2k3 only if addr_space.profile.metadata.get('major', 0) == 5: socks = sockets.Sockets(self._config).calculate() #socks = sockscan.SockScan(self._config).calculate() # you can use sockscan instead if you uncomment for sock in socks: la = "{0}:{1}".format(sock.LocalIpAddress, sock.LocalPort) if not body: line = "{0}|[SOCKET]|{1}|{2}|Protocol: {3} ({4})|{5:#010x}|||\n".format( sock.CreateTime, sock.Pid, la, sock.Protocol, protos.protos.get(sock.Protocol.v(), "-"), sock.obj_offset) else: line = "0|[SOCKET] PID: {1}/LocalIP: {2}/Protocol: {3}({4})/POffset: 0x{5:#010x}|0|---------------|0|0|0|{0}|{0}|{0}|{0}\n".format( sock.CreateTime.v(), sock.Pid, la, sock.Protocol, protos.protos.get(sock.Protocol.v(), "-"), sock.obj_offset) yield line evt = evtlogs.EvtLogs(self._config) stuff = evt.calculate() for name, buf in stuff: for fields in evt.parse_evt_info(name, buf, rawtime=True): if not body: line = '{0} |[EVT LOG]|{1}|{2}|{3}|{4}|{5}|{6}|{7}\n'.format( fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7]) else: line = "0|[EVT LOG] {1}/{2}/{3}/{4}/{5}/{6}/{7}|0|---------------|0|0|0|{0}|{0}|{0}|{0}\n".format( fields[0].v(), fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7]) yield line else: # Vista+ nets = netscan.Netscan(self._config).calculate() for net_object, proto, laddr, lport, raddr, rport, state in nets: conn = "{0}:{1} -> {2}:{3}".format(laddr, lport, raddr, rport) if not body: line = "{0}|[NETWORK CONNECTION]|{1}|{2}|{3}|{4}|{5:<#10x}||\n".format( str(net_object.CreateTime or "-1"), net_object.Owner.UniqueProcessId, conn, proto, state, net_object.obj_offset) else: line = "0|[NETWORK CONNECTION] {1}/{2}/{3}/{4}/{5:<#10x}|0|---------------|0|0|0|{0}|{0}|{0}|{0}\n".format( net_object.CreateTime.v(), net_object.Owner.UniqueProcessId, conn, proto, state, net_object.obj_offset) yield line # Get threads threads = modscan.ThrdScan(self._config).calculate() for thread in threads: image = pids.get(thread.Cid.UniqueProcess.v(), "UNKNOWN") if not body: line = "{0}|[THREAD]|{1}|{2}|{3}|{4}|||\n".format( thread.CreateTime or '-1', image, thread.Cid.UniqueProcess, thread.Cid.UniqueThread, thread.ExitTime or '', ) else: line = "0|[THREAD] {2}/PID: {3}/TID: {4}|0|---------------|0|0|0|{0}|{1}|{0}|{0}\n".format( thread.CreateTime.v(), thread.ExitTime.v(), image, thread.Cid.UniqueProcess, thread.Cid.UniqueThread, ) yield line # now we get to the PE part. All PE's are dumped in case you want to inspect them later data = moddump.ModDump(self._config).calculate() for addr_space, procs, mod_base, mod_name in data: mod_name = str(mod_name or '') space = tasks.find_space(addr_space, procs, mod_base) if space != None: try: header = procdump.ProcExeDump(self._config).get_nt_header( space, mod_base) except ValueError, ve: continue try: if not body: line = "{0}|[PE Timestamp (module)]|{1}||{2:#010x}|||||\n".format( header.FileHeader.TimeDateStamp or '-1', mod_name, mod_base) else: line = "0|[PE Timestamp (module)] {1}/Base: {2:#010x}|0|---------------|0|0|0|{0}|{0}|{0}|{0}\n".format( header.FileHeader.TimeDateStamp.v(), mod_name, mod_base) except ValueError, ve: if not body: line = "-1|[PE Timestamp (module)]|{0}||{1}|||||\n".format( mod_name, mod_base) else: line = "0|[PE Timestamp (module)] {0}/Base: {1:#010x}|0|---------------|0|0|0|0|0|0|0\n".format( mod_name, mod_base) yield line
def calculate(self): # Check if yara has been installed if not has_yara: debug.error("You must install yara to use this plugin") # Starts listing all running processes, using the selected method tasks = [] if self._config.SCAN: tasks = self.filter_tasks( list(filescan.PSScan(self._config).calculate())) else: addr_space = utils.load_as(self._config) tasks = self.filter_tasks(win32.tasks.pslist(addr_space)) procs = [] dumped_files = [] for task in tasks: task_space = task.get_process_address_space() if task_space is None: debug.warning( "Cannot acquire process AS for process {0}".format( task.ImageFileName)) continue elif task.Peb is None: debug.warning( "PEB at {0:#x} is not available (paging?) for process {1}". format(task.m('Peb'), task.m('ImageFileName'))) continue elif task_space.vtop(task.Peb.ImageBaseAddress) is None: debug.warning( "ImageBaseAddress at {0:#x} is not available (paging?) for process {1}" .format(task.Peb.ImageBaseAddress, task.ImageFileName)) continue else: # Extracts the file and checks the indicators of powershell debug.debug("Processing file {0}".format( task.m('ImageFileName'))) pe_file = self.dump_pe(task_space, task.Peb.ImageBaseAddress) if pe_file and self.is_powershell(pe_file): # Powershell found procs.append(task) # Check for VAD inspection if self._config.INSPECT_VAD: if self._config.DUMP_DIR is 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") offset = task_space.vtop(task.obj_offset) # if this fails, we'll get its physical offset using kernel space if offset is None: offset = task.obj_vm.vtop(task.obj_offset) if offset is None: offset = 0 print "Inspecting VAD for " + str(task.UniqueProcessId) def filter(x): return x.Length < self._config.MAX_SIZE for vad, _aaddrspace in task.get_vads( vad_filter=filter, skip_max_commit=True): # Compose file name vad_start = self.format_value( vad.Start, "[addrpad]") vad_end = self.format_value(vad.End, "[addrpad]") path = os.path.join( self._config.DUMP_DIR, "{0}.{1:x}.{2}-{3}.dmp".format( task.ImageFileName, offset, vad_start, vad_end)) dumped_files.append( (task.UniqueProcessId, task.ImageFileName, vad.Start, vad.End, self.inspect_vad(path, vad, task_space))) return procs, dumped_files