示例#1
0
文件: disasm.py 项目: pwndbg/pwndbg
def instruction(ins):
    asm = '%-06s %s' % (ins.mnemonic, ins.op_str)
    if pwndbg.config.syntax_highlight:
        asm = syntax_highlight(asm)
    is_branch = set(ins.groups) & capstone_branch_groups

    # Highlight the current line if enabled
    if pwndbg.config.highlight_pc and ins.address == pwndbg.regs.pc:
        asm = C.highlight(asm)

    # tl;dr is a branch?
    if ins.target not in (None, ins.address + ins.size):
        sym    = pwndbg.symbol.get(ins.target) or None
        target = M.get(ins.target)
        const  = ins.target_const
        hextarget = hex(ins.target)
        hexlen    = len(hextarget)

        # If it's a constant expression, color it directly in the asm.
        if const:
            asm = '%s <%s>' % (ljust_colored(asm, 36), target)
            asm = asm.replace(hex(ins.target), sym or target)

        # It's not a constant expression, but we've calculated the target
        # address by emulation or other means (for example showing ret instruction target)
        elif sym:
            asm = '%s <%s; %s>' % (ljust_colored(asm, 36), target, sym)

        # We were able to calculate the target, but there is no symbol
        # name for it.
        else:
            asm += '<%s>' % (target)

    # not a branch
    elif ins.symbol:
        if is_branch and not ins.target:
            asm = '%s <%s>' % (asm, ins.symbol)

            # XXX: not sure when this ever happens
            asm += '<-- file a pwndbg bug for this'
        else:
            inlined_sym = asm.replace(hex(ins.symbol_addr), ins.symbol)

            # display symbol as mem text if no inline replacement was made
            mem_text = ins.symbol if inlined_sym == asm else None
            asm = '%s <%s>' % (ljust_colored(inlined_sym, 36), M.get(ins.symbol_addr, mem_text))

    # Style the instruction mnemonic if it's a branch instruction.
    if is_branch:
        asm = asm.replace(ins.mnemonic, branch(ins.mnemonic), 1)

    # If we know the conditional is taken, mark it as taken.
    if ins.condition is None:
        asm = '  ' + asm
    elif ins.condition:
        asm = on('✔ ') + asm
    else:
        asm = '  ' + asm

    return asm
示例#2
0
文件: memoize.py 项目: ysf/pwndbg
def memoize():
    pwndbg.memoize.memoize.caching = not pwndbg.memoize.memoize.caching

    status = message.off(
        'OFF (pwndbg will work slower, use only for debugging pwndbg)')
    if pwndbg.memoize.memoize.caching:
        status = message.on('ON')

    print("Caching is now %s" % status)
示例#3
0
文件: aslr.py 项目: xcode2010/ppwndbg
def aslr(state=None):
    if state:
        gdb.execute('set disable-randomization %s' % options[state],
                    from_tty=False,
                    to_string=True)

        if pwndbg.proc.alive:
            print("Change will take effect when the process restarts")

    aslr, method = pwndbg.vmmap.check_aslr()
    status = message.off('OFF')

    if aslr:
        status = message.on('ON')

    print("ASLR is %s (%s)" % (status, method))
示例#4
0
def attachp(target):
    try:
        resolved_target = int(target)
    except ValueError:
        # GDB supposedly supports device files, so let's try it here...:
        #    <disconnect3d> hey, does anyone know what does `attach <device-file>` do?
        #    <disconnect3d> is this an alias for `target extended /dev/ttyACM0` or similar?
        #    <disconnect3d> I mean, `help attach` suggests that the `attach` command supports a device file target...
        #    <simark> I had no idea
        #    <simark> what you pass to attach is passed directly to target_ops::attach
        #    <simark> so it must be very target-specific
        #    <disconnect3d> how can it be target specific if it should  attach you to a target?
        #    <disconnect3d> or do you mean osabi/arch etc?
        #    <simark> in "attach foo", foo is interpreted by the target you are connected to
        #    <simark> But all targets I can find interpret foo as a PID
        #    <simark> So it might be that old targets had some other working mode
        if _is_device(target):
            resolved_target = target

        else:
            try:
                pids = check_output(["pidof",
                                     target]).decode().rstrip("\n").split(" ")
            except FileNotFoundError:
                print(message.error("Error: did not find `pidof` command"))
                return
            except CalledProcessError:
                pids = []

            if not pids:
                print(message.error("Process %s not found" % target))
                return

            if len(pids) > 1:
                print(
                    message.warn("Found pids: %s (use `attach <pid>`)" %
                                 ", ".join(pids)))
                return

            resolved_target = int(pids[0])

    print(message.on("Attaching to %s" % resolved_target))
    try:
        gdb.execute("attach %s" % resolved_target)
    except gdb.error as e:
        print(message.error("Error: %s" % e))
