Beispiel #1
0
def _async_change_current_state(bv, address):
    global _running
    if not __check_executor():
        return

    state = executor.fringe.get_deferred_by_address(address)
    if state is None:
        log_alert("no such deferred state")
        return

    def f(tb):
        global _running
        disable_widgets()

        executor.set_current_state(state)
        sync_ui(bv, delta=False)

        enable_widgets()
        _running = False

    if not _running:
        _running = True
        background_task = TaskInBackground(bv,
                                           "seninja: changing current state",
                                           f)
        background_task.start()
Beispiel #2
0
def _async_start_se(bv, address):
    if globs.executor is not None:
        log_alert("seninja is already running")
        return False

    def f(tb):
        try:
            globs.executor = SymbolicExecutor(bv, address)
        except SENinjaError as e:
            sys.stderr.write(e.message + "\n")
            globs._running = False
            return

        globs.dfs_searcher = searcher.DFSSearcher(globs.executor)
        globs.bfs_searcher = searcher.BFSSearcher(globs.executor)
        globs._running = False

    if not globs._running:
        globs._running = True
        background_task = TaskInBackground(
            bv, "seninja: starting symbolic execution", f)
        background_task.start()
        background_task.join()

        if not __check_executor():
            # something wrong
            return

        initialize_ui()
        sync_ui(bv)
        enable_widgets()
Beispiel #3
0
def _async_run_bfs_searcher(bv):
    if not __check_executor():
        return

    if not globs.bfs_searcher.ready_to_run():
        log_alert("no target set for searcher")
        return

    def f(tb):
        def callback(s):
            tb.progress = "seninja: running BFS @ %s" % hex(s.get_ip())
            if globs._stop:
                globs._stop = False
                return False
            return True

        globs.bfs_searcher.run(callback)

        enable_widgets()
        sync_ui(bv, globs.executor._last_error == None)
        globs._running = False

    if not globs._running:
        disable_widgets()
        globs._running = True
        background_task = TaskInBackground(bv, "seninja: running BFS", f)
        background_task.start()
Beispiel #4
0
def get_debugger_argument(bv):
    """ Pops up a window that lets the user set the debugger arguments. Implemented
    using the native Binja GUI, so we don't have the option of showing a command history"""
    mode = ChoiceField("Mode", choices)
    text = TextLineField("")

    get_form_input([mode, SeparatorField(), text], "Set Run Arguments")

    if mode.result is None:
        mode = 'raw'
    else:
        mode = mode.choices[mode.result]
    text = str(text.result).strip()

    if mode == 'raw':
        return text
    try:
        if mode == 'hex':
            return text.decode('hex')
        if mode == 'b64':
            return b64decode(text)
        if mode == 'py2':
            return eval(text)
    except:
        log_alert("Failed to decode input")
        return ""
Beispiel #5
0
def _async_run_dfs_searcher_findall(bv):
    if not __check_executor():
        return
    if not globs.dfs_searcher.ready_to_run():
        log_alert("no target set for searcher")
        return

    timeout = globs.executor.bncache.get_setting("exploration_timeout")
    timeout = int(timeout)

    def f(tb):
        start = time.time()

        def callback(s):
            tb.progress = "seninja: running DFS @ %s" % hex(s.get_ip())
            if timeout > 0 and time.time() - start > timeout:
                # Timeout elapsed
                print("[!] Timeout elapsed (%d sec)" % timeout)
                return False
            if globs._stop:
                globs._stop = False
                return False
            return True

        globs.dfs_searcher.run(step_callback=callback, findall=True)

        enable_widgets()
        sync_ui(bv, globs.executor._last_error == None)
        globs._running = False

    if not globs._running:
        disable_widgets()
        globs._running = True
        background_task = TaskInBackground(bv, "seninja: running DFS", f)
        background_task.start()
Beispiel #6
0
def _async_start_se(bv, address):
    global _running
    if executor is not None:
        log_alert("seninja is already running")
        return False

    def f(tb):
        global executor, _running
        try:
            executor = SymbolicExecutor(bv, address)
        except Exception as e:
            print("!ERROR!")
            print(traceback.format_exc())
            _running = False
            return

        initialize_ui()
        sync_ui(bv)
        enable_widgets()
        _running = False

    if not _running:
        _running = True
        background_task = TaskInBackground(
            bv, "seninja: starting symbolic execution", f)
        background_task.start()
