def main(): pid = int(sys.argv[1]) proc = Process(pid) #= info print "pid;", proc.get_pid() print "is_alive;", proc.is_alive() print "is_debugged;", proc.is_debugged() print "is_wow;", proc.is_wow64() print "arch;", proc.get_arch() print "bits;", proc.get_bits() print "filename:", proc.get_filename() print "exit_time;", proc.get_exit_time() print "running_time;", proc.get_running_time() print "service;", proc.get_services() print "policy;", proc.get_dep_policy() print "peb;", proc.get_peb() print "main_module;", proc.get_main_module() print "peb_address", proc.get_peb_address() print "entry_point;", proc.get_entry_point() print "image_base;", proc.get_image_base() print "image_name;", proc.get_image_name() print "command_line;", proc.get_command_line() print "environment;", proc.get_environment() print "handle;", proc.get_handle() print "resume;",proc.resume()
class Main(object): def __init__(self, argv): self.argv = argv def parse_cmdline(self): # An empty command line causes the help message to be shown if len(self.argv) == 1: self.argv = self.argv + ['-h'] # Usage string usage = "%prog [options] <target process IDs or names...>" self.parser = optparse.OptionParser(usage=usage) # Options to set the search method search = optparse.OptionGroup( self.parser, "What to search", "(at least one of these switches must be used)") search.add_option("-s", "--string", action="append", metavar="VALUE", help="where VALUE is case sensitive text") search.add_option("-i", "--istring", action="append", metavar="VALUE", help="where VALUE is case insensitive text") search.add_option("-x", "--hexa", action="append", metavar="VALUE", help="where VALUE is hexadecimal data") search.add_option("-p", "--pattern", action="append", metavar="VALUE", help="where VALUE is an hexadecimal pattern") self.parser.add_option_group(search) # Options to control the search internals engine = optparse.OptionGroup(self.parser, "How to search") engine.add_option("-m", "--memory-pages", action="store", type="int", metavar="NUMBER", help="maximum number of consecutive memory pages" \ " to read (matches larger than this won't" \ " be found) " \ "[default: 2, use 0 for no limit]") self.parser.add_option_group(engine) # Options to set the output type output = optparse.OptionGroup(self.parser, "What to show") output.add_option("-v", "--verbose", action="store_true", dest="verbose", help="verbose output") output.add_option("-q", "--quiet", action="store_false", dest="verbose", help="brief output [default]") self.parser.add_option_group(output) # Default values self.parser.set_defaults( string=[], istring=[], hexa=[], pattern=[], regexp=[], memory_pages=2, verbose=False, ) # Parse the command line and check for validity (self.options, self.targets) = self.parser.parse_args(self.argv) # Our script's filename is not a target, skip it self.targets = self.targets[1:] # Fail if no search query was entered if not self.options.string and \ not self.options.istring and \ not self.options.hexa and \ not self.options.pattern: self.parser.error("at least one search switch must be used") def prepare_input(self): # Build the lists of search objects self.build_searchers_list(StringSearch) self.build_searchers_list(TextSearch) self.build_searchers_list(HexSearch) self.build_searchers_list(PatternSearch) # Build the list of target pids self.build_targets_list() def build_searchers_list(self, cls): searchers = getattr(self.options, cls.name) for index in range(len(searchers)): try: searchers[index] = cls(searchers[index], index) except Exception as e: msg = cls.init_error_msg(index, searchers[index], e) self.parser.error(msg) def build_targets_list(self): # Take a process snapshot self.system = System() self.system.request_debug_privileges() self.system.scan_processes() # If no targets were given, search on all processes if not self.targets: self.targets = self.system.get_process_ids() # If targets were given, search only on those processes else: expanded_targets = set() for token in self.targets: try: pid = HexInput.integer(token) if not self.system.has_process(pid): self.parser.error("process not found: %s" % token) expanded_targets.add(pid) except ValueError: found = self.system.find_processes_by_filename(token) pidlist = [process.get_pid() for (process, _) in found] if not pidlist: self.parser.error("process not found: %s" % token) expanded_targets.update(pidlist) self.targets = list(expanded_targets) # Sort the targets list self.targets.sort() def do_search(self): # For each target process... for self.pid in self.targets: # Try to open the process, skip on error try: self.process = Process(self.pid) self.process.get_handle() except WindowsError: print("Can't open process %d, skipping" % self.pid) if self.options.verbose: print continue # Get a list of allocated memory regions memory = list() for mbi in self.process.get_memory_map(): if mbi.State == win32.MEM_COMMIT and \ not mbi.Protect & win32.PAGE_GUARD: memory.append((mbi.BaseAddress, mbi.RegionSize)) # If no allocation limit is set, # read entire regions and search on them if self.options.memory_pages <= 0: for (address, size) in memory: try: data = self.process.read(address, size) except WindowsError as e: begin = HexDump.address(address) end = HexDump.address(address + size) msg = "Error reading %s-%s: %s" msg = msg % (begin, end, str(e)) print(msg) if self.options.verbose: print continue self.search_block(data, address, 0) # If an allocation limit is set, # read blocks within regions to search else: step = self.system.pageSize size = step * self.options.memory_pages for (address, total_size) in memory: try: end = address + total_size shift = 0 buffer = self.process.read(address, min(size, total_size)) while 1: self.search_block(buffer, address, shift) shift = step address = address + step if address >= end: break buffer = buffer[step:] buffer = buffer + self.process.read(address, step) except WindowsError as e: begin = HexDump.address(address) end = HexDump.address(address + total_size) msg = "Error reading %s-%s: %s" msg = msg % (begin, end, str(e)) print(msg) if self.options.verbose: print def search_block(self, data, address, shift): self.search_block_with(self.options.string, data, address, shift) self.search_block_with(self.options.istring, data, address, shift) self.search_block_with(self.options.hexa, data, address, shift) self.search_block_with(self.options.pattern, data, address, shift) def search_block_with(self, searchers_list, data, address, shift): for searcher in searchers_list: if shift == 0: searcher.restart() else: searcher.shift(shift) while 1: searcher.search(data) if not searcher.found(): break if self.options.verbose: print(searcher.message(self.pid, address - shift, data)) print else: print(searcher.message(self.pid, address - shift)) def run(self): # Banner print("Process memory finder") print("by Mario Vilas (mvilas at gmail.com)") print # Parse the command line self.parse_cmdline() # Prepare the input self.prepare_input() # Perform the search on the selected targets self.do_search()