示例#5
0
文件: aslr.py 项目: cebrusfs/217gdb
def aslr(state=None):
    """
    Check the current ASLR status, or turn it on/off.

    Does not take effect until the program is restarted.
    """
    if state:
        gdb.execute('set disable-randomization %s' % options[state], 
                    from_tty=False, to_string=True)

        if pwndbg.proc.alive:
            print("Change will take effect when the process restarts")

    aslr = pwndbg.vmmap.check_aslr()
    status = message.off('OFF')

    if aslr:
        status = message.on('ON')

    print("ASLR is %s" % status)
示例#6
0
def aslr(state=None):
    """
    Check the current ASLR status, or turn it on/off.

    Does not take effect until the program is restarted.
    """
    if state:
        gdb.execute('set disable-randomization %s' % options[state],
                    from_tty=False,
                    to_string=True)

        if pwndbg.proc.alive:
            print("Change will take effect when the process restarts")

    aslr = pwndbg.vmmap.check_aslr()
    status = message.off('OFF')

    if aslr:
        status = message.on('ON')

    print("ASLR is %s" % status)
示例#7
0
文件: disasm.py 项目: cebrusfs/217gdb
def instruction(ins):
    asm = '%-06s %s' % (ins.mnemonic, ins.op_str)
    if pwndbg.config.syntax_highlight:
        asm = syntax_highlight(asm)
    is_branch = set(ins.groups) & capstone_branch_groups

    # Highlight the current line if enabled
    if pwndbg.config.highlight_pc and ins.address == pwndbg.regs.pc:
        asm = C.highlight(asm)

    # tl;dr is a branch?
    if ins.target not in (None, ins.address + ins.size):
        sym    = pwndbg.symbol.get(ins.target) or None
        target = M.get(ins.target)
        const  = ins.target_const

        # Use format string instead of hex() to avoid suffix 'l' or 'L'
        hextarget = '0x%x' % ins.target
        hexlen    = len(hextarget)

        # If it's a constant expression, color it directly in the asm.
        if const:
            # TODO: Also colorize the address starts with '$' and '#'
            asm = asm.replace(hextarget, sym or target)

            if sym:
                asm = '%s <%s>' % (ljust_colored(asm, 36), target)

        # It's not a constant expression, but we've calculated the target
        # address by emulation.
        elif sym:
            asm = '%s <%s; %s>' % (ljust_colored(asm, 36), target, sym)

        # We were able to calculate the target, but there is no symbol
        # name for it.
        else:
            asm += '<%s>' % (target)

    # not a branch
    elif ins.symbol:
        if is_branch and not ins.target:
            asm = '%s <%s>' % (asm, ins.symbol)

            # XXX: not sure when this ever happens
            asm += '<-- file a pwndbg bug for this'
        else:
            asm = asm.replace(hex(ins.symbol_addr), ins.symbol)
            asm = '%s <%s>' % (ljust_colored(asm, 36), M.get(ins.symbol_addr))

    # Style the instruction mnemonic if it's a branch instruction.
    if is_branch:
        asm = asm.replace(ins.mnemonic, branch(ins.mnemonic), 1)

    # If we know the conditional is taken, mark it as taken.
    if ins.condition is None:
        asm = '  ' + asm
    elif ins.condition:
        asm = on('✔ ') + asm
    else:
        asm = '  ' + asm

    return asm
