2013-02-09 9 views
9

Sto imparando a parlare di buffer overflow e sto provando a crearne uno. Ho questo codice:Compilare C per consentire l'overflow del buffer

#include <stdio.h> 

char *secret = "password"; 

void go_shell() { 
    char *shell = "/bin/sh"; 
    char *cmd[] = { "/bin/sh", 0 }; 
    setreuid(0); 
    execve(shell,cmd,0); 
} 

int authorize() { 
    char password[64]; 
    printf("Enter Password: "); 
    gets(password); 
    if (!strcmp(password,secret)) { 
     return 1; 
    } 
    else { 
     return 0; 
    } 
} 

int main() { 
    if (authorize()) { 
     printf("login successful\n"); 
     go_shell(); 
    } else { 
     printf("Incorrect password\n"); 
    } 
    return 0; 
} 

compilo questo con gcc e quindi eseguirlo in gdb

entro in circa 100 s "A" come password e il programma si blocca.

il problema non è il registro viene sovrascritto ad 0x4141414141414141

Googled questo e ha aggiunto la bandiera -fno-stack-protector-gcc, che ha permesso RBP per essere sovrascritto a 0x4141414141414141 ma nient'altro.

Mi chiedevo se c'era un modo per compilare il codice in modo che RIP possa essere sovrascritto.

+0

Stai usando Linux? Dovresti anche impostare qualche bandiera lì, credo. – nhahtdh

+0

Utilizzo di Mac OSX. Qualche idea di cosa sia la bandiera? – carloabelli

+0

Non so su Mac OSX - probabilmente sarà molto diverso da Ubuntu (mi dispiace, l'ho fatto su Ubuntu, non su Linux). – nhahtdh

risposta

3

Il tuo codice fa già ciò che vuoi se lo compili con -fno-stack-protector. Il motivo per cui non vedi RIP con un valore di 0x4141414141414141 in GDB è che viene generato un errore di protezione generale prima dell'aggiornamento di RIP. (Se si verifica un errore di pagina, il gestore GPF di solito carica la pagina da swap e riprende l'esecuzione iniziando con l'istruzione non riuscita.)

+0

Grazie per l'aiuto, ma mi chiedevo se c'era un modo per disattivare quel GPF in modo che RIP potesse essere impostato su' 0x4141414141414141' perché questo è ciò che accade nel tutorial che sto usando. – carloabelli

+0

@ cabellicar123 Non è possibile evitare il GPF a meno che non si crei una pagina eseguibile a quell'indirizzo. Continua con il tuo tutorial. Probabilmente il prossimo passo sarà quello di fornire una password appositamente predisposta che faccia passare il codice a un indirizzo valido. – nwellnhof

+0

Grazie mille per il tuo aiuto! – carloabelli

1

Il motivo per cui si verifica un arresto anomalo di EIP 0 × 41414141 su x32 è dovuto al fatto che quando si apre il programma il valore EIP precedentemente salvato dallo stack e di nuovo in EIP la CPU quindi tenta di eseguire l'istruzione all'indirizzo di memoria 0 × 41414141 che causa un segfault. (deve recuperare la pagina prima dell'esecuzione ovviamente)

Ora, durante l'esecuzione x64 quando il programma fa scattare il valore RIP salvato in precedenza nel registro RIP, il kernel prova a eseguire le istruzioni all'indirizzo di memoria 0 × 4141414141414141. In primo luogo, a causa dell'indirizzamento di forma canonica, i bit da 48 a 63 di qualsiasi indirizzo virtuale devono essere copie del bit 47 (in modo simile all'estensione del segno), oppure il processore solleverà un'eccezione. Se questo non era un problema, il kernel esegue controlli aggiuntivi prima di richiamare il gestore degli errori di pagina poiché l'indirizzo dello spazio utente massimo è 0x00007FFFFFFFFFF.

Per ricapitolare, in architettura x32 l'indirizzo viene passato senza alcuna "convalida" al gestore di errori di pagina che tenta di caricare la pagina che attiva il kernel per inviare il programma segfault ma x64 non arriva così lontano.

Provalo, sovrascrivi RIP con 0 × 0000414141414141 e vedrai che il valore atteso viene inserito in RIP dai precheck del passaggio del kernel e quindi il gestore degli errori di pagina viene richiamato come il caso x32 (che ovviamente, quindi, causa il crash del programma).

Problemi correlati