2011-12-17 24 views
8

Ciao a tutti,Differenza tra dichiarare lo shellcode come char [] array e char *?

Sto cercando di imparare codice di shell di base e ho trovato qualcosa di curioso che spero che qualcuno possa spiegarmi. Ho compilato il seguente codice in due modi: dichiarando lo shellcode come array e come char *. Quando dichiaro shellcode come array, linux rileva che sto cercando di eseguire i dati e ottengo un segfault sulla prima istruzione. Tuttavia, quando dichiaro shellcode come char * tutto lo shellcode viene eseguito e ottengo un "Hello world!". Come fa il compilatore a trattare queste due dichiarazioni in modo diverso e perché finisce uno shellcode che vive in memoria che non è protetto? Grazie in anticipo.

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

/* This declaration ends in a segfault */ 
//char shellcode[] = 

/* This declaration ends in successful execution */ 
char* shellcode = 

/* Shellcode prints "Hello world!" and exits */  
"\xeb\x1f\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\x48\x31\xc0\xb0\x01\x48\x31\xdb\xcd\x80\xe8\xdc\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21"; 

int main() 
{ 
    void (*f)(); 
    f = (void (*)())shellcode; 
    (void)(*f)(); 
} 

risposta

8

Quando si dichiara come un char[], la memoria è in pila. Quando lo si dichiara come char* e gli si assegna una stringa letterale, la memoria si trova nell'immagine eseguibile stessa. A Linux non piace che tu stia eseguendo il codice sullo stack, ma con te stai eseguendo la memoria in quella parte dell'immagine eseguibile. Questo perché sta cercando di evitare un certo tipo di attacco di overflow dello stack in cui le persone possono sovraccaricare lo stack con alcune istruzioni arbitrarie e quindi eseguirle.

È possibile utilizzare mprotect su Linux per impostare le autorizzazioni per un'area di memoria o VirtualProtectEx su Windows. In questo modo è possibile impostare in modo esplicito le autorizzazioni della memoria per essere eseguibili.

3

Nel primo caso:

char shellcode[] = 

questo mette la stringa letterale in pila come una matrice locale. Lo stack e la memoria heap di solito non hanno permessi di esecuzione (per ovvi motivi di sicurezza).

Nel suo secondo caso:

char* shellcode = 

La stringa vive nella memoria statica - in genere nella stessa regione, come il resto del binario programma - che è eseguibile.