示例#8
0
文件: heap.py 项目: yy221/pwndbg
def malloc_chunk(addr, fake=False, verbose=False, simple=False):
    """Print a malloc_chunk struct's contents."""
    # points to the real start of the chunk
    cursor = int(addr)

    allocator = pwndbg.heap.current
    ptr_size = allocator.size_sz

    size_field = pwndbg.memory.u(cursor + allocator.chunk_key_offset('size'))
    real_size = size_field & ~allocator.malloc_align_mask

    headers_to_print = []  # both state (free/allocated) and flags
    fields_to_print = set()  # in addition to addr and size
    out_fields = "Addr: {}\n".format(M.get(cursor))

    if fake:
        headers_to_print.append(message.on("Fake chunk"))
        verbose = True  # print all fields for fake chunks

    if simple:
        chunk = read_chunk(cursor)

        if not headers_to_print:
            headers_to_print.append(message.hint(M.get(cursor)))

        prev_inuse, is_mmapped, non_main_arena = allocator.chunk_flags(
            int(chunk['size']))
        if prev_inuse:
            headers_to_print.append(message.hint('PREV_INUSE'))
        if is_mmapped:
            headers_to_print.append(message.hint('IS_MMAPED'))
        if non_main_arena:
            headers_to_print.append(message.hint('NON_MAIN_ARENA'))

        print(' | '.join(headers_to_print))
        for key, val in chunk.items():
            print(message.system(key) + ": 0x{:02x}".format(int(val)))
        print('')
        return

    arena = allocator.get_arena_for_chunk(cursor)
    arena_address = None
    is_top = False
    if not fake and arena:
        arena_address = arena.address
        top_chunk = arena['top']
        if cursor == top_chunk:
            headers_to_print.append(message.off("Top chunk"))
            is_top = True

    if not is_top:
        fastbins = allocator.fastbins(arena_address) or {}
        smallbins = allocator.smallbins(arena_address) or {}
        largebins = allocator.largebins(arena_address) or {}
        unsortedbin = allocator.unsortedbin(arena_address) or {}
        if allocator.has_tcache():
            tcachebins = allocator.tcachebins(None)

        if real_size in fastbins.keys() and cursor in fastbins[real_size]:
            headers_to_print.append(message.on("Free chunk (fastbins)"))
            if not verbose:
                fields_to_print.add('fd')

        elif real_size in smallbins.keys() and cursor in bin_addrs(
                smallbins[real_size], "smallbins"):
            headers_to_print.append(message.on("Free chunk (smallbins)"))
            if not verbose:
                fields_to_print.update(['fd', 'bk'])

        elif real_size >= list(
                largebins.items())[0][0] and cursor in bin_addrs(
                    largebins[(list(
                        largebins.items())[allocator.largebin_index(real_size)
                                           - 64][0])], "largebins"):
            headers_to_print.append(message.on("Free chunk (largebins)"))
            if not verbose:
                fields_to_print.update(
                    ['fd', 'bk', 'fd_nextsize', 'bk_nextsize'])

        elif cursor in bin_addrs(unsortedbin['all'], "unsortedbin"):
            headers_to_print.append(message.on("Free chunk (unsortedbin)"))
            if not verbose:
                fields_to_print.update(['fd', 'bk'])

        elif allocator.has_tcache() and real_size in tcachebins.keys(
        ) and cursor + ptr_size * 2 in bin_addrs(tcachebins[real_size],
                                                 "tcachebins"):
            headers_to_print.append(message.on("Free chunk (tcache)"))
            if not verbose:
                fields_to_print.add('fd')

        else:
            headers_to_print.append(message.hint("Allocated chunk"))

    if verbose:
        fields_to_print.update(
            ['prev_size', 'size', 'fd', 'bk', 'fd_nextsize', 'bk_nextsize'])
    else:
        out_fields += "Size: 0x{:02x}\n".format(size_field)

    prev_inuse, is_mmapped, non_main_arena = allocator.chunk_flags(size_field)
    if prev_inuse:
        headers_to_print.append(message.hint('PREV_INUSE'))
    if is_mmapped:
        headers_to_print.append(message.hint('IS_MMAPED'))
    if non_main_arena:
        headers_to_print.append(message.hint('NON_MAIN_ARENA'))

    fields_ordered = [
        'prev_size', 'size', 'fd', 'bk', 'fd_nextsize', 'bk_nextsize'
    ]
    for field_to_print in fields_ordered:
        if field_to_print in fields_to_print:
            out_fields += message.system(
                field_to_print) + ": 0x{:02x}\n".format(
                    pwndbg.memory.u(
                        cursor + allocator.chunk_key_offset(field_to_print)))

    print(' | '.join(headers_to_print) + "\n" + out_fields)
