From 5861c6a675a79add08b54ef7ae26245b088ae61f Mon Sep 17 00:00:00 2001 From: Zach Riggle Date: Wed, 10 May 2017 18:11:25 -0500 Subject: [PATCH] Add Command.repeat property for repeated commands (#272) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Command.repeat property for repeated commands * Support repeated invocations of the "hexdump" command The output now looks like: pwndbg> hexdump $rsp 0x20 +0000 0x7fffffffdb38 30 18 60 f7 ff 7f 00 00 00 00 00 00 00 00 00 00 │0.`.│....│....│....│ +0010 0x7fffffffdb48 18 dc ff ff ff 7f 00 00 00 00 00 00 01 00 00 00 │....│....│....│....│ +0020 0x7fffffffdb58 pwndbg> +0000 0x7fffffffdb58 d0 ee 41 00 00 00 00 00 00 00 00 00 00 00 00 00 │..A.│....│....│....│ +0010 0x7fffffffdb68 23 ff 3e ed 14 92 d9 c6 60 05 42 00 00 00 00 00 │#.>.│....│`.B.│....│ +0020 0x7fffffffdb78 pwndbg> +0000 0x7fffffffdb78 10 dc ff ff ff 7f 00 00 00 00 00 00 00 00 00 00 │....│....│....│....│ +0010 0x7fffffffdb88 00 00 00 00 00 00 00 00 23 ff de 19 7c 6d 26 39 │....│....│#...│|m&9│ +0020 0x7fffffffdb98 --- pwndbg/commands/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ pwndbg/commands/hexdump.py | 11 +++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/pwndbg/commands/__init__.py b/pwndbg/commands/__init__.py index 0dfd0c74f..52e0586cf 100644 --- a/pwndbg/commands/__init__.py +++ b/pwndbg/commands/__init__.py @@ -27,6 +27,7 @@ class _Command(gdb.Command): """Generic command wrapper""" count = 0 commands = [] + history = {} def __init__(self, function, inc=True, prefix=False): super(_Command, self).__init__(function.__name__, gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION, prefix=prefix) @@ -44,11 +45,46 @@ class _Command(gdb.Command): def invoke(self, argument, from_tty): argv = self.split_args(argument) try: + self.repeat = self.check_repeated(argument, from_tty) return self(*argv) except TypeError: if debug: print(traceback.format_exc()) raise + finally: + self.repeat = False + + def check_repeated(self, argument, from_tty): + """Keep a record of all commands which come from the TTY. + + Returns: + True if this command was executed by the user just hitting "enter". + """ + # Don't care unless it's interactive use + if not from_tty: + return False + + lines = gdb.execute('show commands', from_tty=False, to_string=True) + lines = lines.splitlines() + + # No history + if not lines: + return False + + last_line = lines[-1] + number, command = last_line.split(None, 1) + number = int(number) + + # A new command was entered by the user + if number not in _Command.history: + _Command.history[number] = command + return False + + # Somehow the command is different than we got before? + if not command.endswith(argument): + return False + + return True def __call__(self, *args, **kwargs): try: diff --git a/pwndbg/commands/hexdump.py b/pwndbg/commands/hexdump.py index 188519b93..ed315f8d2 100644 --- a/pwndbg/commands/hexdump.py +++ b/pwndbg/commands/hexdump.py @@ -23,14 +23,18 @@ pwndbg.config.Parameter('hexdump-bytes', 'number of bytes printed by hexdump command') parser = argparse.ArgumentParser(description='Hexdumps data at the specified address (or at $sp)') -parser.add_argument('address', nargs='?', default='$sp', +parser.add_argument('address', nargs='?', default='$sp', help='Address to dump') -parser.add_argument('count', nargs='?', default=pwndbg.config.hexdump_bytes, +parser.add_argument('count', nargs='?', default=pwndbg.config.hexdump_bytes, help='Number of bytes to dump') @pwndbg.commands.ArgparsedCommand(parser) @pwndbg.commands.OnlyWhenRunning def hexdump(address=None, count=pwndbg.config.hexdump_bytes): + + if hexdump.repeat: + address = hexdump.last_address + address = int(address) address &= pwndbg.arch.ptrmask count = max(int(count), 0) @@ -41,9 +45,12 @@ def hexdump(address=None, count=pwndbg.config.hexdump_bytes): try: data = pwndbg.memory.read(address, count, partial=True) + hexdump.last_address = (address + count) except gdb.error as e: print(e) return for line in pwndbg.hexdump.hexdump(data, address=address, width=width): print(line) + +hexdump.last_address = 0