mirror of https://github.com/pwndbg/pwndbg.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.6 KiB
Python
146 lines
4.6 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
import gdb
|
|
import gef.compat
|
|
import gef.types
|
|
|
|
PAGE_SIZE = 0x1000
|
|
MMAP_MIN_ADDR = 0x10000
|
|
|
|
def read(addr, count):
|
|
result = gdb.selected_inferior().read_memory(addr, count)
|
|
|
|
if gef.compat.python3:
|
|
result = result.tobytes()
|
|
|
|
return bytearray(result)
|
|
|
|
def readtype(gdb_type, addr):
|
|
return int(gdb.Value(addr).cast(gdb_type.pointer()).dereference())
|
|
|
|
def write(addr, data):
|
|
gdb.selected_inferior().write_memory(addr, data)
|
|
|
|
def peek(address):
|
|
try: return read(address, 1)
|
|
except: pass
|
|
return None
|
|
|
|
def poke(address):
|
|
c = peek(address)
|
|
if c is None: return False
|
|
try: write(address, c)
|
|
except: return False
|
|
return True
|
|
|
|
def byte(addr): return readtype(gef.types.uchar, addr)
|
|
def uchar(addr): return readtype(gef.types.uchar, addr)
|
|
def ushort(addr): return readtype(gef.types.ushort, addr)
|
|
def uint(addr): return readtype(gef.types.uint, addr)
|
|
|
|
def u8(addr): return readtype(gef.types.uint8_t, addr)
|
|
def u16(addr): return readtype(gef.types.uint16_t, addr)
|
|
def u32(addr): return readtype(gef.types.uint32_t, addr)
|
|
def u64(addr): return readtype(gef.types.uint64_t, addr)
|
|
|
|
def s8(addr): return readtype(gef.types.int8_t, addr)
|
|
def s16(addr): return readtype(gef.types.int16_t, addr)
|
|
def s32(addr): return readtype(gef.types.int32_t, addr)
|
|
def s64(addr): return readtype(gef.types.int64_t, addr)
|
|
|
|
def write(addr, data):
|
|
gdb.selected_inferior().write_memory(addr, data)
|
|
|
|
def poi(type, addr): return gdb.Value(addr).cast(type.pointer()).dereference()
|
|
|
|
def round_down(address, align): return address & ~(align-1)
|
|
def round_up(address, align): return (address+(align-1))&(~(align-1))
|
|
|
|
align_down = round_down
|
|
align_up = round_up
|
|
|
|
def page_align(address): return round_down(address, PAGE_SIZE)
|
|
def page_size_align(address): return round_up(address, PAGE_SIZE)
|
|
def page_offset(address): return (address & (PAGE_SIZE-1))
|
|
|
|
assert round_down(0xdeadbeef, 0x1000) == 0xdeadb000
|
|
assert round_up(0xdeadbeef, 0x1000) == 0xdeadc000
|
|
|
|
def find_upper_boundary(addr):
|
|
addr = gef.memory.page_align(int(addr))
|
|
try:
|
|
while True:
|
|
gef.memory.read(addr, 1)
|
|
addr += gef.memory.PAGE_SIZE
|
|
except gdb.MemoryError:
|
|
pass
|
|
return addr
|
|
|
|
def find_lower_boundary(addr):
|
|
addr = gef.memory.page_align(int(addr))
|
|
try:
|
|
while True:
|
|
gef.memory.read(addr, 1)
|
|
addr -= gef.memory.PAGE_SIZE
|
|
except gdb.MemoryError:
|
|
pass
|
|
return addr
|
|
|
|
class Page(object):
|
|
"""
|
|
Represents the address space and page permissions of at least
|
|
one page of memory.
|
|
"""
|
|
vaddr = 0 #: Starting virtual address
|
|
memsz = 0 #: Size of the address space, in bytes
|
|
flags = 0 #: Flags set by the ELF file, see PF_X, PF_R, PF_W
|
|
offset = 0 #: Offset into the original ELF file that the data is loaded from
|
|
objfile = '' #: Path to the ELF on disk
|
|
def __init__(self, start, size, flags, offset, objfile=''):
|
|
self.vaddr = start
|
|
self.memsz = size
|
|
self.flags = flags
|
|
self.offset = offset
|
|
self.objfile = objfile
|
|
@property
|
|
def read(self):
|
|
return bool(self.flags & 4)
|
|
@property
|
|
def write(self):
|
|
return bool(self.flags & 2)
|
|
@property
|
|
def execute(self):
|
|
return bool(self.flags & 1)
|
|
@property
|
|
def rw(self):
|
|
return self.read and self.write
|
|
@property
|
|
def rwx(self):
|
|
return self.read and self.write and self.execute
|
|
@property
|
|
def permstr(self):
|
|
flags = self.flags
|
|
return ''.join(['r' if flags & 4 else '-',
|
|
'w' if flags & 2 else '-',
|
|
'x' if flags & 1 else '-',
|
|
'p'])
|
|
def __str__(self):
|
|
width = 2 + 2*gef.types.ptrsize
|
|
fmt_string = "%#{}x %#{}x %s %8x %-6x %s"
|
|
fmt_string = fmt_string.format(width, width)
|
|
return fmt_string % (self.vaddr,
|
|
self.vaddr+self.memsz,
|
|
self.permstr,
|
|
self.memsz,
|
|
self.offset,
|
|
self.objfile or '')
|
|
def __repr__(self):
|
|
return "%s(%r)" % (self.__class__.__name__, self.__str__())
|
|
def __contains__(self, a):
|
|
return self.vaddr <= a < (self.vaddr + self.memsz)
|
|
def __eq__(self, other):
|
|
return self.vaddr == getattr(other, 'vaddr', other)
|
|
def __lt__(self, other):
|
|
return self.vaddr < getattr(other, 'vaddr', other)
|
|
def __hash__(self):
|
|
return hash((self.vaddr, self.memsz, self.flags, self.offset, self.objfile)) |