|
|
|
|
@ -91,7 +91,15 @@ class Freelist:
|
|
|
|
|
seen: set[int] = set()
|
|
|
|
|
current_object = self.start_addr
|
|
|
|
|
while current_object:
|
|
|
|
|
addr = int(current_object)
|
|
|
|
|
try:
|
|
|
|
|
addr = int(current_object)
|
|
|
|
|
except Exception:
|
|
|
|
|
print(
|
|
|
|
|
M.warn(
|
|
|
|
|
f"Corrupted slab freelist detected at {hex(current_object)} when length is {len(seen)}"
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
break
|
|
|
|
|
yield current_object
|
|
|
|
|
current_object = pwndbg.aglib.memory.read_pointer_width(addr + self.offset)
|
|
|
|
|
if self.random:
|
|
|
|
|
@ -163,6 +171,10 @@ class SlabCache:
|
|
|
|
|
def size(self) -> int:
|
|
|
|
|
return int(self._slab_cache["size"])
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def slab_size(self) -> int:
|
|
|
|
|
return 0x1000 << self.oo_order
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def object_size(self) -> int:
|
|
|
|
|
return int(self._slab_cache["object_size"])
|
|
|
|
|
@ -250,6 +262,20 @@ class SlabCache:
|
|
|
|
|
def oo_objects(self):
|
|
|
|
|
return oo_objects(self.__oo_x)
|
|
|
|
|
|
|
|
|
|
def find_containing_slab(self, address) -> Slab | None:
|
|
|
|
|
for cpu_cache in self.cpu_caches:
|
|
|
|
|
slab = cpu_cache.active_slab
|
|
|
|
|
if slab is not None and address in slab:
|
|
|
|
|
return slab
|
|
|
|
|
for slab in cpu_cache.partial_slabs:
|
|
|
|
|
if slab is not None and address in slab:
|
|
|
|
|
return slab
|
|
|
|
|
for node_cache in self.node_caches:
|
|
|
|
|
for slab in node_cache.partial_slabs:
|
|
|
|
|
if slab is not None and address in slab:
|
|
|
|
|
return slab
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CpuCache:
|
|
|
|
|
def __init__(self, cpu_cache: pwndbg.dbg_mod.Value, slab_cache: SlabCache, cpu: int) -> None:
|
|
|
|
|
@ -275,7 +301,7 @@ class CpuCache:
|
|
|
|
|
_slab = self._cpu_cache[slab_key]
|
|
|
|
|
if not int(_slab):
|
|
|
|
|
return None
|
|
|
|
|
return Slab(_slab.dereference(), self, self.slab_cache)
|
|
|
|
|
return Slab(_slab.dereference(), self, None)
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def partial_slabs(self) -> List[Slab]:
|
|
|
|
|
@ -284,7 +310,7 @@ class CpuCache:
|
|
|
|
|
cur_slab_int = int(cur_slab)
|
|
|
|
|
while cur_slab_int:
|
|
|
|
|
_slab = cur_slab.dereference()
|
|
|
|
|
partial_slabs.append(Slab(_slab, self, self.slab_cache, is_partial=True))
|
|
|
|
|
partial_slabs.append(Slab(_slab, self, None, is_partial=True))
|
|
|
|
|
cur_slab = _slab["next"]
|
|
|
|
|
cur_slab_int = int(cur_slab)
|
|
|
|
|
return partial_slabs
|
|
|
|
|
@ -306,7 +332,7 @@ class NodeCache:
|
|
|
|
|
for slab in for_each_entry(
|
|
|
|
|
self._node_cache["partial"], f"struct {slab_struct_type()}", "slab_list"
|
|
|
|
|
):
|
|
|
|
|
ret.append(Slab(slab.dereference(), None, self.slab_cache, is_partial=True))
|
|
|
|
|
ret.append(Slab(slab.dereference(), None, self, is_partial=True))
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
@ -323,13 +349,21 @@ class Slab:
|
|
|
|
|
self,
|
|
|
|
|
slab: pwndbg.dbg_mod.Value,
|
|
|
|
|
cpu_cache: CpuCache | None,
|
|
|
|
|
slab_cache: SlabCache,
|
|
|
|
|
node_cache: NodeCache | None,
|
|
|
|
|
is_partial: bool = False,
|
|
|
|
|
) -> None:
|
|
|
|
|
self._slab = slab
|
|
|
|
|
self.cpu_cache = cpu_cache
|
|
|
|
|
self.slab_cache = slab_cache
|
|
|
|
|
self.node_cache = node_cache
|
|
|
|
|
self.is_partial = is_partial
|
|
|
|
|
self.is_cpu = False
|
|
|
|
|
self.slab_cache = None
|
|
|
|
|
if cpu_cache is not None:
|
|
|
|
|
self.is_cpu = True
|
|
|
|
|
self.slab_cache = cpu_cache.slab_cache
|
|
|
|
|
assert node_cache is None
|
|
|
|
|
if node_cache is not None:
|
|
|
|
|
self.slab_cache = node_cache.slab_cache
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def slab_address(self) -> int:
|
|
|
|
|
@ -399,6 +433,9 @@ class Slab:
|
|
|
|
|
def free_objects(self) -> Set[int]:
|
|
|
|
|
return {obj for freelist in self.freelists for obj in freelist}
|
|
|
|
|
|
|
|
|
|
def __contains__(self, addr: int):
|
|
|
|
|
return self.virt_address <= addr < self.virt_address + self.slab_cache.slab_size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_containing_slab_cache(addr: int) -> SlabCache | None:
|
|
|
|
|
"""Find the slab cache associated with the provided address."""
|
|
|
|
|
|