Sfondo generale: Ho scritto un server di eco cercando di implementare un esempio di BoF in C che utilizza una chiamata di funzione strcpy () come tale:
// .... including the corresponding libraries depending on host environment
#include <stdio.h> // crossed platform headers
#include <string.h> // string header, for strcpy
#include <stdlib.h> // stardard lib, for exit()
void echo(void); // infinite loop echo serving client
char* vuln_func(char* recieved); // BoF vulnerable function that uses strcpy from string.h
int main(void)
{
... setting up echo server
echo();
return 0;
}
void echo(void)
{
char *send_str; // declaring the pointer to the string recieved from vulnFunc
char recv_str[1024]; // variable declaration to store input string from client
// infinite loop to echo serve clients
while(1)
{
... recieving string from client and storing it starting at location recv_str
// calling vuln_func and inputting the received string from client
send_str = vuln_func(recv_str);
...echoing the send_str back to the client
}
}
char* vuln_func( char* recieved)
{
char* sending_str = (char*)calloc(100, sizeof(char));
char buf[100];
int i; // declaring counter for loop
strcpy(buf, recieved);
for (i = 0; i < strlen(buf); i++) // for loop to populate return string with the send
{
sending_str[i] = buf[i];
}
return sending_str;
}
Problema: Quindi, una volta che il server viene alimentato con una stringa di input sufficientemente grande, il server genererà una violazione di accesso con offset 41414141 (che è ciò che volevamo); tuttavia, una volta smontato l'exe in un disassembler / debugger (ho usato l'immunità Debugger) al punto della violazione né l'ESP né l'EIP sono stati sovrascritti con la stringa di As (ad esempio). Mentre il registro EBP è stato sovrascritto con la grande stringa "overflown" di As.
Soluzione: Così ho fatto qualche ricerca su google e ho visto codici di esempio simili dello stesso tipo (Echo Server con un vuln di BoF) e ho provato diverse cose con il vuln_func come tale:
void vuln_func( char* recieved)
{
char buf[100];
strcpy(buf, recieved);
}
o
int vuln_func( char* recieved)
{
char buf[100];
strcpy(buf, recieved);
return 1;
}
e la funzione echo sarà simile a questa:
void echo(void)
{
char recv_str[1024]; // variable declaration to store input string from client
// infinite loop to echo serve clients
while(1)
{
... recieving string from client and storing it starting at location recv_str
// calling vuln_func with string received from client
vuln_func(recv_str);
...echoing the recv_str back to the client
}
}
quindi la funzione echo riporta indietro recv_str invece di send_str che imho sconfigge l'intero scopo della chiamata vuln_func, ma allo scopo di dimostrare questa vulnerabilità del BoF, la lasceremo lì. Dopo aver controllato con Immunity Debugger, entrambi i registri ESP e EIP vengono sovrascritti con successo con la stringa ("A * 128"), problema risolto !! Grande
Domanda: Perché il problema si è comportato in questo modo?
- Come mai quando si restituisce un puntatore (indirizzo) a una stringa al la funzione di chiamata impedisce che l'EIP venga sovrascritto, mentre restituisce void, o int causerà la sovrascrittura del registro EIP come atteso
- In che modo il registro EIP memorizza il suo valore nei due scanrios
menzionato sopra (con un vuln_func che restituisce char * e altri vuln_func
return void)? - Il problema che si comporta in questo modo ha qualcosa a che fare con il allineamento dello stack, so che (avendo EIP sovrascritto) sarebbe un problema se strcpy veniva chiamato in main (), studiando da altro SE messaggi / risposte
Come puoi vedere, il problema è stato risolto ma non capisco perché ha funzionato. Per favore spiega, o indica la direzione di scrittura. Tanti complimenti e grazie in anticipo.