Пример #1
0
    def add_function(self, f):
        bn.log_info('[+] Adding function')
        b, i, c = 0, 0, 0
        x = len(self.bv.get_code_refs(f.start))

        for block in f.low_level_il:
            b += 1
            for inst in block:
                i += 1
                if inst.operation == bn.LowLevelILOperation.LLIL_CALL:
                    c += 1

        # naivly determine function size
        if b == 1 or i < 10:
            size = 'small'
        elif i < 100:
            size = 'medium'
        else:
            size = 'large'

        self.function_data[f.name] = {
            'start': f.start,
            'blocks': b,
            'instructions': i,
            'calls': c,
            'xrefs': x,
            'size': size
        }
Пример #2
0
	def port_symbols(self, i):
		if self.role == None:
			return

		entry = self.match_model.entries[i]
		target_index = self.role
		source_index = 1 if target_index == 0 else 0

		source_name = entry["name{}".format(source_index + 1)]
		target_address = entry["address{}".format(target_index + 1)]

		old_sym = self.bv.get_symbol_at(target_address)

		target_name = None
		if old_sym:
			target_name = old_sym.name
		target_text = target_name if target_name else "<unnamed>"

		if not source_name:
			bn.log_warn("Port symbols: {} @ {:x} has no source name, skipping".format(target_text, target_address))
			return

		if old_sym and not old_sym.auto:
			bn.log_warn("Port symbols: {} @ {:x} is already named, skipping".format(target_text, target_address))
			return

		bn.log_info("Port symbols: {} @ {:x} -> {}".format(target_text, target_address, source_name))
		new_sym = bn.Symbol(bn.SymbolType.FunctionSymbol, target_address, source_name)
		self.bv.define_user_symbol(new_sym)
Пример #3
0
def rename_all_functions(bv):
    init_cache()

    for function in bv.functions:
        if function.name.startswith("0x"):
            log_info("performing 4byte lookup for '{}'".format(function.name))
            try:
                # sig = "0x" + function.name[1:].strip()
                sig = function.name
                sigs = lookup_hash(sig)
                if len(sigs) >= 1:
                    new_name, comment = format_comment(sigs)
                    function.name = new_name

                    # imm = int(sig, 16)
                    # hash_value = "#{:0=8x}".format(imm)
                    # reset_symbol(bv, imm, hash_value, new_name)
                    if function.comment:
                        function.comment += "\n------\n"
                    function.comment += comment
                log_info(
                    "found {} text sigs for hash {} renamed function to {}".
                    format(len(sigs), sig, function.name))
            except AssertionError:
                raise
            except Exception as e:
                log_error(
                    "4byte lookup failed for function '{}' reason ({}): {}".
                    format(function.name, type(e), e))

    save_4byte_cache()
    return 0
Пример #4
0
    def save_single_function_hash(self,
                                  bv,
                                  search_index,
                                  function,
                                  write_meta=True):
        """
      Save the hash of a given function into a given search index.
    """

        # TODO: detect if we are opening database instead of binary
        exec_id = self.get_exec_id(bv.file.filename)
        h1, h2 = self.extract_flowgraph_hash(function)

        if h1 and h2:
            search_index.add_function(h1, h2, exec_id, function.start)
            bn.log_info(
                '[+] Added function <{:x}:0x{:x} {:x}-{:x}> to search index.'.
                format(exec_id, function.start, h1, h2))
            self.metadata.add(exec_id, function.start, bv.file.filename,
                              function.name)
            if write_meta:
                self.metadata.__save__()
        else:
            bn.log_info(
                '[-] Did not add function <{:x}:0x{:x}> to search index.'.
                format(exec_id, function.start))
