I participated to 0ctf but only had time to play for
the reversing challenge
trace (write-up coming up soon) during the competition
I did this challenge only for fun after the CTF was over so I do not know the flag, and since I found it interesting, I decided to write a quick write-up.
And kudos to all teams who solved it !
The vulnerable file is here
Pretty stripped down file, very small (which seemed weird for a statically linked file). Stack canary and PIE are not on, but NX is.
The binary is really small, does not do much either, so the vulnerability is quite easy to find and trigger.
At 0x08048174, We have a
read(socket, buffer, 52) where buffer can only
contain 32 bytes, so we have a classic stack overflow. A part of the challenge
is however due to the fact that our controlled part is quite limited
(i.e. 52-32=20 bytes=5 DWORD).
In addition to not having a lot of gadgets (the source was written in pure assembly), no libc, etc. 0ctf organizers added that
notice: This service is protected by a sandbox, you can only read the flag at /home/warmup/flag
Meaning: we cannot simply write
/bin/sh somewhere in memory, set
eax to 11
and simply use a gadget to set
edx to value loaded from the
stack. We have to go all the way to open, read, write back the value of the flag
This lead to a much funkier way to exploit.
The objective here seems pretty straight forward. We need to :
/tmp/flagin a predictable and writable location ( anywhere in the
.datasection will do just fine).
- Forge a
- Forge a
sys_read(fd, another_writeable_location, 50)gadget
- Forge a
sys_write(socket, another_writeable_location, 50)
And it is done! In theory it seems pretty easy, but it took me a few hours (never underestimate a challenge ☺).
What the binary provides us with are gadgets to read and write:
Where the arguments are read from the limited stack we control.
However, we do not have an
sys_open gadget, but since we can control
from the stack, all we need is to find a way to set
My original intention was to force a call to
sys_read from our socket, and
send 5 bytes of junk data so that the syscall can return with the right value in
eax. Unfortunately, we do not have enough space in our stack to chain correctly our
read arguments, then jump into it and finally jump back to our next gadget ☹ .
After quite some time, I realized that
warmup starts by initializing an alarm
for 10 seconds (which when SIGALARM is received, will kill the
Nevertheless, this could be valuable to us, because RTFM:
alarm() returns the number of seconds remaining until any previously scheduled alarm was due to be delivered, or zero if there was no previously scheduled alarm.
That means that if we jump a second time into the gadget @0x0804810D (i.e. call
alarm() a second time),
eax will be populated with whatever time is left
before SIGALRM is issued!
alarm() can take any integer as argument, our syscall will not
return as an error! So by sleeping 5 seconds,
sys_alarm will return with
NR_sys_open (5), and we can use the stack to populate the other
registers required for
Again, because of our limited space in the stack, we need to trigger the
vulnerability multiple times. To do, we have to perform only one operation, then
return to the original function (
0x0804815A), and let the control flow repeat
again until it re-hit our vulnerability.
So let’s go back to the steps we set in the Objective part for the exploitation part:
/tmp/flag in a predictable and writable location can be done with the
Now we have to sleep !! ☺
Now we can send our second payload, to call
NR_sys_open, and append the other arguments:
We have now a file descriptor open to our flag file! Let’s read its content:
… And write it back to our socket (and exit cleanly, just because):
This write-up does not give justice to the challenge, making it look easy. But it was not. I really like how you are made to create really inventive and neat technique for subverting existing calls to set up the structure the exact way you want it.
For those who want, the full exploit script is here. But again, it was not tested against the game server.
Another good lesson to pay attention to details…
Share this post: