Example #1
0
def _get_pc(dbg: DebugAdapter.DebugAdapter) -> int:
    pc_names = ['rip', 'eip', 'pc']
    for reg_name in pc_names:
        if reg_name in dbg.reg_list():
            return dbg.reg_read(reg_name)
    raise Exception('[!] No program counter name (%s) found in registers: %s' %
                    (pc_names, dbg.reg_list()))
def read_value(dbg: DebugAdapter.DebugAdapter, reg: Optional[str],
               offset: Optional[int]) -> Optional[int]:
    """Read the requested value from the debug adapter.

    If only reg is specified, gets the value of that register.
    If only offset is specified, reads a 64-bit int from memory at the address.
    If reg+offset is specified, reads a 64-bit int from memory at [reg+offset]

    Will try to rebase address if you only supply and offset and it appears to
    be within the target module.

    DebugAdapter will raise exceptions if you do something wrong.
    """
    if reg is not None and offset is None:
        return dbg.reg_read(reg)
    elif offset is not None:
        if reg is None:
            addr = _rebase_if_needed(dbg, offset)
        if reg is not None:
            addr = dbg.reg_read(reg)
            addr += offset
        #print('DBG: reading addr 0x%x+0x%x (0x%x)' % (addr, offset, addr+offset))

        data = dbg.mem_read(addr, 8)
        return struct.unpack('<Q', data)[0]
    else:
        raise Exception(
            '[!] Must specify at least one of reg or offset arguments')
def _rebase_bv(bv: BinaryView, dbg: DebugAdapter.DebugAdapter) -> BinaryView:
    """Get a rebased BinaryView for support of ASLR compatible binaries."""
    new_base = dbg.target_base()
    if core_ui_enabled() and new_base != bv.start:
        dbg.quit()
        raise Exception('[!] Can\'t do necessary rebase in GUI, try headless operation')

    new_bv = bv.rebase(new_base)
    if new_bv is None:  # None if rebasing is unecessary
        return bv
    print('[*] Rebasing bv from 0x%x to 0x%x' % (bv.start, new_base))
    new_bv.update_analysis_and_wait()  # required after rebase
    return new_bv
def get_value_at(dbg: DebugAdapter.DebugAdapter,
                 reg: Optional[str],
                 offset: Optional[int],
                 breakpoint_addr: int,
                 breakpoint_times: int = 0) -> int:
    """Run the DebugAdapter to the specified addr and read the requested value.

    If only reg is specified, gets the value of that register.
    If only offset is specified, reads a 64-bit int from memory at the address.
    If reg+offset is specified, reads a 64-bit int from memory at [reg+offset]

    Will try to rebase address if you only supply and offset and it appears to
    be within the target module.

    Raises exceptions on errors, for example if breakpoint_addr isn't hit or
    is hit fewer times than specified.
    """
    value_read = None
    times_hit = 0

    dbg.breakpoint_set(breakpoint_addr)

    while True:
        (reason, _) = dbg.go()  # second item in tuple "data" unused
        if reason == DebugAdapter.STOP_REASON.BREAKPOINT:
            stop_addr = _get_pc(dbg)
            dbg.breakpoint_clear(stop_addr)
            if times_hit < breakpoint_times:
                dbg.step_into()
                dbg.breakpoint_set(stop_addr)
                times_hit += 1
            else:
                value_read = read_value(dbg, reg, offset)
                break
        elif reason == DebugAdapter.STOP_REASON.PROCESS_EXITED:
            break
        else:
            print('[!] Unexpected stop reason: %s' % str(reason))
            break

    if value_read is None:
        if times_hit == 0:
            raise Exception('[!] Never hit requested breakpoint')
        elif times_hit < breakpoint_times:
            raise Exception(
                '[!] Only hit breakpoint %d times, requested read after %d' %
                (times_hit, breakpoint_times))
        else:
            raise Exception(
                '[!] Unexpected error: Breakpoint hit but value_read is None')

    return value_read