Пример #5
0
  def save_hash(self, bv, current_function):
    """
      Save hash of current function into search index.
    """
    if not self.sim_hash_location:
      self.init_db()

    # Supported platform check
    if bv.platform.name not in supported_arch:
      bn.log_error('[!] Right now this plugin supports only the following architectures: ' + str(supported_arch))
      return -1

    h1, h2 = self.extract_flowgraph_hash(current_function)

    if os.path.isfile(self.sim_hash_location):
      create_index = False
    else:
      create_index = True
    
    search_index = fss.SimHashSearchIndex(self.sim_hash_location, create_index, 28)
    # TODO: detect if we are opening database instead of binary
    exec_id = self.get_exec_id(bv.file.filename)
    search_index.add_function(h1, h2, exec_id, current_function.start)
    bn.log_info('[+] Added function <{:x}:0x{:x} {:x}-{:x}> to search index.'.format(exec_id, current_function.start, h1, h2))
    
    self.metadata.add(exec_id, current_function.start, bv.file.filename, current_function.name)
 def avoid_address(self, bv, addr):
     if(addr == self.start or addr == self.end):
         show_message_box("Afl-Unicorn", "Start or End address cannot be avoided !",
                          MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.WarningIcon)
         return
     self.avoid = addr
     try:
         blocks = bv.get_basic_blocks_at(addr)
         for block in blocks:
             if(addr == self.avoid and addr in self.avoid_addresses):
                 block.function.set_auto_instr_highlight(
                     self.avoid, HighlightStandardColor.NoHighlightColor)
                 self.avoid_addresses = [
                     x for x in self.avoid_addresses if x != addr]
                 self.avoid = addr
             else:
                 block.function.set_auto_instr_highlight(
                     addr, HighlightStandardColor.RedHighlightColor)
                 if addr not in self.avoid_addresses:
                     self.avoid_addresses.append(addr)
                 self.avoid = addr
                 binja.log_info("Avoid address: 0x{0:0x}".format(addr))
     except:
         show_message_box("Afl-Unicorn", "Error please open git issue !",
                          MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon)
Пример #7
0
def dumpBlocks(bv, output):
    module = blocks_pb2.module()
    for (func_idx, func) in enumerate(bv.functions):
        pbFunc = module.fuc.add()
        pbFunc.va = func.start
        binja.log_info("Function {0}: {1}".format(func_idx, func.start))
        for (blk_idx, block) in enumerate(func):
            blk_start = None
            pbBB = pbFunc.bb.add()
            pbBB.va = block.start
            # can't get the basic block size for now
            pbBB.parent = pbFunc.va
            block_start = block.start
            binja.log_info("\tBasic Block {0:x}: {1:x}".format(
                blk_idx, block_start))
            insn_cur = block_start
            if not block.can_exit:
                pbBB.type = 0x20  # ninja potentially non-return type
                binja.log_info("\t bb 0x%x can exit" % pbBB.va)

            for insn in block:
                instruction = pbBB.instructions.add()
                instruction.va = insn_cur
                binja.log_info("\t\t{0:x}".format(insn_cur))
                insn_cur += insn[1]
            for (successor_idx, out_edge) in enumerate(block.outgoing_edges):
                print(out_edge)
                binja.log_info("\t\tsuccessor {0:x}: {1:x}".format(
                    successor_idx, out_edge.target.start))
                child = pbBB.child.add()
                child.va = out_edge.target.start
    f = open(output, "wb")
    f.write(module.SerializeToString())
    f.close()
