Ptmalloc
BINMAPSIZE = 4
module-attribute
¶
HEAP_MAX_SIZE: int = None
module-attribute
¶
IS_MMAPPED = 2
module-attribute
¶
NBINS = 128
module-attribute
¶
NFASTBINS = 10
module-attribute
¶
NONCONTIGUOUS_BIT = 2
module-attribute
¶
NON_MAIN_ARENA = 4
module-attribute
¶
NSMALLBINS = 64
module-attribute
¶
PREV_INUSE = 1
module-attribute
¶
SIZE_BITS = PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA
module-attribute
¶
TCACHE_MAX_BINS = 64
module-attribute
¶
TheType = TypeVar('TheType', pwndbg.dbg_mod.Type, typing.Type[pwndbg.aglib.heap.structs.CStruct2GDB])
module-attribute
¶
TheValue = TypeVar('TheValue', pwndbg.dbg_mod.Value, pwndbg.aglib.heap.structs.CStruct2GDB)
module-attribute
¶
Arena
¶
__slots__ = ('_gdbValue', 'address', '_is_main_arena', '_top', '_active_heap', '_heaps', '_mutex', '_flags', '_non_contiguous', '_have_fastchunks', '_fastbinsY', '_bins', '_binmap', '_next', '_next_free', '_system_mem')
class-attribute
instance-attribute
¶
active_heap: Heap
property
¶
address = int(self._gdbValue.address)
instance-attribute
¶
binmap: List[int]
property
¶
bins: List[int]
property
¶
fastbinsY: List[int]
property
¶
flags: int | None
property
¶
have_fastchunks: int | None
property
¶
heaps
property
¶
is_main_arena: bool
property
¶
mutex: int | None
property
¶
next: int | None
property
¶
next_free: int | None
property
¶
non_contiguous: bool | None
property
¶
system_mem: int | None
property
¶
top: int | None
property
¶
__init__(addr)
¶
__str__()
¶
fastbins()
¶
Bin
¶
BinType
¶
Bases: str
, Enum
FAST = 'fastbins'
class-attribute
instance-attribute
¶
LARGE = 'largebins'
class-attribute
instance-attribute
¶
NOT_IN_BIN = 'not_in_bin'
class-attribute
instance-attribute
¶
SMALL = 'smallbins'
class-attribute
instance-attribute
¶
TCACHE = 'tcachebins'
class-attribute
instance-attribute
¶
UNSORTED = 'unsortedbin'
class-attribute
instance-attribute
¶
valid_fields()
¶
Bins
¶
Chunk
¶
__slots__ = ('_gdbValue', 'address', '_prev_size', '_size', '_real_size', '_flags', '_non_main_arena', '_is_mmapped', '_prev_inuse', '_fd', '_bk', '_fd_nextsize', '_bk_nextsize', '_heap', '_arena', '_is_top_chunk')
class-attribute
instance-attribute
¶
address = int(self._gdbValue.address)
instance-attribute
¶
arena: Arena | None
property
¶
bk
property
¶
bk_nextsize
property
¶
fd
property
¶
fd_nextsize
property
¶
flags: Dict[str, bool] | None
property
¶
heap: Heap
property
¶
is_mmapped: bool | None
property
¶
is_top_chunk
property
¶
non_main_arena: bool | None
property
¶
prev_inuse: bool | None
property
¶
prev_size: int | None
property
¶
real_size: int | None
property
¶
size: int | None
property
¶
__contains__(addr)
¶
This allow us to avoid extra constructions like 'if start_addr <= ptr < end_addr', etc.
__init__(addr, heap=None, arena=None)
¶
__match_renamed_field(field)
¶
next_chunk()
¶
ChunkField
¶
Bases: int
, Enum
DebugSymsHeap
¶
Bases: GlibcMemoryAllocator[Type, Value]
can_be_resolved = GlibcMemoryAllocator.libc_has_debug_syms
class-attribute
instance-attribute
¶
global_max_fast: int | None
property
¶
heap_info: pwndbg.dbg_mod.Type | None
property
¶
main_arena: Arena | None
property
¶
mallinfo: pwndbg.dbg_mod.Type | None
property
¶
malloc_chunk: pwndbg.dbg_mod.Type | None
property
¶
malloc_par: pwndbg.dbg_mod.Type | None
property
¶
malloc_state: pwndbg.dbg_mod.Type | None
property
¶
mp: pwndbg.dbg_mod.Value | None
property
¶
tcache_entry: pwndbg.dbg_mod.Type | None
property
¶
tcache_perthread_struct: pwndbg.dbg_mod.Type | None
property
¶
thread_arena: Arena | None
property
¶
thread_cache: pwndbg.dbg_mod.Value | None
property
¶
Locate a thread's tcache struct. If it doesn't have one, use the main thread's tcache.
get_heap(addr)
¶
Find & read the heap_info struct belonging to the chunk at 'addr'.
get_sbrk_heap_region()
¶
Return a Page object representing the sbrk heap region. Ensure the region's start address is aligned to SIZE_SZ * 2, which compensates for the presence of GLIBC_TUNABLES.
get_tcache(tcache_addr=None)
¶
has_tcache()
¶
is_initialized()
¶
GlibcMemoryAllocator
¶
Bases: MemoryAllocator
, Generic[TheType, TheValue]
arenas: Tuple[Arena, ...]
property
¶
Return a tuple of all current arenas.
global_max_fast: int | None
property
¶
heap_info: TheType | None
property
¶
largebin_reverse_lookup_32 = (512, 576, 640, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 10752, 12288, 16384, 20480, 24576, 28672, 32768, 36864, 40960, 65536, 98304, 131072, 163840, 262144, 524288)
class-attribute
instance-attribute
¶
largebin_reverse_lookup_32_big = (1008, 1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 2944, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 10752, 12288, 16384, 20480, 24576, 28672, 32768, 36864, 40960, 65536, 98304, 131072, 163840, 262144, 524288)
class-attribute
instance-attribute
¶
largebin_reverse_lookup_64 = (1024, 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 10752, 12288, 16384, 20480, 24576, 28672, 32768, 36864, 40960, 65536, 98304, 131072, 163840, 262144, 524288)
class-attribute
instance-attribute
¶
main_arena: Arena | None
property
¶
mallinfo: TheType | None
property
¶
malloc_align_mask: int
property
¶
Corresponds to MALLOC_ALIGN_MASK in glibc malloc.c
malloc_alignment: int
property
¶
Corresponds to MALLOC_ALIGNMENT in glibc malloc.c
malloc_chunk: TheType | None
property
¶
malloc_par: TheType | None
property
¶
malloc_state: TheType | None
property
¶
min_chunk_size: int
property
¶
Corresponds to MIN_CHUNK_SIZE in glibc malloc.c
minsize: int
property
¶
Corresponds to MINSIZE in glibc malloc.c
mp: TheValue | None
property
¶
multithreaded: bool
property
¶
Is malloc operating within a multithreaded environment.
size_sz: int
property
¶
Corresponds to SIZE_SZ in glibc malloc.c
tcache_entry: TheType | None
property
¶
tcache_next_offset: int
property
¶
tcache_perthread_struct: TheType | None
property
¶
thread_arena: Arena | None
property
¶
thread_cache: TheValue | None
property
¶
__init__()
¶
bin_at(index, arena_addr=None)
¶
Modeled after glibc's bin_at function - so starts indexing from 1 https://bazaar.launchpad.net/~ubuntu-branches/ubuntu/trusty/eglibc/trusty-security/view/head:/malloc/malloc.c#L1394
bin_at(1) returns the unsorted bin
Bin 1 - Unsorted BiN Bin 2 to 63 - Smallbins Bin 64 to 126 - Largebins
Returns: tuple(chain_from_bin_fd, chain_from_bin_bk, is_chain_corrupted) or None
can_be_resolved()
¶
check_chain_corrupted(chain_fd, chain_bk)
¶
Checks if the doubly linked list (of a {unsorted, small, large} bin) defined by chain_fd, chain_bk is corrupted.
Even if the chains do not cover the whole bin, they still are expected to be of the same length.
Returns True if the bin is certainly corrupted, otherwise False.
chunk_flags(size)
¶
chunk_key_offset(key)
¶
Find the index of a field in the malloc_chunk struct.
64bit example
prev_size == 0 size == 8 fd == 16 bk == 24 ...
fastbin_index(size)
¶
fastbins(arena_addr=None)
¶
Returns: chain or None
get_bins(bin_type, addr=None)
¶
get_heap(addr)
¶
get_region(addr)
¶
Find the memory map containing 'addr'.
get_sbrk_heap_region()
¶
get_tcache(tcache_addr=None)
¶
has_tcache()
¶
is_initialized()
¶
is_statically_linked()
¶
largebin_index(sz)
¶
Pick the appropriate largebin_index_ function for this architecture.
largebin_index_32(sz)
¶
Modeled on the GLIBC malloc largebin_index_32 macro.
largebin_index_32_big(sz)
¶
Modeled on the GLIBC malloc largebin_index_32_big macro.
largebin_index_64(sz)
¶
Modeled on the GLIBC malloc largebin_index_64 macro.
largebin_reverse_lookup(index)
¶
Pick the appropriate largebin_reverse_lookup_ function for this architecture.
largebin_size_range_from_index(index)
¶
largebins(arena_addr=None)
¶
libc_has_debug_syms()
¶
The struct malloc_chunk
comes from debugging symbols and it will not be there for statically linked binaries
smallbins(arena_addr=None)
¶
tcachebins(tcache_addr=None)
¶
Returns: tuple(chain, count) or None
unsortedbin(arena_addr=None)
¶
Heap
¶
__slots__ = ('_gdbValue', 'arena', '_memory_region', 'start', 'end', '_prev', 'first_chunk')
class-attribute
instance-attribute
¶
arena = main_arena if arena is None else arena
instance-attribute
¶
end: int = self._memory_region.end
instance-attribute
¶
first_chunk = Chunk(self.start)
instance-attribute
¶
prev
property
¶
start: int = self._memory_region.start
instance-attribute
¶
__contains__(addr)
¶
__init__(addr, arena=None)
¶
Build a Heap object given an address on that heap. Heap regions are treated differently depending on their arena: 1) main_arena - uses the sbrk heap 2) non-main arena - heap starts after its heap_info struct (and possibly an arena) 3) non-contiguous main_arena - just a memory region 4) no arena - for fake/mmapped chunks
__iter__()
¶
__str__()
¶
HeuristicHeap
¶
Bases: GlibcMemoryAllocator[Type['pwndbg.aglib.heap.structs.CStruct2GDB'], 'pwndbg.aglib.heap.structs.CStruct2GDB']
global_max_fast: int
property
¶
heap_info: Type['pwndbg.aglib.heap.structs.HeapInfo'] | None
property
¶
main_arena: Arena | None
property
¶
mallinfo: Type['pwndbg.aglib.heap.structs.CStruct2GDB'] | None
property
¶
malloc_chunk: Type['pwndbg.aglib.heap.structs.MallocChunk'] | None
property
¶
malloc_par: Type['pwndbg.aglib.heap.structs.MallocPar'] | None
property
¶
malloc_state: Type['pwndbg.aglib.heap.structs.MallocState'] | None
property
¶
mp: 'pwndbg.aglib.heap.structs.CStruct2GDB'
property
¶
struct_module: types.ModuleType | None
property
¶
tcache_entry: Type['pwndbg.aglib.heap.structs.TcacheEntry'] | None
property
¶
tcache_perthread_struct: Type['pwndbg.aglib.heap.structs.TcachePerthreadStruct'] | None
property
¶
thread_arena: Arena | None
property
¶
thread_cache: 'pwndbg.aglib.heap.structs.TcachePerthreadStruct' | None
property
¶
Locate a thread's tcache struct. We try to find its address in Thread Local Storage (TLS) first, and if that fails, we guess it's at the first chunk of the heap.
__init__()
¶
brute_force_thread_local_variable_near_tls_base(tls_address, validator)
¶
Brute force the thread-local variable near the TLS base address that can pass the validator.
brute_force_tls_reference_in_got_section(tls_address, validator)
¶
Brute force the TLS-reference in the .got section to that can pass the validator.
can_be_resolved()
¶
get_heap(addr)
¶
Find & read the heap_info struct belonging to the chunk at 'addr'.
get_sbrk_heap_region()
¶
Return a Page object representing the sbrk heap region. Ensure the region's start address is aligned to SIZE_SZ * 2, which compensates for the presence of GLIBC_TUNABLES. This heuristic version requires some sanity checks and may raise SymbolUnresolvableError if malloc's mp_
struct can't be resolved.
get_tcache(tcache_addr=None)
¶
has_tcache()
¶
is_initialized()
¶
prompt_for_brute_force_thread_arena_permission()
¶
Check if the user wants to brute force the thread_arena's value.
prompt_for_brute_force_thread_cache_permission()
¶
Check if the user wants to brute force the tcache's value.
prompt_for_tls_address()
¶
Check if we can determine the TLS address and return it.
fetch_chunk_metadata(address, include_only_fields=None)
¶
heap_for_ptr(ptr)
¶
Round a pointer to a chunk down to find its corresponding heap_info struct, the pointer must point inside a heap which does not belong to the main arena.