From 86497b14aa25e504d4440622ddfa6bce14d3696a Mon Sep 17 00:00:00 2001 From: Zach Riggle Date: Sat, 18 Apr 2015 17:59:18 -0400 Subject: [PATCH] Docs and search enhancements --- pwndbg/commands/search.py | 26 +++++++++++++ pwndbg/commands/telescope.py | 15 ++++++++ pwndbg/commands/vmmap.py | 3 ++ pwndbg/commands/windbg.py | 73 ++++++++++++++++++++++++++++++++---- pwndbg/proc.py | 1 + pwndbg/search.py | 17 +++++++-- 6 files changed, 124 insertions(+), 11 deletions(-) diff --git a/pwndbg/commands/search.py b/pwndbg/commands/search.py index 89d2c1a9b..942f2a4b0 100644 --- a/pwndbg/commands/search.py +++ b/pwndbg/commands/search.py @@ -14,10 +14,24 @@ import pwndbg.vmmap @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def search(value): + """ + Search memory for the specified value, provided + either as a pointer-width integer, or a string. + + > search 0xdeadbeef + > search "/bin/sh" + """ + hits = set() + for address in pwndbg.search.search(value): if not address: continue + if address in hits: + continue + + hits.add(address) + vmmap = pwndbg.vmmap.find(address) if vmmap: region = os.path.basename(vmmap.objfile) @@ -30,3 +44,15 @@ def search(value): addr = pwndbg.color.get(address) display = pwndbg.enhance.enhance(address) print(region,addr,display) + +@pwndbg.commands.Command +@pwndbg.commands.OnlyWhenRunning +def searchmem(value): + """ + Search memory for the specified value, provided + either as a pointer-width integer, or a string. + + > search 0xdeadbeef + > search "/bin/sh" + """ + return search(value) diff --git a/pwndbg/commands/telescope.py b/pwndbg/commands/telescope.py index 27f0e8e63..d8c847e4b 100644 --- a/pwndbg/commands/telescope.py +++ b/pwndbg/commands/telescope.py @@ -15,6 +15,10 @@ import pwndbg.typeinfo @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def telescope(address=None, count=8, to_string=False): + """ + Starting at the specified address, recursively dereference + N pointers (default 8). + """ if None not in (address, count) and int(address) < int(count): count -= address @@ -63,3 +67,14 @@ def telescope(address=None, count=8, to_string=False): print('\n'.join(result)) return result + + + +@pwndbg.commands.ParsedCommand +@pwndbg.commands.OnlyWhenRunning +def stack(*a): + """ + Starting at the specified address, recursively dereference + N pointers (default 8). + """ + telescope(*a) \ No newline at end of file diff --git a/pwndbg/commands/vmmap.py b/pwndbg/commands/vmmap.py index b471b900d..6c5c80bbc 100644 --- a/pwndbg/commands/vmmap.py +++ b/pwndbg/commands/vmmap.py @@ -12,6 +12,9 @@ import pwndbg.vmmap @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def vmmap(map=None): + """ + Print the virtal memory map + """ int_map = None str_map = None if isinstance(map, str): diff --git a/pwndbg/commands/windbg.py b/pwndbg/commands/windbg.py index 9b4cb7166..9cb2608ef 100644 --- a/pwndbg/commands/windbg.py +++ b/pwndbg/commands/windbg.py @@ -25,21 +25,37 @@ def get_type(size): @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def db(address, count=64): + """ + Starting at the specified address, dump N bytes + (default 64). + """ return dX(1, int(address), int(count)) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dw(address, count=32): + """ + Starting at the specified address, dump N words + (default 32). + """ return dX(2, int(address), int(count)) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dd(address, count=16): + """ + Starting at the specified address, dump N dwords + (default 16). + """ return dX(4, int(address), int(count)) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dq(address, count=8): + """ + Starting at the specified address, dump N qwords + (default 8). + """ return dX(8, int(address), int(count)) @@ -81,32 +97,49 @@ def enhex(size, value): @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def eb(address, *data): + """ + Write hex bytes at the specified address. + """ return eX(1, address, data) @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def ew(address, *data): + """ + Write hex words at the specified address. + """ return eX(2, address, data) @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def ed(address, *data): - """Edits DWORDs""" + """ + Write hex dwords at the specified address. + """ return eX(4, address, data) @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def eq(address, *data): + """ + Write hex qwords at the specified address. + """ return eX(8, address, data) @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def ez(address, *data): + """ + Write a string at the specified address. + """ return eX(1, address, data[0], hex=False) @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def eza(address, *data): + """ + Write a string at the specified address. + """ return ez(address, data) def eX(size, address, data, hex=True): @@ -126,32 +159,50 @@ def eX(size, address, data, hex=True): @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dds(*a): + """ + Dump pointers and symbols at the specified address. + """ return pwndbg.commands.telescope.telescope(*a) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dps(*a): + """ + Dump pointers and symbols at the specified address. + """ return pwndbg.commands.telescope.telescope(*a) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def dqs(*a): + """ + Dump pointers and symbols at the specified address. + """ return pwndbg.commands.telescope.telescope(*a) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def da(address): + """ + Dump a string at the specified address. + """ print("%x" % address, pwndbg.strings.get(address)) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def bl(): + """ + List breakpoints + """ gdb.execute('info breakpoints') @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def bd(which = '*'): + """ + Disable the breapoint with the specified index. + """ if which == '*': gdb.execute('disable breakpoints') else: @@ -160,7 +211,10 @@ def bd(which = '*'): @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning -def bd(which = '*'): +def be(which = '*'): + """ + Enable the breapoint with the specified index. + """ if which == '*': gdb.execute('enable breakpoints') else: @@ -169,6 +223,9 @@ def bd(which = '*'): @pwndbg.commands.Command @pwndbg.commands.OnlyWhenRunning def bc(which = '*'): + """ + Clear the breapoint with the specified index. + """ if which == '*': gdb.execute('delete breakpoints') else: @@ -178,16 +235,18 @@ def bc(which = '*'): @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def bp(where): - gdb.execute('break *%#x' % int(where)) - -@pwndbg.commands.ParsedCommand -@pwndbg.commands.OnlyWhenRunning -def bp(where): + """ + Set a breakpoint + """ gdb.execute('break *%#x' % int(where)) @pwndbg.commands.ParsedCommand @pwndbg.commands.OnlyWhenRunning def u(where=None, n=5): + """ + Starting at the specified address, disassemble + N instructions (default 5). + """ if where is None: where = pwndbg.regs.pc cmd = 'x/%ii %#x' % (int(n), int(where)) diff --git a/pwndbg/proc.py b/pwndbg/proc.py index b8a61e214..6b607e5d2 100644 --- a/pwndbg/proc.py +++ b/pwndbg/proc.py @@ -30,6 +30,7 @@ class module(ModuleType): return func(*a, **kw) wrapper.__name__ = func.__name__ wrapper.__module__ = func.__module__ + wrapper.__doc__ = func.__doc__ return wrapper # To prevent garbage collection diff --git a/pwndbg/search.py b/pwndbg/search.py index 896c627a0..13263885d 100644 --- a/pwndbg/search.py +++ b/pwndbg/search.py @@ -9,6 +9,7 @@ import gdb import pwndbg.memory import pwndbg.typeinfo import pwndbg.vmmap +import pwndbg.arch def search(searchfor): @@ -21,9 +22,9 @@ def search(searchfor): searchfor = int(searchfor, 16) if isinstance(searchfor, (long, int)): - if searchfor <= 0xffffffff: + if pwndbg.arch.ptrsize == 4: searchfor = struct.pack('I', searchfor) - elif searchfor <= 0xffffffffffffffff: + elif pwndbg.arch.ptrsize == 8: searchfor = struct.pack('L', searchfor) i = gdb.selected_inferior() @@ -34,11 +35,19 @@ def search(searchfor): start = vmmap.vaddr end = start + vmmap.memsz while True: + # No point in searching if we can't read the memory if not pwndbg.memory.peek(start): break + start = i.search_memory(start, end - start, searchfor) + if start is None: break - hits.append(start) + + # For some reason, search_memory will return a positive hit + # when it's unable to read memory. + if not pwndbg.memory.peek(start): + break + + yield start start += len(searchfor) - return hits