Fix glibc-fastbin-bug option of find_fake_fast (#1774)

* Fix glibc-fastbin-bug option of find_fake_fast

Using the find_fake_fast option --glibc-fastbin-bug always resulted in an error, at least on 64-bit platforms.
This was because the option caused only 4 bytes to be read for the size, but then that gets passed to unpack() which expects 8 bytes.

Closes #1773

* Address review comment

* Update arch.py

* Update pwndbg/commands/heap.py

* Fix lint

* Update arch.py

* Update arch.py

---------

Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
pull/1811/head
SlidyBat 2 years ago committed by GitHub
parent 3e8b597929
commit 1fb1b24a19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -765,7 +765,7 @@ def find_fake_fast(
candidate = search_region[i : i + size_field_width]
if len(candidate) == size_field_width:
size_field = pwndbg.gdblib.arch.unpack(candidate)
size_field = pwndbg.gdblib.arch.unpack_size(candidate, size_field_width)
size_field &= ~(allocator.malloc_align_mask)
if size_field < min_chunk_size or size_field > max_candidate_size:

@ -3,6 +3,9 @@ import sys
from typing_extensions import Literal
FMT_LITTLE_ENDIAN = {1: "B", 2: "<H", 4: "<I", 8: "<Q"}
FMT_BIG_ENDIAN = {1: "B", 2: ">H", 4: ">I", 8: ">Q"}
class Arch:
def __init__(self, arch_name: str, ptrsize: int, endian: Literal["little", "big"]) -> None:
@ -20,9 +23,8 @@ class Arch:
self.ptrmask = (1 << 8 * ptrsize) - 1
self.endian = endian
self.fmt = {(4, "little"): "<I", (4, "big"): ">I", (8, "little"): "<Q", (8, "big"): ">Q"}[
(self.ptrsize, self.endian)
]
self.fmts = FMT_LITTLE_ENDIAN if endian == "little" else FMT_BIG_ENDIAN
self.fmt = self.fmts[self.ptrsize]
if self.name == "arm" and self.endian == "big":
self.qemu = "armeb"
@ -36,3 +38,9 @@ class Arch:
def unpack(self, data: bytes) -> int:
return struct.unpack(self.fmt, data)[0]
def pack_size(self, integer: int, size: int) -> bytes:
return struct.pack(self.fmts[size], integer & self.ptrmask)
def unpack_size(self, data: bytes, size: int) -> int:
return struct.unpack(self.fmts[size], data)[0]

@ -128,4 +128,9 @@ int main(void) {
// range of the target address
setup_mem(0x100, 0x100);
break_here();
// A fastbin chunk with a size that has top 4 bytes clobbered, due to glibc
// fastbin size bug, this is still valid
setup_mem(0xAABBCCDD00000020, 0x8);
break_here();
}

@ -150,3 +150,11 @@ def test_find_fake_fast_command(start_binary):
result = gdb.execute("find_fake_fast &target_address 0x100", to_string=True)
check_no_results(result)
gdb.execute("continue")
# setup_mem(0xAABBCCDD00000020, 0x8)
result = gdb.execute("find_fake_fast &target_address", to_string=True)
check_no_results(result)
result = gdb.execute("find_fake_fast &target_address --glibc-fastbin-bug", to_string=True)
check_result(result, 0xAABBCCDD00000020)
gdb.execute("continue")

Loading…
Cancel
Save