Пример #8
0
def addr2line(executable, offset):
    """Returns the line of source like "<file>:<line #>:<function_name>"

    Returns "ERROR: str(exception)" or "?" on failure."""
    addr2line_invocation = "addr2line -e %s -a 0x%x -f" % (executable, offset)
    child = subprocess.Popen(addr2line_invocation.split(),
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    out, err = child.communicate()
    try:
        if not isinstance(out, str):
            out = out.decode()
        output_lines = out.split("\n")
        #output_address = output_lines[0]  # "0x00025ff4"
        function_name = output_lines[1].strip(
        )  # e.g. "png_get_current_pass_number"
        source_line = output_lines[2].strip(
        )  # e.g. "/home/wintermute/targets/libpng-1.6.36/pngtrans.c:861"
    except Exception as e:
        log_warn("[!] Exception encountered in addr2line: %s" % str(e))
        log_info("    stdout: %s" % out)
        log_info("    stderr: %s" % err)
        return "ERROR: %s" % str(e)
    if source_line.startswith("??") or source_line.endswith("?"):
        return "?"
    return ":".join((source_line, function_name))
Пример #9
0
def run_plugin(bv, function):
    # Supported platform check
    if bv.platform.name not in supported_arch:
        log_error(
            '[x] Right now this plugin supports only the following platforms: '
            + str(supported_arch))
        return -1

    r = Report(bv)
    r.load_template('main', 'functions_report.html')
    r.load_template('function_row', 'function_table_row.tpl')
    r.load_template('function_pane', 'function_pane.tpl')
    r.load_template('function_call_row', 'function_call_row.tpl')
    r.load_template('function_xref_row', 'function_xref_row.tpl')
    r.load_template('fingerprint', 'fingerprint_image.tpl')

    bn.log_info('[*] Scanning functions...')
    for function in bv.functions:
        if function.symbol.type != bn.SymbolType.ImportedFunctionSymbol:
            r.add_function(function)

    save_filename = bn.interaction.get_save_filename_input(
        "Save report to ...")

    if save_filename:
        with open(save_filename, "w+") as fh:
            fh.write(r.generate_html())
Пример #10
0
def do_discover_caller_names(bv, func):
    param_name = interaction.get_text_line_input(
        "Please enter the name of the parameter that contains the method name",
        "Parameter name")
    # Docs says the above function returns a string with a link to the Python 3
    # docs (e.g. a Py3 str), but it actually returns a bytes-object under Py3
    param_name = param_name.decode("utf-8")
    func_params = [
        param for param in func.parameter_vars if param.name == param_name
    ]
    force = False

    if len(func_params) != 1:
        log_error("Unable to determine method name argument")
        return

    for name, func in discover_names(func, func_params).items():
        # Skip if named correctly
        if func.symbol.name == name:
            continue

        # Skip if we're not forcing and the user has named this already
        if not func.symbol.auto and not force:
            log_debug("Skipped %r due to no auto symbol" % name)
            continue

        log_info("Renaming %r to %r" % (func, name))
        func.view.define_auto_symbol(
            Symbol(func.symbol.type, func.symbol.address, short_name=name))
 def _start_unicorn_emulation(self, harness_file, json_file, dumped_memory, input_file):
     try:
         output = subprocess.Popen(['python', harness_file.result, '-d', json_file.result,
                                    dumped_memory.result, input_file.result], stdout=subprocess.PIPE).communicate()[0]
         binja.log_info(output)
     except TypeError:
         show_message_box("Afl-Unicorn", "Error please open git issue !",
                          MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon)
Пример #12
0
    def test_helper(should_be_found, found, msg_type):
        nonlocal success

        for i in should_be_found:
            if i not in found:
                log_error(f"'{i}' was not detected as a {msg_type}.")
                success = False
            else:
                log_info(f"'{i}' successfully detected as a {msg_type}.")
Пример #13
0
 def shutdown(self):
     """ shutdown() => None
     Cleanly shutdown the XML-RPC service.
     Example: binaryninja shutdown
     """
     self.server.server_close()
     log_info("[+] XMLRPC server stopped")
     setattr(self.server, "shutdown", True)
     return 0
Пример #14
0
def show_message(message):
    """ Originally popped up a message box. Now just logs to console """
    global main_window
    init_gui()
    log_info(message)
    if (hasattr(main_window, 'messagebox')):
        main_window.messagebox.update(message)
    else:
        main_window.messagebox = MessageBox()
Пример #15
0
  def init_db(self):
    # Fetch location
    location = bn.interaction.get_open_filename_input("Load SimHash database", ".simhash")
    if not location:
      bn.log_info("[*] Using default location for SimHash database: {}".format(default_sim_hash_location))
      location = default_sim_hash_location

    # setup metadata class
    self.sim_hash_location = location
    self.metadata = Metadata(location+ '.meta')
Пример #16
0
 def load_signature(self, filepath):
     if os.path.isfile(filepath):
         try:
             self.rules.append(yara.compile(filepath))
             log_info("Loaded YARA rule: {}".format(filepath))
         except yara.SyntaxError:
             log_error(
                 "Syntax error compiling YARA rule: {}".format(filepath))
     else:
         log_error("YARA rule filepath is invalid: {}".format(filepath))
 def cancel_task(self):
     global process
     if(process):
         result = show_message_box("Afl-Unicorn", "Do you want to cancel afl-unicorn fuzzing ?",
                          MessageBoxButtonSet.YesNoButtonSet, MessageBoxIcon.WarningIcon)
         if result == 1:
             binja.log_info("Cancel process {0}".format(
                 os.getpgid(process.pid)))
             os.killpg(os.getpgid(process.pid), signal.SIGTERM)
             process = None
 def _start_afl_fuzz(self, afl_binary, inputs, outputs, harness_file, json_file, dumped_memory):
     try:
         global process
         process = subprocess.Popen([afl_binary.result, '-U', '-m', 'none', '-i', inputs.result, '-o', outputs.result,
                                     '--', 'python', harness_file.result, json_file.result, dumped_memory.result, '@@'],  preexec_fn=os.setsid)
         binja.log_info('Process {0} started'.format(
             os.getpgid(process.pid)))
     except:
         show_message_box("Afl-Unicorn", "Error please open git issue !",
                          MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon)
Пример #19
0
  def find_all_hashes(self, bv, current_function):
    search_index = self.init_index(bv, current_function)
    report = ""
    for function in bv.functions:
      h1, h2 = self.extract_flowgraph_hash(function)
      if h1 and h2:
        report = self.find_function_hash(bv, h1, h2, function.start, search_index, report)
      else:
        bn.log_info('[-] Did not search for function 0x{:x}.'.format(function.start))

    bn.interaction.show_markdown_report('Function Similarity Search Report', report)
Пример #20
0
 def find_hash(self, bv, current_function):
   """
     Find functions similar to the current one.
   """
   search_index = self.init_index(bv, current_function)
   h1, h2 = self.extract_flowgraph_hash(current_function)
   if h1 and h2:
     report = self.find_function_hash(bv, h1, h2, current_function.start, search_index, "")
     bn.interaction.show_markdown_report('Function Similarity Search Report', report)
   else:
     bn.log_info('[-] Did not search for function <{:x}:0x{:x}> to search index.'.format(self.get_exec_id(bv.file.filename), function.start))
Пример #21
0
    def run(self):
        for function in self.functions:
            for block in function.low_level_il:
                for instruction in block:
                    if instruction.operation == bn.LowLevelILOperation.LLIL_SYSCALL:
                        possible_value = instruction.get_reg_value(
                            self.registers[0])

                        if (possible_value.is_constant):
                            syscall = self.db[str(
                                possible_value.value
                            )]  # Get corresponding syscall
                        else:
                            syscall = {'name': 'Unknown Syscall', 'args': []}
                        bn.log_info(
                            "[*] Found syscall {} in function {} at 0x{:x}".
                            format(syscall['name'], function.name,
                                   instruction.address))

                        args = []
                        # construct arguments
                        for i, arg in enumerate(syscall['args']):
                            possible_arg_value = instruction.get_reg_value(
                                self.registers[i + 1])

                            if (possible_arg_value.is_constant):
                                arg_value = possible_arg_value.value
                            else:
                                s = '{}: {}'.format(arg['name'], 'Unknown')
                                args.append(s)
                                continue

                            if arg['type'] == 'value':
                                value = arg_value
                            if arg['type'] == 'pointer':
                                value = '*{}'.format(hex(arg_value))
                            if arg['type'] == 'string':
                                s = self.bv.read(
                                    arg_value,
                                    self.bv.find_next_data(arg_value, "\x00") -
                                    arg_value)
                                if s:
                                    value = '<{}>'.format(repr(s))
                                else:
                                    value = '[{}]'.format(hex(arg_value))

                            s = '{}: {}'.format(arg['name'], value)
                            args.append(s)

                        comment = '{syscall_name}({arguments})'.format(
                            syscall_name=syscall['name'],
                            arguments=", ".join(args))
                        function.set_comment(instruction.address, comment)
                        args = []
Пример #22
0
 def color(self, visited):
     with open(visited, 'r') as f:
         for line in f:
             index = line.find(':') + 1
             addr = line[index:].split()[0]
             log_info(addr)
             try:
                 self.color_at(int(addr, 16))
             except ValueError:
                 # if thrown by int()
                 pass
Пример #23
0
def run_vsa(thread, view, function):
    cfg = function.session_data.cfg
    log_info(str(cfg))
    cfg_function = cfg.get_function_at(function.start -
                                       1 if function.start != 0 else 0)
    log_info(str(cfg_function))
    hash_id = cfg_function.hash_id

    thread.task.progress = '[VSA] Analyzing...'

    to_process = [
        cfg.get_basic_block_at(function.start -
                               1 if function.start != 0 else 0)
    ]

    seen = set()

    i = 3

    while to_process:
        thread.task.progress = '[VSA] Processing Basic Blocks{}'.format('.' *
                                                                        i)
        i += (i + 1) % 4
        basic_block = to_process.pop()
        seen.add(basic_block)
        end = basic_block.end.pc
        outgoing_edges = basic_block.outgoing_basic_blocks(hash_id)

        if outgoing_edges is not None:
            for outgoing_edge in outgoing_edges:
                if (view.get_function_at(outgoing_edge.start.pc + 1) is None
                        and outgoing_edge not in seen):
                    to_process.append(outgoing_edge)

                dest_branches = function.get_indirect_branches_at(end)

                current_branches = {dest.dest_addr for dest in dest_branches}

                if outgoing_edge.start.pc not in current_branches:
                    current_branches.add(outgoing_edge.start.pc)
                    function.set_user_indirect_branches(
                        end, [(view.arch, dest) for dest in current_branches
                              if (not basic_block.ends_with_jumpi
                                  or outgoing_edge.start.pc != end + 1)])

    if function.start == 0:
        max_function_size, _ = Settings().get_integer_with_scope(
            'analysis.limits.maxFunctionSize',
            scope=SettingsScope.SettingsDefaultScope)
        if max_function_size:
            view.max_function_size_for_analysis = max_function_size
        else:
            view.max_function_size_for_analysis = 65536
Пример #24
0
 def check_path_substitution(self, path):
     """Checks for files using path substitutions, going from longest to shortest original path"""
     sorted_original_paths = sorted(self.path_substitutions.keys(),
                                    key=lambda k: len(k),
                                    reverse=True)
     candidate_matches = []
     for candidate_path in sorted_original_paths:
         if candidate_path in path:
             substitute_pattern = self.path_substitutions[candidate_path]
             substitute_path = path.replace(candidate_path,
                                            substitute_pattern)
             substitute_path = os.path.expanduser(substitute_path)
             candidate_matches.append(substitute_path)
             if os.path.exists(substitute_path):
                 return substitute_path
     # Only log_warn once per file, and only if the user has tried to add translations
     if path not in self.failed_substitutions:
         if len(self.path_substitutions) > 0:
             log_warn("Failed to find substitution for %s" % path)
             log_info("Current substitution paths:")
             for orig_path, sub_path in self.path_substitutions.items():
                 log_info("  %s => %s" % (orig_path, sub_path))
             log_info("Matching patterns' failed substitute paths:")
             for candidate in candidate_matches:
                 log_info("  %s" % candidate)
         self.failed_substitutions.append(path)
     return ""
def plugin_fs_finder(bv):
    # Find format strings
    fs_finder = FormatStringFinder(
        bv,
        Settings().get_bool(setting_1_should_highlight_variable_trace))
    fs_finder.find_format_strings()

    # Get results and print them in the logs view and in a markdown report
    md = fs_finder.get_results_string()
    log_info(md)

    md = '<span style="color:red">(use the \'Log View\' for clickable addresses)</span>\n' + md
    title = f"FormatStringFinder results for {os.path.basename(bv.file.filename)}"
    bv.show_markdown_report(title=title, contents=md)
Пример #26
0
def explain_llil(bv, llil_instruction):
    """ Returns the explanation string from explanations_en.json, formatted with the preprocessed LLIL instruction """
    if llil_instruction is None:
        return
    if llil_instruction.operation.name in explanations:
        try:
            # Get the string from the JSON and format it
            return explanations[llil_instruction.operation.name].format(llil=preprocess(bv, llil_instruction))
        except AttributeError:
            # Usually a bad format string. Shouldn't show up unless something truly weird happens.
            log_error("Bad Format String in binja_explain_instruction")
            traceback.print_exc()
            return llil_instruction.operation.name
    # If there's anything in the LLIL that doesn't have an explanation, yell about it in the logs
    log_info("binja_explain_instruction doen't understand " + llil_instruction.operation.name + " yet")
    return llil_instruction.operation.name
Пример #27
0
def run_plugin(bv, function):
    # Supported platform check
    if bv.platform.name not in supported_arch:
        log_error(
            '[x] Right now this plugin supports only the following platforms: '
            + str(supported_arch))
        return -1

    r = Report(bv)
    r.load_template('functions_report.html')

    bn.log_info('[*] Scanning functions...')
    for function in bv.functions:
        if function.symbol.type != bn.SymbolType.ImportedFunctionSymbol:
            r.add_function(function)

    bn.interaction.show_html_report('Functions report', r.generate_html(),
                                    'Not available')
Пример #28
0
    def load_signatures(self, directories):
        rule_files = []

        for directory in directories:
            if not os.path.isdir(directory) and directory != "":
                log_error(
                    "YARA rule directory is invalid: {}".format(directory))
            else:
                for f in os.listdir(directory):
                    if f.lower().endswith((".yar", ".yara")):
                        rule_files.append(directory + os.sep + f)

        for f in rule_files:
            try:
                self.rules.append(yara.compile(f))
                log_info("Loaded YARA rule: {}".format(f))
            except yara.SyntaxError:
                log_error("Syntax error compiling YARA rule: {}".format(f))
Пример #29
0
def unret(il: MediumLevelILInstruction):
    global bb_cache
    bb_cache = {}

    function = il.function.source_function
    # Step 1: find the return
    ret_addr = il.address
    log_info(repr(il))
    # Step 2: calculate the address to jump to
    current_esp = function.get_reg_value_at(ret_addr, 'esp')
    log_info(repr(current_esp))
    current_esp = current_esp.offset
    next_jump_value = function.get_stack_contents_at(ret_addr, current_esp, 4)
    if next_jump_value.type == RegisterValueType.ConstantValue:
        next_jump_addr = next_jump_value.value
    else:
        print("Return value isn't constant")
        function.reanalyze()
        return

    # Step 3: Identify the start
    print("Step 3")
    ret_il_ssa = il.ssa_form
    mmlil = il.function
    jump_variable_ssa = ret_il_ssa.dest.src
    jump_il = mmlil[mmlil.get_ssa_var_definition(jump_variable_ssa)]
    while jump_il.src.operation != MediumLevelILOperation.MLIL_CONST:
        new_var_ssa = jump_il.src.left.ssa_form.src
        jump_il = mmlil[mmlil.get_ssa_var_definition(new_var_ssa)]

    # Step 4: Patch the binary to jump
    print("Step 4")
    patch_addr = jump_il.address
    view = function.view

    patch_value = view.arch.assemble(f'jmp 0x{next_jump_addr:x}', patch_addr)

    if (ret_addr - patch_addr) < len(patch_value):
        print("Not enough space", hex(patch_addr), len(patch_value))
        return

    view.write(patch_addr, patch_value)

    return next_jump_addr
Пример #30
0
    def sync(self, off, added, removed):
        """ Sync(off, added, removed) => None
        Synchronize debug info with gef. This is an internal function. It is
        not recommended using it from the command line.
        """
        global g_current_instruction

        off = int(off, 0)
        pc = self.base + off
        if DEBUG:
            log_info("[*] current_pc=%#x , old_pc=%#x" %
                     (pc, g_current_instruction))

        # unhighlight the _current_instruction
        if g_current_instruction > 0:
            hl(self.view, g_current_instruction, HL_NO_COLOR)
        hl(self.view, pc, HL_CUR_INSN_COLOR)

        # update the _current_instruction
        g_current_instruction = pc

        dbg("pre-gdb-add-breakpoints: %s" % (added, ))
        dbg("pre-gdb-del-breakpoints: %s" % (removed, ))
        dbg("pre-binja-breakpoints: %s" % (g_breakpoints))

        bn_added = [
            x - self.base for x in g_breakpoints if x not in self.old_bps
        ]
        bn_removed = [
            x - self.base for x in self.old_bps if x not in g_breakpoints
        ]

        for bp in added:
            add_gef_breakpoint(self.view, self.base + bp)

        for bp in removed:
            delete_gef_breakpoint(self.view, self.base + bp)

        self.old_bps = copy.deepcopy(g_breakpoints)

        dbg("post-gdb-add-breakpoints: %s" % (bn_added, ))
        dbg("post-gdb-del-breakpoints: %s" % (bn_removed, ))
        dbg("post-binja-breakpoints: %s" % (g_breakpoints, ))
        return [bn_added, bn_removed]
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

import sys
import binaryninja as binja

if len(sys.argv) > 1:
	target = sys.argv[1]

bv = binja.BinaryViewType.get_view_of_file(target)
binja.log_to_stdout(True)
binja.log_info("-------- %s --------" % target)
binja.log_info("START: 0x%x" % bv.start)
binja.log_info("ENTRY: 0x%x" % bv.entry_point)
binja.log_info("ARCH: %s" % bv.arch.name)
binja.log_info("\n-------- Function List --------")

""" print all the functions, their basic blocks, and their il instructions """
for func in bv.functions:
	binja.log_info(repr(func))
	for block in func.low_level_il:
		binja.log_info("\t{0}".format(block))

		for insn in block:
			binja.log_info("\t\t{0}".format(insn))