Antecedentes generales: He escrito un servidor de eco que intenta implementar un ejemplo de BoF en C que utiliza una llamada a la función strcpy () como esta:
// .... 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: Entonces, una vez que alimentemos al servidor con una cadena de entrada lo suficientemente grande, el servidor generará una infracción de acceso con un desplazamiento 41414141 (que es lo que queríamos); sin embargo, una vez que desmontamos el archivo ejecutable en un desensamblador / depurador (utilicé el Depurador de inmunidad) en el momento de la violación, ni el ESP ni el EIP se sobrescribieron con la cadena As (por ejemplo). Mientras que el registro de EBP se sobrescribió con la cadena grande desbordada de As.
Solución: Así que hice algunas búsquedas en Google y vi códigos de ejemplo similares del mismo tipo (Echo Server con un BoF vuln) y probé cosas diferentes con vuln_func como tal:
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;
}
y la función de eco se verá así:
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
}
}
así que la función echo repite el recv_str en lugar del send_str el cual imho derrota todo el propósito de la llamada vuln_func, pero con el propósito de demostrar esta vulnerabilidad de BoF, la dejaremos ahí. Después de verificar con Immunity Debugger, los registros ESP y EIP se sobrescriben con éxito con la cadena ("A * 128"), ¡el problema se solucionó! Genial
Pregunta: ¿Por qué el problema se comportó de esa manera?
- ¿Por qué, al devolver un puntero (dirección) a una cadena a la La función de llamada evita que se sobrescriba el EIP mientras se devuelve. void, o int hará que el registro EIP se sobrescriba como esperado
- ¿Cómo almacena el valor el registro EIP en los dos scanrios?
mencionado anteriormente (con un vuln_func que devuelve char * y otro vuln_func
devolviendo el vacío)? - ¿El problema que se comporta de esta manera tiene algo que ver con el alineación de la pila, sé que (habiendo sobrescrito el EIP) sería un problema si se llamó a strcpy en main (), estudiando desde otra SE mensajes / respuestas
Como puede ver, el problema se resolvió pero no entiendo por qué funcionó. Por favor explique, o señale la dirección de escritura. Muchas felicitaciones y gracias de antemano.