Beispiel #7
0
def _async_merge_states(bv, address):
    # merge all states at address and put them in current state. Current state must be at address
    if not __check_executor():
        return

    if globs.executor.state.get_ip() != address:
        log_alert("current state is not at this address")
        return

    to_be_merged = globs.executor.fringe.get_all_deferred_by_address(address)
    if to_be_merged is None:
        log_alert("no deferred state at this address")
        return

    def f(tb):
        disable_widgets()
        tot = len(to_be_merged)
        i = 0
        for s in to_be_merged:
            globs.executor.state.merge(s)
            i += 1
            tb.progress = "seninja: merging states %d/%d" % (i, tot)

        sync_ui(bv)
        enable_widgets()
        globs._running = False

    if not globs._running:
        globs._running = True
        background_task = TaskInBackground(bv, "seninja: merging states", f)
        background_task.start()
Beispiel #8
0
def start_se(bv, address):
    if globs.executor is not None:
        log_alert("seninja is already running")
        return False
    globs.executor = SymbolicExecutor(bv, address)
    globs.dfs_searcher = searcher.DFSSearcher(globs.executor)
    globs.bfs_searcher = searcher.BFSSearcher(globs.executor)
 def create_bookmark(self):
     if not bookmarks:
         return
     bookmarks.create_bookmark(self.bv, self.bv.offset)
     try:
         with open(self.default_bookmarks_file, "w") as bookmarks_file:
             pickle.dump(self.bv.file.session_data['bookmarks'],
                         bookmarks_file)
     except:
         bn.log_alert("Error Saving Bookmarks")
Beispiel #10
0
def find_constructor(bv):
    constructor_list = [(c.short_name, c.address) for c in bv.symbols.values()
                        if re.match(r'([A-Za-z0-9_]+)\:\:\1', c.short_name)]

    if not len(constructor_list):
        log_alert("No constructors found!")

    constructor = get_choice_input('Choose a constructor', 'Constructors:',
                                   [x[0] for x in constructor_list])

    if constructor is not None:
        return bv.get_function_at(constructor_list[constructor][1])

    return None
Beispiel #11
0
def change_current_state(address_or_state):
    # take only the first one at the given address. TODO
    if not __check_executor():
        return

    if not isinstance(address_or_state, State):
        state = executor.fringe.get_deferred_by_address(address_or_state)
    else:
        state = address_or_state
    if state is None:
        log_alert("no such deferred state")
        return

    executor.set_current_state(state)
Beispiel #12
0
 def decode(self, encoded):
     """ Takes the input from the text box and decodes it using the parameter
     set in the combobox """
     mode = self._encodings[self._decoder.currentIndex()]
     if mode == 'raw':
         return str(encoded)
     try:
         if mode == 'hex':
             return encoded.decode('hex')
         if mode == 'b64':
             return b64decode(encoded)
         if mode == 'py2':
             return eval(encoded)
     except:
         log_alert("Failed to decode input")
         return None
Beispiel #13
0
def _async_merge_states(bv, address):
    # merge all states at address and put them in current state. Current state must be at address
    if not __check_executor():
        return

    if globs.executor.state.get_ip() != address:
        log_alert("current state is not at this address")
        return

    to_be_merged_all = globs.executor.fringe.get_all_deferred_by_address(
        address)
    if to_be_merged_all is None:
        log_alert("no deferred state at this address")
        return

    mergeable, not_mergeable = globs.executor.extract_mergeable_with_current_state(
        to_be_merged_all)
    if len(not_mergeable) > 0:
        print(
            "WARNING: %d states was not merged since they deviate from the current state after executing the current instruction"
            % len(not_mergeable))
        globs.executor.fringe._deferred[address] = not_mergeable

    if len(mergeable) == 0:
        return
    to_be_merged = mergeable

    def f(tb):
        disable_widgets()
        tot = len(to_be_merged)
        i = 0
        for s in to_be_merged:
            globs.executor.state.merge(s)
            i += 1
            tb.progress = "seninja: merging states %d/%d" % (i, tot)

        globs.executor.delete_comment_for_address(address)
        sync_ui(bv)
        enable_widgets()
        globs._running = False

    if not globs._running:
        globs._running = True
        background_task = TaskInBackground(bv, "seninja: merging states", f)
        background_task.start()
Beispiel #14
0
def navigate_to_virtual_function(bv, addr):
    constructor = find_constructor(bv)

    if constructor is None:
        return

    vtable = find_vtable(bv, constructor.low_level_il)

    if vtable is None:
        log_alert("Couldn't find vtable for {}".format(
            constructor.symbol.full_name))
        return

    function_pointer = find_function_offset(vtable, bv, addr)

    if function_pointer is None:
        log_alert("Couldn't find vtable offset for this call!")
        return

    bv.file.navigate(bv.file.view, function_pointer)
Beispiel #15
0
def _async_change_current_state(bv, address):
    if not __check_executor():
        return

    states = globs.executor.fringe.get_list_deferred_by_address(address)
    if len(states) == 0:
        log_alert("no such deferred state")
        return
    if len(states) == 1:
        state = globs.executor.fringe.get_deferred_by_address(address)
    else:
        state_idx = get_choice_input("Select state", "states",
                                     list(map(str, states)))
        state = globs.executor.fringe.get_deferred_by_address(
            address, state_idx)

    disable_widgets()
    globs.executor.delete_comment_for_address(address)
    globs.executor.set_current_state(state)
    sync_ui(bv, delta=False)
    enable_widgets()
