From 9146c25a77cbae9f51fe0067216ad998eabf44a2 Mon Sep 17 00:00:00 2001 From: Zach Riggle Date: Tue, 31 Mar 2015 03:26:30 -0700 Subject: [PATCH] nearpc command, auxv enhancement for arm --- pwndbg/auxv.py | 12 +++++-- pwndbg/commands/context.py | 53 ++++++------------------------ pwndbg/commands/nearpc.py | 66 ++++++++++++++++++++++++++++++++++++++ pwndbg/dt.py | 2 ++ pwndbg/elf.py | 3 ++ pwndbg/stack.py | 2 ++ pwndbg/symbol.py | 2 +- 7 files changed, 94 insertions(+), 46 deletions(-) create mode 100644 pwndbg/commands/nearpc.py diff --git a/pwndbg/auxv.py b/pwndbg/auxv.py index 802c76fb2..0799bf853 100644 --- a/pwndbg/auxv.py +++ b/pwndbg/auxv.py @@ -6,6 +6,7 @@ import pwndbg.events import pwndbg.info import pwndbg.regs import pwndbg.types +import pwndbg.arch example_info_auxv_linux = """ 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffa000 @@ -66,7 +67,6 @@ AT_CONSTANTS = { 37: 'AT_L3_CACHESHAPE', } -print(sys.modules[__name__]) sys.modules[__name__].__dict__.update({v:k for k,v in AT_CONSTANTS.items()}) @@ -176,6 +176,10 @@ def walk_stack(): end = find_stack_boundary(sp) p = gdb.Value(end).cast(pwndbg.types.ulong.pointer()) + # Because reasons? + if pwndbg.arch.current == 'arm': + p -= 1 + # So we don't walk off the end of the stack p -= 2 @@ -199,8 +203,12 @@ def walk_stack(): # This check is needed because the above loop isn't # guaranteed to actually get us to AT_NULL, just to some # consecutive NULLs. QEMU is pretty generous with NULLs. - while p.dereference() != AT_BASE: + for i in range(1024): + if p.dereference() == AT_BASE: + break p -= 2 + else: + return # If we continue to p back, we should bump into the # very end of ENVP (and perhaps ARGV if ENVP is empty). diff --git a/pwndbg/commands/context.py b/pwndbg/commands/context.py index 457253a4f..142ff9476 100644 --- a/pwndbg/commands/context.py +++ b/pwndbg/commands/context.py @@ -8,6 +8,7 @@ import pwndbg.ui import pwndbg.disasm import pwndbg.chain import pwndbg.commands.telescope +import pwndbg.commands.nearpc import pwndbg.events import pwndbg.ida @@ -46,49 +47,15 @@ def context_regs(): return result def context_code(): - pc = pwndbg.regs.pc - result = [] - result.append(pwndbg.color.blue(pwndbg.ui.banner("code"))) - instructions = pwndbg.disasm.near(pwndbg.regs.pc, 5) - - # In case $pc is in a new map we don't know about, - # this will trigger an exploratory search. - pwndbg.vmmap.find(pc) - - # Ensure screen data is always at the same spot - for i in range(11 - len(instructions)): - result.append('') - - # Find all of the symbols for the addresses - symbols = [] - for i in instructions: - symbol = pwndbg.symbol.get(i.address) - if symbol: - symbol = '<%s> ' % symbol - symbols.append(symbol) - - # Find the longest symbol name so we can adjust - if symbols: - longest_sym = max(map(len, symbols)) - else: - longest_sym = '' - - # Pad them all out - for i,s in enumerate(symbols): - symbols[i] = s.ljust(longest_sym) - - # Print out each instruction - for i,s in zip(instructions, symbols): - asm = pwndbg.disasm.color(i) - prefix = ' =>' if i.address == pc else ' ' - - pre = pwndbg.ida.Anterior(i.address) - if pre: - result.append(pwndbg.color.bold(pre)) - - line = ' '.join((prefix, s + hex(i.address), asm)) - result.append(line) - return result + banner = [pwndbg.color.blue(pwndbg.ui.banner("code"))] + result = pwndbg.commands.nearpc.nearpc() + + # If we didn't disassemble backward, try to make sure + # that the amount of screen space taken is roughly constant. + while len(result) < 11: + result.insert(0, '') + + return banner + result def context_stack(): result = [] diff --git a/pwndbg/commands/nearpc.py b/pwndbg/commands/nearpc.py new file mode 100644 index 000000000..cbe72aafa --- /dev/null +++ b/pwndbg/commands/nearpc.py @@ -0,0 +1,66 @@ +import pwndbg.regs +import pwndbg.ui +import pwndbg.symbol +import pwndbg.vmmap +import pwndbg.disasm +import pwndbg.color +import pwndbg.ida + +@pwndbg.commands.ParsedCommand +@pwndbg.commands.OnlyWhenRunning +def nearpc(pc=None, lines=None, to_string=False): + # Fix the case where we only have one argument, and + # it's a small value. + if lines is None or pc < 0x100: + lines = pc + pc = None + + if pc is None: + pc = pwndbg.regs.pc + if lines is None: + lines = 5 + + pc = int(pc) + lines = int(lines) + + result = [] + instructions = pwndbg.disasm.near(pwndbg.regs.pc, lines) + + # In case $pc is in a new map we don't know about, + # this will trigger an exploratory search. + pwndbg.vmmap.find(pc) + + # Find all of the symbols for the addresses + symbols = [] + for i in instructions: + symbol = pwndbg.symbol.get(i.address) + if symbol: + symbol = '<%s> ' % symbol + symbols.append(symbol) + + # Find the longest symbol name so we can adjust + if symbols: + longest_sym = max(map(len, symbols)) + else: + longest_sym = '' + + # Pad them all out + for i,s in enumerate(symbols): + symbols[i] = s.ljust(longest_sym) + + # Print out each instruction + for i,s in zip(instructions, symbols): + asm = pwndbg.disasm.color(i) + prefix = ' =>' if i.address == pc else ' ' + + pre = pwndbg.ida.Anterior(i.address) + if pre: + result.append(pwndbg.color.bold(pre)) + + line = ' '.join((prefix, s + hex(i.address), asm)) + result.append(line) + + if not to_string: + print('\n'.join(result)) + + return result \ No newline at end of file diff --git a/pwndbg/dt.py b/pwndbg/dt.py index 62b334284..03c0f681c 100644 --- a/pwndbg/dt.py +++ b/pwndbg/dt.py @@ -95,6 +95,8 @@ def dt(name='', addr=None, obj = None): if obj: header = "%s @ %s" % (header, hex(int(obj.address))) rv.append(header) + if t.strip_typedefs().code == gdb.TYPE_CODE_ARRAY: + return "Arrays not supported yet" if t.strip_typedefs().code != gdb.TYPE_CODE_STRUCT: t = {name: obj or gdb.Value(0).cast(t)} diff --git a/pwndbg/elf.py b/pwndbg/elf.py index e3f40a243..eb4cf3136 100644 --- a/pwndbg/elf.py +++ b/pwndbg/elf.py @@ -163,6 +163,9 @@ def get_phdrs(pointer): return x def iter_phdrs(ehdr): + if not ehdr: + return [] + phnum, phentsize, phdr = get_phdrs(int(ehdr.address)) if not phdr: diff --git a/pwndbg/stack.py b/pwndbg/stack.py index 8b3c8567b..7324b5896 100644 --- a/pwndbg/stack.py +++ b/pwndbg/stack.py @@ -44,6 +44,8 @@ def update(): page = pwndbg.memory.Page(start, stop-start, 6 if not is_executable() else 7, 0, '[stack]') stacks[thread.ptid] = page continue + elif page.objfile is None: + page.objfile = '[stack]' # If we *DO* already know about this thread, just # udpate the lower boundary. diff --git a/pwndbg/symbol.py b/pwndbg/symbol.py index 1b2fb6e7f..2b7b8b373 100644 --- a/pwndbg/symbol.py +++ b/pwndbg/symbol.py @@ -26,7 +26,7 @@ def get(address): exe = pwndbg.elf.exe() if exe: exe_map = pwndbg.vmmap.find(exe.address) - if address in exe_map: + if exe_map and address in exe_map: res = pwndbg.ida.Name(address) or pwndbg.ida.GetFuncOffset(address) return res or ''