mirror of https://github.com/pwndbg/pwndbg.git
Adding p2p command - pointer chain search
This command can be used to search for any length of pointer chains in specified mappings. Pointer chain is set of pointers that point to one another.pull/959/head
parent
a7a554f3c4
commit
8cc218f0b8
@ -0,0 +1,120 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
import gdb
|
||||||
|
|
||||||
|
import pwndbg.arch
|
||||||
|
import pwndbg.commands
|
||||||
|
import pwndbg.config
|
||||||
|
import pwndbg.memory
|
||||||
|
import pwndbg.regs
|
||||||
|
import pwndbg.color
|
||||||
|
|
||||||
|
ts = pwndbg.commands.telescope.telescope
|
||||||
|
|
||||||
|
class AddrRange:
|
||||||
|
def __init__(self, begin, end):
|
||||||
|
self.begin = begin
|
||||||
|
self.end = end
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return (self.begin, self.end).__repr__()
|
||||||
|
|
||||||
|
def get_addrrange_any_named():
|
||||||
|
return [AddrRange(page.start, page.end) for page in pwndbg.vmmap.get()]
|
||||||
|
|
||||||
|
def guess_numbers_base(num: str):
|
||||||
|
base = 10
|
||||||
|
if num.startswith('0x'):
|
||||||
|
base = 16
|
||||||
|
elif num.startswith('0b'):
|
||||||
|
base = 2
|
||||||
|
elif num.startswith('0'):
|
||||||
|
base = 8
|
||||||
|
|
||||||
|
return base
|
||||||
|
|
||||||
|
def address_range_explicit(section):
|
||||||
|
global parser
|
||||||
|
|
||||||
|
try:
|
||||||
|
begin, end = section.split(':')
|
||||||
|
|
||||||
|
begin = int(begin, guess_numbers_base(begin))
|
||||||
|
end = int(end, guess_numbers_base(end))
|
||||||
|
|
||||||
|
return AddrRange(begin, end)
|
||||||
|
except:
|
||||||
|
parser.error('\"%s\" - Bad format of explicit address range!' \
|
||||||
|
' Expected format: \"BEGIN_ADDRESS:END_ADDRESS\"' % pwndbg.color.red(section))
|
||||||
|
|
||||||
|
def address_range(section):
|
||||||
|
global parser
|
||||||
|
|
||||||
|
if section == '*' or section == 'any':
|
||||||
|
return (0, pwndbg.arch.ptrmask)
|
||||||
|
|
||||||
|
# User can use syntax: "begin:end" to specify explicit address range instead of named page.
|
||||||
|
# TODO: handle page names that contains ':'.
|
||||||
|
if ':' in section:
|
||||||
|
return [address_range_explicit(section)]
|
||||||
|
|
||||||
|
pages = list(filter(lambda page: section in page.objfile, pwndbg.vmmap.get()))
|
||||||
|
|
||||||
|
if pages:
|
||||||
|
return [AddrRange(page.start, page.end) for page in pages]
|
||||||
|
else:
|
||||||
|
parser.error('Memory page with name \"%s\" does not exist!' % pwndbg.color.red(section))
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Pointer to pointer chain search - '
|
||||||
|
'Searches given mapping for all pointers that point to specified mapping (any chain length > 0 is valid).'
|
||||||
|
'If only one mapping is given it just looks for any pointers in that mapping.')
|
||||||
|
|
||||||
|
parser.add_argument('mapping_names', type=address_range, nargs='+', help='Mapping name ')
|
||||||
|
|
||||||
|
def maybe_points_to_ranges(ptr: int, rs: [AddrRange]):
|
||||||
|
try:
|
||||||
|
pointee = pwndbg.memory.pvoid(ptr)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for r in rs:
|
||||||
|
if pointee >= r.begin and pointee < r.end:
|
||||||
|
return pointee
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def p2p_walk(addr, ranges, current_level):
|
||||||
|
levels = len(ranges)
|
||||||
|
|
||||||
|
if current_level >= levels:
|
||||||
|
return None
|
||||||
|
|
||||||
|
maybe_addr = maybe_points_to_ranges(addr, ranges[current_level])
|
||||||
|
|
||||||
|
if maybe_addr == None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if current_level == levels-1:
|
||||||
|
return addr
|
||||||
|
|
||||||
|
return p2p_walk(maybe_addr, ranges, current_level+1)
|
||||||
|
|
||||||
|
@pwndbg.commands.ArgparsedCommand(parser)
|
||||||
|
@pwndbg.commands.OnlyWhenRunning
|
||||||
|
def p2p(mapping_names: [] = None):
|
||||||
|
|
||||||
|
if not mapping_names:
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(mapping_names) == 1:
|
||||||
|
mapping_names.append(get_addrrange_any_named())
|
||||||
|
|
||||||
|
for rng in mapping_names[0]:
|
||||||
|
for addr in range(rng.begin, rng.end):
|
||||||
|
maybe_pointer = p2p_walk(addr, mapping_names, current_level = 1)
|
||||||
|
|
||||||
|
if maybe_pointer != None:
|
||||||
|
ts(address = addr, count = 1)
|
||||||
|
|
||||||
Loading…
Reference in new issue