示例#9
0
    def new_malloc_chunk(addr, fake=False, verbose=False, simple=False):
        idx, start, end, rest = (lambda idx, start, end, **rest:
                                 (idx, start, end, rest))(**scope)
        scope['idx'] += 1

        if start is not None and end is not None and idx not in range(
                start, end + 1):
            return

        ## original begin
        cursor = int(addr)

        allocator = pwndbg.heap.current
        ptr_size = allocator.size_sz

        size_field = pwndbg.memory.u(cursor +
                                     allocator.chunk_key_offset('size'))
        real_size = size_field & ~allocator.malloc_align_mask

        headers_to_print = []  # both state (free/allocated) and flags
        fields_to_print = set()  # in addition to addr and size
        out_fields = "Addr: {}\n".format(M.get(cursor))

        if fake:
            headers_to_print.append(message.on("Fake chunk"))
            verbose = True  # print all fields for fake chunks

        if simple:
            chunk = read_chunk(cursor)

            if not headers_to_print:
                headers_to_print.append(message.hint(M.get(cursor)))

            prev_inuse, is_mmapped, non_main_arena = allocator.chunk_flags(
                int(chunk['size']))
            if prev_inuse:
                headers_to_print.append(message.hint('PREV_INUSE'))
            if is_mmapped:
                headers_to_print.append(message.hint('IS_MMAPED'))
            if non_main_arena:
                headers_to_print.append(message.hint('NON_MAIN_ARENA'))

            print(' | '.join(headers_to_print))
            for key, val in chunk.items():
                print(message.system(key) + ": 0x{:02x}".format(int(val)))
            print('')
            return

        arena = allocator.get_arena_for_chunk(cursor)
        arena_address = None
        is_top = False
        if not fake and arena:
            arena_address = arena.address
            top_chunk = arena['top']
            if cursor == top_chunk:
                headers_to_print.append(message.off("Top".center(9, " ")))
                is_top = True

        if not is_top:
            fastbins = allocator.fastbins(arena_address) or {}
            smallbins = allocator.smallbins(arena_address) or {}
            largebins = allocator.largebins(arena_address) or {}
            unsortedbin = allocator.unsortedbin(arena_address) or {}
            if allocator.has_tcache():
                tcachebins = allocator.tcachebins(None)

            if real_size in fastbins.keys() and cursor in fastbins[real_size]:
                headers_to_print.append(message.on("F(fast)".center(9, " ")))
                if not verbose:
                    fields_to_print.add('fd')

            elif real_size in smallbins.keys() and cursor in bin_addrs(
                    smallbins[real_size], "smallbins"):
                headers_to_print.append(message.on("F(small)".center(9, " ")))
                if not verbose:
                    fields_to_print.update(['fd', 'bk'])

            elif real_size >= list(
                    largebins.items())[0][0] and cursor in bin_addrs(
                        largebins[(list(largebins.items())[
                            allocator.largebin_index(real_size) - 64][0])],
                        "largebins"):
                headers_to_print.append(message.on("F(large)".center(9, " ")))
                if not verbose:
                    fields_to_print.update(
                        ['fd', 'bk', 'fd_nextsize', 'bk_nextsize'])

            elif cursor in bin_addrs(unsortedbin['all'], "unsortedbin"):
                headers_to_print.append(message.on("F(unsort)".center(9, " ")))
                if not verbose:
                    fields_to_print.update(['fd', 'bk'])

            elif allocator.has_tcache() and real_size in tcachebins.keys(
            ) and cursor + ptr_size * 2 in bin_addrs(tcachebins[real_size],
                                                     "tcachebins"):
                headers_to_print.append(message.on("F(tcache)".center(9, " ")))
                if not verbose:
                    fields_to_print.add('fd')

            else:
                headers_to_print.append(
                    message.hint("Allocated".center(9, " ")))

        if verbose:
            fields_to_print.update([
                'prev_size', 'size', 'fd', 'bk', 'fd_nextsize', 'bk_nextsize'
            ])
        else:
            out_fields += "Size: 0x{:02x}\n".format(size_field)

        prev_inuse, is_mmapped, non_main_arena = allocator.chunk_flags(
            size_field)
        if prev_inuse:
            headers_to_print.append(message.hint('PREV_INUSE'))
        if is_mmapped:
            headers_to_print.append(message.hint('IS_MMAPED'))
        if non_main_arena:
            headers_to_print.append(message.hint('NON_MAIN_ARENA'))

        ## original end
        if not verbose:
            def ascii_char(byte):
                if byte >= 0x20 and byte < 0x7e:
                    return chr(byte)  # Ensure we return a str
                else:
                    return "."

            content = ""
            content += "[{:03d}] ".format(idx)

            content += M.get(cursor) + f" SIZE=0x{size_field:08x}"
            data = addr + pwndbg.arch.ptrsize * 2
            content += " DATA[" + hex(data) + "]"
            if size_field >= 0x20:
                bytes_read = pwndbg.memory.read(data, 0x20, partial=True)
            else:
                bytes_read = pwndbg.memory.read(data, size, partial=True)
            content += " |" + "".join([ascii_char(c) for c in bytes_read]) + "| "
            print(content + " | ".join(headers_to_print))
        else:
            print_chunk_detail(addr, size_field)
