This post is a solution to pwnable.tw‘s CTF “Start” challenge. If you’re planning to solve it yourself, please don’t cheat.
How the challenge works
- After solving a challenge, the flag is submitted.
- Flags can usually be found in /home/<challenge_name>/flag.
- Most challenges run on
Ubuntu 16.04docker containers.
- After analysis of the binary, you connect to chall.pwnable.tw on a port the changes per challenge - and run the exploit to get the flag.
This challenge is a small (elf) executable, it’s length is only 564 bytes.
Here is it’s disassembly:
As you can see, there are 5 pushes of constant numbers to the stack (0x0804806e-0x08048082). Each number contains bytes that can be ascii characters.
After decoding, we get
Let's start the CTF:.
The string is written to stdout directly using syscalls (syscalls are
int 0x80 for Linux OSs).
A bit about syscalls
Syscalls in Linux take eax as the syscall number, ebx, ecx, edx, etc… as parameters. The return code is stored in eax, all other registers remain the same.
Syscalls in this binary:
|eax (syscall #)||name||ebx||ecx||edx|
Immediatly after writing “Let’s start the CTF:", the program wait for 0x3C (=60) bytes of input and writes it to $esp - At this point $esp is pointing to the beginning of the printed string.
Since the stack itself is 20 bytes long, we can control the return address!
Since ASLR is enabled, we must first leak the stack’s address.
Leaking the stack’s address
In order to print the string the code used $esp as a parameter for write(1, $esp, 4). This is great, because it means we can leak $esp. Leaking $esp is done by setting the return address to 0x08048087. This will cause the program to write 20 bytes of which the first 4 will contain $esp’s value.
c.send('x' * 20 + pack('<I', 0x08048087)) esp = unpack('<I', c.recv(0x100)[:4])
After sending the above payload, we will get $esp and the program will be expecting another (up to) 60 byte input.
Now that we have $esp, we can use
ragg2 -i exec -b32 to generate a shellcode.
The shellcode’s input follows the shellcode.