Пример #1
0
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)
Пример #2
0
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
Пример #3
0
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',
Пример #4
0
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
Пример #5
0
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")
Пример #6
0
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()
Пример #7
0
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="| ")
Пример #8
0
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)
Пример #9
0
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,
Пример #10
0
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")