def miasm_machine(): """Retrieve a miasm2 machine using the R2M2_ARCH environment variable.""" r2m2_arch = os.getenv("R2M2_ARCH") available_archs = Machine.available_machine() if not r2m2_arch or not r2m2_arch in available_archs: message = "Please specify a valid miasm2 arch in the R2M2_ARCH " \ "environment variable !\n" \ "The following are available: " message += ", ".join(available_archs) print >> sys.stderr, message + "\n" else: return Machine(r2m2_arch)
def miasm_machine(): """Retrieve a miasm2 machine using the R2M2_ARCH environment variable.""" r2m2_arch = os.getenv("R2M2_ARCH") available_archs = Machine.available_machine() if not r2m2_arch or r2m2_arch not in available_archs: message = "Please specify a valid miasm2 arch in the R2M2_ARCH " message += "environment variable !\nThe following are available: " message += ", ".join(available_archs) print >> sys.stderr, message + "\n" return None else: global MIASM_MACHINE if MIASM_MACHINE is None: MIASM_MACHINE = Machine(r2m2_arch) return MIASM_MACHINE
from miasm2.analysis.data_flow import dead_simp, DiGraphDefUse, ReachingDefinitions from miasm2.expression.simplifications import expr_simp log = logging.getLogger("dis") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.INFO) parser = ArgumentParser("Disassemble a binary") parser.add_argument('filename', help="File to disassemble") parser.add_argument('address', help="Starting address for disassembly engine", nargs="*") parser.add_argument('-m', '--architecture', help="architecture: " + \ ",".join(Machine.available_machine())) parser.add_argument('-f', "--followcall", action="store_true", help="Follow call instructions") parser.add_argument('-b', "--blockwatchdog", default=None, type=int, help="Maximum number of basic block to disassemble") parser.add_argument('-n', "--funcswatchdog", default=None, type=int, help="Maximum number of function to disassemble") parser.add_argument('-r',
from argparse import ArgumentParser from pdb import pm from miasm2.analysis.machine import Machine from miasm2.analysis.binary import Container from miasm2.analysis.depgraph import DependencyGraph parser = ArgumentParser("Dependency grapher") parser.add_argument("filename", help="Binary to analyse") parser.add_argument("func_addr", help="Function address") parser.add_argument("target_addr", help="Address to start") parser.add_argument("element", nargs="+", help="Elements to track") parser.add_argument("-m", "--architecture", help="Architecture (%s)" % Machine.available_machine()) parser.add_argument("-i", "--implicit", help="Use implicit tracking", action="store_true") parser.add_argument("--unfollow-mem", help="Stop on memory statements", action="store_true") parser.add_argument("--unfollow-call", help="Stop on call statements", action="store_true") parser.add_argument("--do-not-simplify", help="Do not simplify expressions", action="store_true") args = parser.parse_args() # Get architecture
console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.INFO) filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): execfile(filename) parser = ArgumentParser("Disassemble a binary") parser.add_argument('filename', help="File to disassemble") parser.add_argument('address', help="Starting address for disassembly engine", nargs="*") parser.add_argument('-m', '--architecture', help="architecture: " + \ ",".join(Machine.available_machine())) parser.add_argument('-f', "--followcall", action="store_true", help="Follow call instructions") parser.add_argument('-b', "--blockwatchdog", default=None, type=int, help="Maximum number of basic block to disassemble") parser.add_argument('-n', "--funcswatchdog", default=None, type=int, help="Maximum number of function to disassemble") parser.add_argument('-r', "--recurfunctions", action="store_true", help="Disassemble founded functions") parser.add_argument('-v', "--verbose", action="store_true", help="Verbose mode") parser.add_argument('-g', "--gen_ir", action="store_true", help="Compute the intermediate representation") parser.add_argument('-z', "--dis-nulstart-block", action="store_true", help="Do not disassemble NULL starting block") parser.add_argument('-l', "--dontdis-retcall", action="store_true", help="If set, disassemble only call destinations")
from argparse import ArgumentParser from pdb import pm import json from miasm2.analysis.machine import Machine from miasm2.analysis.binary import Container from miasm2.analysis.depgraph import DependencyGraph from miasm2.expression.expression import ExprMem, ExprId, ExprInt32 parser = ArgumentParser("Dependency grapher") parser.add_argument("filename", help="Binary to analyse") parser.add_argument("func_addr", help="Function address") parser.add_argument("target_addr", help="Address to start") parser.add_argument("element", nargs="+", help="Elements to track") parser.add_argument("-m", "--architecture", help="Architecture (%s)" % Machine.available_machine()) parser.add_argument("-i", "--implicit", help="Use implicit tracking", action="store_true") parser.add_argument("--unfollow-mem", help="Stop on memory statements", action="store_true") parser.add_argument("--unfollow-call", help="Stop on call statements", action="store_true") parser.add_argument("--do-not-simplify", help="Do not simplify expressions", action="store_true") parser.add_argument("--rename-args", help="Rename common arguments (@32[ESP_init] -> Arg1)", action="store_true") parser.add_argument("--json", help="Output solution in JSON", action="store_true") args = parser.parse_args()
class ActionFind(Action): """Action for actually launching function guessing""" _name_ = "find" _desc_ = "Function guesser" _args_ = [ # Mandatory (["filename"], {"help": "File to load"}), (["address"], {"help": "Address of the function under test. Allowed" \ " formats are '112233', '0x11223344', '-' for stdin " \ "and 'filename' for a file containing addresses", "nargs": "+"}), # Optional (["-a", "--architecture"], {"help": "Target architecture", "choices": Machine.available_machine()}), (["-b", "--abi"], {"help": "ABI to use", "choices": [x.__name__ for x in ABIS]}), (["-t", "--tests"], {"help": "Tests to run (default is all)", "choices": config.available_tests.keys(), "default": [], "action": "append"}), (["-v", "--verbose"], {"help": "Verbose mode (use multiple time to " \ "increase verbosity level)", "action": "count", "default": 0}), (["-i", "--timeout"], {"help": "Test timeout (in seconds)", "default": 2, "type": int}), (["-m", "--mapping-base"], {"help": "Binary mapping address", "default": "0"}), (["-j", "--jitter"], {"help": "Jitter engine (override default one)", "choices": ["gcc", "tcc", "llvm", "python", "qemu"], "default": config.jit_engine}), (["-p", "--monoproc"], {"help": "Launch tests in a single process " \ "(mainly for debug purpose)", "action": "store_true"}), (["-o", "--output-format"], {"help": "Output format", "choices": ["JSON", "human"], "default": "human"}), ] def do_test(self, addr_queue, msg_queue): """Multi-process worker for launching on functions""" # Init components tl = TestLauncher(self.args.filename, self.machine, self.abicls, self.tests, self.args.jitter, self.map_addr) # Activatate logging INFO on at least -vv if self.args.verbose > 1: tl.logger.setLevel(logging.INFO) # Main loop while True: address = addr_queue.get() if address is None: break possible_funcs = tl.run(address, timeout_seconds=self.args.timeout) msg_queue.put(MessageTaskDone(address, possible_funcs)) # Signal to master the end msg_queue.put(None) def run(self): """Launch search""" # Import multiprocessing only when required from multiprocessing import cpu_count, Queue, Process # Parse args self.map_addr = int(self.args.mapping_base, 0) if self.args.monoproc: cpu_count = lambda: 1 Process = FakeProcess # Architecture architecture = False if self.args.architecture: architecture = self.args.architecture else: with open(self.args.filename) as fdesc: architecture = ArchHeuristic(fdesc).guess() if not architecture: raise ValueError( "Unable to recognize the architecture, please specify it") if self.args.verbose > 0: print "Guessed architecture: %s" % architecture self.machine = Machine(architecture) if not self.args.address: print "No function address provided. Use 'sibyl func' to discover addresses" exit(-1) addresses = [] for address in self.args.address: if address == '-': # Use stdin addresses = [int(addr, 0) for addr in sys.stdin] continue try: addresses.append(int(address, 0)) except ValueError: # File addresses = [int(addr, 0) for addr in open(address)] if self.args.verbose > 0: print "Found %d addresses" % len(addresses) # Select ABI if self.args.abi is None: candidates = set(abicls for abicls in ABIS if architecture in abicls.arch) if not candidates: raise ValueError("No ABI for architecture %s" % architecture) if len(candidates) > 1: print "Please specify the ABI:" print "\t" + "\n\t".join(cand.__name__ for cand in candidates) exit(0) abicls = candidates.pop() else: for abicls in ABIS: if self.args.abi == abicls.__name__: break else: raise ValueError("Unknown ABI name: %s" % self.args.abi) self.abicls = abicls # Select Test set self.tests = [] for tname, tcases in config.available_tests.iteritems(): if not self.args.tests or tname in self.args.tests: self.tests += tcases if self.args.verbose > 0: print "Found %d test cases" % len(self.tests) # Prepare multiprocess cpu_c = cpu_count() addr_queue = Queue() msg_queue = Queue() processes = [] # Add tasks for address in addresses: addr_queue.put(address) # Add poison pill for _ in xrange(cpu_c): addr_queue.put(None) # Launch workers for _ in xrange(cpu_c): p = Process(target=self.do_test, args=(addr_queue, msg_queue)) processes.append(p) p.start() addr_queue.close() # Get results nb_poison = 0 results = {} # address -> possible functions while nb_poison < cpu_c: msg = msg_queue.get() # Poison pill if msg is None: nb_poison += 1 continue # Save result results[msg.address] = msg.results # Display status if needed if self.args.verbose > 0: sys.stdout.write("\r%d / %d" % (len(results), len(addresses))) sys.stdout.flush() if msg.results and self.args.output_format == "human": prefix = "" if self.args.verbose > 0: prefix = "\r" print prefix + "0x%08x : %s" % (msg.address, ",".join( msg.results)) # Clean output if needed if self.args.verbose > 0: print "" # End connexions msg_queue.close() msg_queue.join_thread() addr_queue.join_thread() for p in processes: p.join() #if not addr_queue.empty(): # raise RuntimeError("An error occured: queue is not empty") # Print final results if self.args.output_format == "JSON": # Expand results to always have the same key, and address as int print json.dumps({ "information": { "total_count": len(addresses), "test_cases": len(self.tests) }, "results": [{ "address": addr, "functions": result } for addr, result in results.iteritems()], }) elif self.args.output_format == "human" and self.args.verbose > 0: # Summarize results title = ["Address", "Candidates"] ligs = [title] ligs += [["0x%08x" % addr, ",".join(result)] for addr, result in sorted(results.iteritems(), key=lambda x: x[0]) if result] print_table(ligs, separator="| ")
class ActionFunc(Action): """Function discovering""" _name_ = "func" _desc_ = "Function discovering" _args_ = [ # Mandatory (["filename"], { "help": "File to load" }), # Optional (["-a", "--architecture"], { "help": "Target architecture", "choices": Machine.available_machine() }), (["-v", "--verbose"], { "help": "Verbose mode", "action": "store_true" }), (["-d", "--disable-heuristic"], { "help": "Disable an heuristic", "action": "append", "choices": heur_names, "default": [] }), (["-e", "--enable-heuristic"], { "help": "Enable an heuristic", "action": "append", "choices": heur_names, "default": [] }), ] def run(self): # Architecture architecture = False if self.args.architecture: architecture = self.args.architecture else: with open(self.args.filename) as fdesc: architecture = ArchHeuristic(fdesc).guess() if not architecture: raise ValueError( "Unable to recognize the architecture, please specify it") if self.args.verbose: print "Guessed architecture: %s" % architecture cont = Container.from_stream(open(self.args.filename)) machine = Machine(architecture) addr_size = machine.ira().pc.size / 4 fh = FuncHeuristic(cont, machine, self.args.filename) # Default: force only IDA if available if config.idaq64_path: fh.heuristics = [ida_funcs] # Enable / disable heuristics for name in self.args.enable_heuristic: heur = fh.name2heuristic(name) if heur not in fh.heuristics: fh.heuristics.append(heur) for name in self.args.disable_heuristic: heur = fh.name2heuristic(name) fh.heuristics.remove(heur) if self.args.verbose: print "Heuristics to run: %s" % ", ".join(fh.heuristic_names) # Launch guess fmt = "0x{:0%dx}" % addr_size for addr in fh.guess(): print fmt.format(addr)
from pdb import pm log = logging.getLogger("dis") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.INFO) filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): execfile(filename) parser = OptionParser(usage="usage: %prog [options] file address") parser.add_option('-m', "--architecture", dest="machine", metavar="MACHINE", help="architecture: " + ",".join(Machine.available_machine())) parser.add_option('-f', "--followcall", dest="followcall", action="store_true", default=False, help="follow call") parser.add_option('-b', "--blocwatchdog", dest="bw", default=None, help="address to disasemble") parser.add_option('-n', "--funcsnumwatchdog", dest="funcswd", default=None, help="max func to disasm") parser.add_option( '-r', "--recurfunctions", dest="recurfunctions", action="store_true", default=False,
log = logging.getLogger("dis") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.INFO) filename = os.environ.get("PYTHONSTARTUP") if filename and os.path.isfile(filename): execfile(filename) parser = ArgumentParser("Disassemble a binary") parser.add_argument("filename", help="File to disassemble") parser.add_argument("address", help="Starting address for disassembly engine", nargs="*") parser.add_argument("-m", "--architecture", help="architecture: " + ",".join(Machine.available_machine())) parser.add_argument("-f", "--followcall", action="store_true", help="Follow call instructions") parser.add_argument( "-b", "--blockwatchdog", default=None, type=int, help="Maximum number of basic block to disassemble" ) parser.add_argument("-n", "--funcswatchdog", default=None, type=int, help="Maximum number of function to disassemble") parser.add_argument("-r", "--recurfunctions", action="store_true", help="Disassemble founded functions") parser.add_argument("-v", "--verbose", action="store_true", help="Verbose mode") parser.add_argument("-g", "--gen_ir", action="store_true", help="Compute the intermediate representation") parser.add_argument("-z", "--dis-nulstart-block", action="store_true", help="Do not disassemble NULL starting block") parser.add_argument("-l", "--dontdis-retcall", action="store_true", help="If set, disassemble only call destinations") parser.add_argument("-s", "--simplify", action="store_true", help="Use the liveness analysis pass") parser.add_argument( "-o", "--shiftoffset", default=None, type=lambda x: int(x, 0), help="Shift input binary by an offset" ) parser.add_argument("-a", "--try-disasm-all", action="store_true", help="Try to disassemble the whole binary")