Beispiel #16
0
def enable_dynamics(bv):
    """ Does first time setup for everything. See show_message calls for more explanation.
    Not sure how well this handles being called twice... """
    global main_window, reg_prefix, reg_width
    if (bv.arch.name == 'x86_64'):
        pass
    elif (bv.arch.name == 'x86'):
        reg_width = 32
        reg_prefix = 'e'
    else:
        log_alert("Architecture not supported!")  # Maybe msp430 someday?
        return

    show_message("Syncing with Voltron")
    if not sync(bv):
        show_message("Could not Sync with Voltron, spawning debugger terminal")
        terminal_wrapper(bv)
        for _ in range(
                5):  # Give up if the sync doesn't work after five seconds
            if (sync(bv)):
                break
            sleep(1)
    show_message("Attempting to set breakpoint at main")
    funcs = [f for f in filter(lambda b: b.name == 'main', bv.functions)]
    if (len(funcs) != 0):
        set_breakpoint(bv, funcs[0].start)
        navigate_to_address(bv, funcs[0].start)
    else:
        log_alert("No main function found, so no breakpoints were set")
    show_message("Placing windows")
    # Set the binary view the toolbar should pass to everything it calls
    set_bv(bv)
    show_register_window(bv)
    show_memory_window(bv)
    show_traceback_window(bv)
    if ('gdb' in debugger):
        show_terminal_window(bv)
        # Tell GDB to hand off io from the binary to our pseudoterminal
        set_tty(bv, main_window.term_window.tty)
    main_window.messagebox.hide()
Beispiel #17
0
def update_registers(registers, derefs):
    """ Updates the value and dereference string for each register in the OrderedDict
    passed in the registers parameter. """
    global main_window
    if main_window is not None:
        dereferences = OrderedDict()
        if (len(registers.keys()) == 0):
            log_alert(
                "Got a response from Voltron, but no registers. The process has probably exited."
            )
            return
        # Update registers in order, build an OrderedDict of derefs so the order
        # for those is preserved too.
        for reg in reglist:
            try:
                main_window.regwindow.update_single_register(
                    reg, registers[reg])
                dereferences[reg] = derefs[reg]
            except KeyError:
                log_error("Voltron did not return a register called " + reg)
        main_window.regwindow.update_derefs(dereferences)
        main_window.regwindow.highlight_dirty()
Beispiel #18
0
def _async_start_se(bv, address):
    if globs.executor is not None:
        log_alert("seninja is already running")
        return False

    def f(tb):
        globs.executor = SymbolicExecutor(bv, address)

        globs.dfs_searcher = searcher.DFSSearcher(globs.executor)
        globs.bfs_searcher = searcher.BFSSearcher(globs.executor)
        globs._running = False

    if not globs._running:
        globs._running = True
        background_task = TaskInBackground(
            bv, "seninja: starting symbolic execution", f)
        background_task.start()
        background_task.join()

        initialize_ui()
        sync_ui(bv)
        enable_widgets()
Beispiel #19
0
def _async_toggle_state_history(bv):
    if not __check_executor():
        return

    if globs.executor.state is None:
        return

    if globs.executor.bncache.get_setting("save_state_history") == "false":
        log_alert(
            "State history is not saved. This can be changed in settings")
        return

    if len(globs.highlighted_state_history) > 0:
        # Remove highlight
        ui_reset_state_history_highlight()

    else:
        # Set highlight
        for insn in globs.executor.state.insn_history:
            globs.highlighted_state_history.append(insn)
            func = globs.executor.bncache.get_function(insn)
            func.set_auto_instr_highlight(insn, HIGHLIGHTED_HISTORY_COLOR)
Beispiel #20
0
def start_se(bv, address):
    global executor
    if executor is not None:
        log_alert("seninja is already running")
        return False
    executor = SymbolicExecutor(bv, address)
