Come sfruttare il valore della variabile

4

Sto provando a sfruttare un file binario che ho accesso al codice sorgente.

int flag = 0;

int main() {
    char buf[0x50];
    puts("Who are you? ");
    printf("> ");
    fgets(buf, 0x50, stdin);
    printf(buf);

    if (flag == 1337) {
        puts("Enjoy your shell!");
        system("/bin/sh");}
    else {
        puts("Not allowed");
    }
    return 0;
}

Come puoi vedere dal codice sorgente, se flag è 1377 otterrò una shell. Posso vederlo anche con gdb.

 0x4007ec <main+175>       mov    eax, DWORD PTR [rip+0x200892]       # 0x601084 <flag>
 0x4007f2 <main+181>       cmp    eax, 0x539

Le misure di sicurezza sono configurate in questo modo:

Canary                        : Yes
NX                            : Yes
PIE                           : No
Fortify                       : No
RelRO                         : Partial

Quindi, prima di tutto non posso fare il classico overflow del buffer perché il programma usa fgets per raccogliere input. Ovviamente c'è anche il canarino, ma non farà del male perché se potessi cambiare il valore del flag (prima che fosse fatto l'assegno di Canary) avrei avuto successo nell'ottenere quel guscio. Non so se quello che sto pensando è giusto, quindi per favore correggimi se sbaglio.

La mia prima conclusione è stata che non sarei stato in grado di sfruttare buf per riscrivere il valore del flag. (Supponevo che buf e flag fossero posizionati uno accanto all'altro nello stack). Penso di aver ragione su questo perché quando ho dato un'occhiata al $rsp registrati e ho scoperto che solo la quantità consentita di "A" è stata messa in pila. Quindi anche se il flag fosse posizionato proprio sotto di esso, il valore del flag non verrebbe sovrascritto. Ho ragione finora? Questa sarebbe la mia prima domanda

0x7fffffffdaf0: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb00: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb10: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb20: 0x41414141  0x41414141  0x41414141  0x41414141
0x7fffffffdb30: 0x41414141  0x41414141  0x41414141  0x00414141
0x7fffffffdb40: 0x00400840  0x00000000  0x96703f00  0x948afed7
0x7fffffffdb50: 0xffffdc40  0x00007fff  0x00000000  0x00000000

Quindi, come potrei essere in grado di valutare tale valore? Penso che l'exploit debba provenire dal payload fornito da un utente malintenzionato ma buf è l'unico modo per ottenere quel payload nello stack. Dal momento che non riesco a sovrascrivere i registri facendo traboccare buf sono un po 'perso.

    
posta fish202 01.12.2017 - 02:16
fonte

2 risposte

3

Hai ragione che il buffer non può traboccare il flag a causa del controllo dei limiti. Fgets include anche il carattere null nel suo controllo associato.
link

Tuttavia, qui esiste una vulnerabilità in formato stringa:

printf(buf);

La variabile buf controllata dall'utente viene utilizzata in un'istruzione printf, causando una vulnerabilità della stringa di formato.

link

Usando una combinazione di %x %n puoi sovrascrivere il flag con "1337". % x è usato per estrarre i valori dallo stack e% n è usato per scrivere il numero di caratteri in quell'indirizzo. Il "1337u" espande il numero di caratteri in modo da poter scrivere il valore corretto. Ad esempio, se la posizione di memoria del flag è "0xffffff80"

$(python -c 'print "\x80\xff\xff\xff"+"%x%1337u%n"')

Questo scriverà un numero che è maggiore di 1337 a causa delle altre cose prima del "1337u", quindi devi solo sottrarre quel numero per l'importo che esagerare, e avrai il numero giusto. Oppure, se vuoi fare un po 'di matematica, il valore di "u" è: "Il byte da scrivere" - "il byte emesso" + "la larghezza del% x specificato appena prima del% n"

    
risposta data 01.12.2017 - 15:53
fonte
1

flag non è locale a nessuna funzione e ha portata globale. Pertanto, non si trova nello stack di runtime. O patch il binario o approfitta del fatto che l'input a buf non è sterilizzato e che buf un argomento a printf (manipola il valore dell'argomento stringa di formato in modo che 1337 sia scritto per indirizzare 0x601084 ).

flag è una variabile allocata staticamente il cui valore verrà archiviato nel segmento data o bss del processo anziché nello stack di runtime. Se hai accesso al binario, puoi semplicemente applicare una patch in modo che il valore 1337 sia memorizzato all'indirizzo 0x601084 , che dovrebbe essere nella sezione .data o .bss . Poiché qui la variabile globale flag è inizializzata a 0, sarà probabilmente nella sezione .bss del binario e il segmento bss del processo (questo non sarebbe il caso se fosse inizializzato su qualche altro valore) .

Anche se non si sa come il compilatore alloca la memoria per le variabili in base alla loro posizione nel codice sorgente, si potrebbe ancora determinare che flag non è memorizzato nello stack di runtime confrontando il suo indirizzo con quello del puntatore dello stack %rsp : la posizione 0x601084 è molto più bassa in memoria di 0x7fffffffdaf0 .

    
risposta data 01.12.2017 - 06:38
fonte

Leggi altre domande sui tag