示例#10
0
文件: heap.py 项目: sung3r/pwndbg
def heap(addr=None, verbose=False):
    """Iteratively print chunks on a heap, default to the current thread's
    active heap.
    """
    allocator = pwndbg.heap.current
    heap_region = allocator.get_heap_boundaries(addr)
    arena = allocator.get_arena_for_chunk(
        addr) if addr else allocator.get_arena()

    top_chunk = arena['top']
    ptr_size = allocator.size_sz

    # Calculate where to start printing; if an address was supplied, use that,
    # if this heap belongs to the main arena, start at the beginning of the
    # heap's mapping, otherwise, compensate for the presence of a heap_info
    # struct and possibly an arena.
    if addr:
        cursor = int(addr)
    elif arena == allocator.main_arena:
        cursor = heap_region.start
    else:
        cursor = heap_region.start + allocator.heap_info.sizeof
        if pwndbg.vmmap.find(allocator.get_heap(
                heap_region.start)['ar_ptr']) == heap_region:
            # Round up to a 2-machine-word alignment after an arena to
            # compensate for the presence of the have_fastchunks variable
            # in GLIBC versions >= 2.27.
            cursor += (allocator.malloc_state.sizeof +
                       ptr_size) & ~allocator.malloc_align_mask

    # i686 alignment heuristic
    first_chunk_size = pwndbg.arch.unpack(
        pwndbg.memory.read(cursor + ptr_size, ptr_size))
    if first_chunk_size == 0:
        cursor += ptr_size * 2

    while cursor in heap_region:
        old_cursor = cursor
        size_field = pwndbg.memory.u(cursor +
                                     allocator.chunk_key_offset('size'))
        real_size = size_field & ~allocator.malloc_align_mask

        if cursor == top_chunk:
            out = message.off("Top chunk\n")
            out += "Addr: {}\nSize: 0x{:02x}".format(M.get(cursor), size_field)
            print(out)
            break

        fastbins = allocator.fastbins(arena.address)
        smallbins = allocator.smallbins(arena.address)
        largebins = allocator.largebins(arena.address)
        unsortedbin = allocator.unsortedbin(arena.address)
        if allocator.has_tcache():
            tcachebins = allocator.tcachebins(None)

        out = "Addr: {}\nSize: 0x{:02x}\n".format(M.get(cursor), size_field)

        if real_size in fastbins.keys() and cursor in fastbins[real_size]:
            out = message.on("Free chunk (fastbins)\n") + out
            if not verbose:
                out += message.system("fd: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
        elif real_size in smallbins.keys() and cursor in bin_addrs(
                smallbins[real_size], "smallbins"):
            out = message.on("Free chunk (smallbins)\n") + out
            if not verbose:
                out += message.system("fd: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
                out += message.system("bk: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('bk')))
        elif real_size >= list(
                largebins.items())[0][0] and cursor in bin_addrs(
                    largebins[(list(
                        largebins.items())[allocator.largebin_index(real_size)
                                           - 64][0])], "largebins"):
            out = message.on("Free chunk (largebins)\n") + out
            if not verbose:
                out += message.system("fd: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
                out += message.system("bk: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('bk')))
                out += message.system("fd_nextsize: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor +
                                    allocator.chunk_key_offset('fd_nextsize')))
                out += message.system("bk_nextsize: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor +
                                    allocator.chunk_key_offset('bk_nextsize')))
        elif cursor in bin_addrs(unsortedbin['all'], "unsortedbin"):
            out = message.on("Free chunk (unsortedbin)\n") + out
            if not verbose:
                out += message.system("fd: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
                out += message.system("bk: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('bk')))
        elif allocator.has_tcache() and real_size in tcachebins.keys(
        ) and cursor + ptr_size * 2 in bin_addrs(tcachebins[real_size],
                                                 "tcachebins"):
            out = message.on("Free chunk (tcache)\n") + out
            if not verbose:
                out += message.system("fd: ") + "0x{:02x}\n".format(
                    pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
        else:
            out = message.hint("Allocated chunk\n") + out

        if verbose:
            out += message.system("fd: ") + "0x{:02x}\n".format(
                pwndbg.memory.u(cursor + allocator.chunk_key_offset('fd')))
            out += message.system("bk: ") + "0x{:02x}\n".format(
                pwndbg.memory.u(cursor + allocator.chunk_key_offset('bk')))
            out += message.system("fd_nextsize: ") + "0x{:02x}\n".format(
                pwndbg.memory.u(cursor +
                                allocator.chunk_key_offset('fd_nextsize')))
            out += message.system("bk_nextsize: ") + "0x{:02x}\n".format(
                pwndbg.memory.u(cursor +
                                allocator.chunk_key_offset('bk_nextsize')))

        print(out)
        cursor += real_size

        # Avoid an infinite loop when a chunk's size is 0.
        if cursor == old_cursor:
            break