Beispiel #21
0
def update_wrapper(wrapped, bv):
    global executing_on_stack, stack_bv, lowest_stack
    """ Runs each time a button on the toolbar is pushed. Updates the live displays of program information """
    # Call wrapped function
    wrapped(bv)
    # Handle Register Updates
    reg, derefs = get_registers(
        bv)  # derefs will have the error message if something goes wrong
    try:
        update_registers(reg, derefs)
    except AttributeError:  # reg was None
        if (
                derefs == 'Target busy'
        ):  # Probably living in kernel-land, which could be for a number of reasons.
            # We make the hopeful assumption that the reason is the program is waiting for user input.
            main_window.term_window.bring_to_front()
            log_info(
                "The target was busy, preventing us from retrieving the register state. It may be waiting for input from you."
            )
        elif (derefs == 'No such target'):
            # Usually happens when the inferior process has exited
            log_alert(
                "Couldn't get register state. The process may not be running.")
        else:
            # Maybe you didn't run the binary yet?
            log_alert(
                "Couldn't get register state. Please consult the log for more information"
            )
        # If something went wrong with the last update, we register a callback that will get run
        # the next time we have a sucessful sync. We partially apply the arguments on the callback
        # so we don't lose our reference to the binary view. See docstring on signal_sync_done for more
        register_sync_callback(partial(signal_sync_done, bv),
                               should_delete=True)
        return
    # Handle Memory Updates
    procname = filename.split(
        "/")[-1] if filename is not None else bv.file.filename.split(
            "/")[-1].replace(".bndb", "")
    # Iterate through the processes on the system to find the right memory map
    for proc in psutil.process_iter():
        if proc.name() == procname:  # Found debugged process
            maps = proc.memory_maps(grouped=False)
            for m in maps:
                # Update Stack
                if (m.path.strip("[]") == 'stack'):
                    addr = m.addr.split("-")
                    high = int(addr[1], 16)
                    sp, bp, ip = reg[reg_prefix +
                                     'sp'], reg[reg_prefix +
                                                'bp'], reg[reg_prefix + 'ip']
                    # Lock out the top of the memory to an even multiple of 32 so we don't
                    # get confusing column-wise shifts in the display
                    memtop = min([sp, lowest_stack])
                    memtop = memtop if (memtop %
                                        32 == 0) else (memtop +
                                                       (32 - memtop % 32) - 32)
                    lowest_stack = memtop
                    mem = get_memory(bv, memtop, high - memtop)
                    if mem is None:
                        log_error("No memory returned!")
                        return
                    # Display memory from the base of the stack (high addresses)
                    # to the stack pointer (low addresses)
                    main_window.hexv.update_display('stack', memtop, mem)
                    main_window.hexv.highlight_stack_pointer(sp,
                                                             width=reg_width /
                                                             8)
                    main_window.hexv.highlight_base_pointer(bp,
                                                            width=reg_width /
                                                            8)

                    # If the instruction pointer is on the stack, highlight it in the memory viewer
                    # and try to display it in the Binary Ninja window.
                    if (ip > memtop and ip <= high):
                        main_window.hexv.highlight_instr_pointer(ip)
                        if not executing_on_stack:
                            executing_on_stack = True
                            # Ideally we'd like to get the stack view inline using something like
                            # stack_bv = BinaryViewType.get_view_of_file('/dev/null'),
                            # but that doesn't actually work because Binary Ninja really only supports
                            # getting active binary views via callbacks, for now.
                            if stack_bv is not None:
                                # because of the way .write is implemented, this works if we jump to the stack
                                # exactly one time and stay there. If we go to the stack, leave, and come back,
                                # we end up creating multiple overlapping segments, which will probably break things.
                                stack_bv.write(memtop, mem)
                                stack_bv.add_function(
                                    ip, plat=bv.arch.standalone_platform)
                                print(stack_bv)
                    else:
                        executing_on_stack = False

                    # Update BSS
                    try:
                        bss = bv.sections['.bss']
                        bssmem = get_memory(bv, bss.start, bss.length)
                        main_window.hexv.update_display(
                            'bss', bss.start, bssmem)
                    except KeyError:
                        log_info('Binary has no bss section')

                    # Repaint the viewer once (much faster than the 8 times we used to do)
                    main_window.hexv.redraw()

                    # Update traceback
                    main_window.tb_window.update_frames(get_backtrace(bv))

                    # Update return address
                    try:
                        ret = calculate_return_addr_pos(sp, bp, ip, bv)
                        ret_add_offset = (ret - memtop) if (
                            ret is not None) else (bp - memtop +
                                                   (reg_width / 8))
                        main_window.hexv.highlight_retn_addr(
                            (ret) if (ret is not None) else
                            (bp + (reg_width / 8)),
                            width=reg_width / 8)
                        retrieved = mem[ret_add_offset:ret_add_offset +
                                        (reg_width / 8)][::-1].encode('hex')
                        if (len(retrieved) > 0):
                            ret_add = int(retrieved, 16)
                            main_window.tb_window.update_ret_address(ret_add)
                    except ValueError:
                        log_error(
                            "Tried to find the return address before the stack was set up. Carry on."
                        )
                    break
            break
Beispiel #22
0
def __check_executor():
    if globs.executor is None:
        log_alert("seninja not running")
        return False
    return True
 def visit_LLIL_NORET(self, expr):
     log_alert("VM Halted.")