diff --git a/pwndbg/__init__.py b/pwndbg/__init__.py index 89c915117..6f9db901a 100644 --- a/pwndbg/__init__.py +++ b/pwndbg/__init__.py @@ -40,6 +40,7 @@ import pwndbg.commands.shell import pwndbg.commands.aslr import pwndbg.commands.misc import pwndbg.commands.next +import pwndbg.commands.dumpargs __all__ = [ 'arch', diff --git a/pwndbg/arguments.py b/pwndbg/arguments.py index 4fb212b9f..d79d66381 100644 --- a/pwndbg/arguments.py +++ b/pwndbg/arguments.py @@ -100,8 +100,6 @@ def get(instruction): else: args = [pwndbg.functions.Argument('int',0,argname(i)) for i in range(4)] - print(repr(args)) - for i,arg in enumerate(args): result.append((arg, argument(i))) diff --git a/pwndbg/commands/dumpargs.py b/pwndbg/commands/dumpargs.py new file mode 100644 index 000000000..68b1880b7 --- /dev/null +++ b/pwndbg/commands/dumpargs.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import pwndbg.commands +import pwndbg.arguments +import pwndbg.disasm + +@pwndbg.commands.Command +@pwndbg.commands.OnlyWhenRunning +def dumpargs(*a): + result = [] + + # For call instructions, attempt to resolve the target and + # determine the number of arguments. + for arg, value in pwndbg.arguments.get(pwndbg.disasm.one()): + code = False if arg.type == 'char' else True + pretty = pwndbg.chain.format(value, code=code) + result.append('%8s%-10s %s' % ('',arg.name+':', pretty)) + + print '\n'.join(result) \ No newline at end of file diff --git a/pwndbg/disasm/__init__.py b/pwndbg/disasm/__init__.py index 36d47b324..6b59f215e 100644 --- a/pwndbg/disasm/__init__.py +++ b/pwndbg/disasm/__init__.py @@ -48,8 +48,10 @@ VariableInstructionSizeMax = { 'x86-64': 16, } +smart_backward_cache = collections.defaultdict(lambda: 0) backward_cache = collections.defaultdict(lambda: 0) + def get_disassembler(pc): arch = pwndbg.arch.current d = CapstoneArch[arch] @@ -74,7 +76,8 @@ def one(address=None): if address is None: address = pwndbg.regs.pc for insn in get(address, 1): - backward_cache[insn.next] = insn.address + smart_backward_cache[insn.next] = insn.address + backward_cache[insn.address + insn.size] = insn.address return insn def fix(i): @@ -119,14 +122,22 @@ def near(address, instructions=1): insns.append(current) # Now find all of the instructions moving forward. - insn = current - while insn and len(insns) < 1+(2*instructions): - # In order to avoid annoying cycles where the current instruction - # is a branch, which evaluates to true, and jumps back a short - # number of instructions. - - insn = one(insn.next) - if insn: - insns.append(insn) + next = current.next + while len(insns) < 1+(2*instructions): + insn = one(next) + if not insn: + break + insns.append(insn) + next = insn.next + + # On a short backward jump, we may get an annoying cycle in the + # disassembly listing, because we're reading the jump target and + # have evaluated the destination. + # + # We don't want this loop to show up in the future, so force it + # to fall-through, as long as the jump destination is a small-enough + # backward jump that it also shows up in the disassembly. + if insn.address == current.address and any(i.address == next for i in insns): + next = insn.address + insn.size return insns