El reto que planteabamos era el siguiente : https://www.nodo313.net/index.php?threads/reto-overflow-ctf.7524/#post-72133
Y como de costumbre en los temas relacionados con la tématica del foro el interés generado ha sido escaso, creo que el único usuario interesado ha sido @Galaxyytbr, y como me ha ido preguntado dudas y me ha pedido la solución se la voy a subir ya, porque este tema caerá en el olvido imagino.
La solución la haré enfocada a las dudas de este usuario, que eran bastante básicas, así que, intentaré obviar partes muy técnicas y enseñarle a llegar a la solución de manera sencilla.
- El primer paso es descargarse el .c y el ejecutable.
- Ahora procedemos a ver el codigo en cualquier editor de texto y veremos algo como esto :
Según el título del reto, lo que nos tiene que llamar la atención del código es lo siguiente :
#define BUFFSIZE 64
gets(buf);
Vemos el tamaño 64 y una función que presenta esto en su documentación
gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with a null byte (aq\0aq). No check for buffer overrun is performed (see BUGS below).
Y el objetivo parece ser llegar a la función flag(), veremos como lo hacemos:
- Bien pues lo primero que haremos es probar el ejecutable a ver que sucede:
Vemos que nos pide la entrada, luego la imprime, y después nos da la dirección de retorno, la siguiente dirección a donde va a saltar el programa. (Como vemos no hacía falta ni saber c para comprender el programa ya que es muy simple.)
- Ahora siguendo la documentación de la función gets, el cual nos dice que no tiene ningun tipo de comprobacion en la entrada, es decir va a aceptar todo lo que le metamos, sin importar el tamaño de la variable.
(Recordemos : #define BUFFSIZE 64 )
Así que vamos a ver que pasa si nos pasamos de ese tamaño.
(Vamos a hacer todos estos paso de forma manual, sin ningun tipo de herramienta para complicar lo menos posible la solución)
Vemos que hemos superado el tamaño máximo de la variable, y nos ha dado un error.
Y si nos fijamos un poco hemos sobrescrito la dirección de retorno!!!!
Hemos pasao de 0x8048705 a 0x41414141.
Con una simple conversión online podemos ver que significa el nuevo numero que tenemos.
Como vemos hemos sobrescrito la dirección de retorno con las As que le hemos pasado como input!
- Ahora debemos comprobar exactamente cuantas As hacen falta para llegar a ese punto, para que podamos tener control total del retorno y llegar a la función flag().
Como haremos esto? Pues existen diversas técnicas, pero como el objetivo es hacer esta explicación apta para todo el mundo, vamos a hacerlo con python para comodidad pero el proceso será puramente manual. Añadiremos ahora unas cuantas As + 4Bs hasta conseguir que nuestra dirección de retorno sea todo 42(como vimos antes las As son 41, y la B es 42)
Bueno no voy a comentar demasiado del comando, y como veis podemos hacerlo de forma sencilla solo con ir probando(en este caso simple claro xD)
BIEN, sabemos que ingresando exactamente 76 As, lo siguiente que ingresemos será la dirección de retorno, como podemos ver por nuestras 4Bs (42) saliendo por pantalla.
- Que nos queda? simplemente que esa dirección de retorno que tenemos ya controlada apunte a nuestra función flag().
Otra vez hay muchas formas de hacerlo, pero no vamos a entrar en ver la memoria guardad en la pila ni nada que pueda complicar mas el asunto, vamos a tirar un simple comando que os vais a creer que funciona y el cual podeis investigar en internet, o buscar otras formas de llegar a la dirección de la función deseada.
Bien ya tenemos la dirección de nuestra función flag(). Solo nos quedaría añadirla tras exactamente las 76As (o cualquier caracter) para que la dirección de retorno sea la función deseada.
Nota: No entraremos en esto tampoco pero la dirección debe escribirse en little endian (google) por lo que nos quedaría : 080485e6 --> '\xe6\x85\x04\08'
- Por lo que como último paso solo tendremos que concatenar esa dirección en vez de las 4Bs que teníamos ya saltándonos por pantalla :
Como vemos saltamos a la función deseada, pero al no tener el txt con la flag obtenemos este mensaje, pero hemos superado el reto !!!
Espero que os guste y hayáis aprendido algo con todo esto. Yo seguiré haciendo retillos y compartiendo lo que aprenda!
Y como de costumbre en los temas relacionados con la tématica del foro el interés generado ha sido escaso, creo que el único usuario interesado ha sido @Galaxyytbr, y como me ha ido preguntado dudas y me ha pedido la solución se la voy a subir ya, porque este tema caerá en el olvido imagino.
La solución la haré enfocada a las dudas de este usuario, que eran bastante básicas, así que, intentaré obviar partes muy técnicas y enseñarle a llegar a la solución de manera sencilla.
- El primer paso es descargarse el .c y el ejecutable.
- Ahora procedemos a ver el codigo en cualquier editor de texto y veremos algo como esto :
C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"
#define BUFFSIZE 64
#define FLAGSIZE 64
void flag() {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("Flag File is Missing. please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(buf,FLAGSIZE,f);
printf(buf);
}
void vuln(){
char buf[BUFFSIZE];
gets(buf);
printf("Woah, were jumping to 0x%x !\n", get_return_address());
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
gid_t gid = getegid();
setresgid(gid, gid, gid);
puts("Give me a string and lets see what happens: ");
vuln();
return 0;
}
Según el título del reto, lo que nos tiene que llamar la atención del código es lo siguiente :
#define BUFFSIZE 64
gets(buf);
Vemos el tamaño 64 y una función que presenta esto en su documentación
gets() reads a line from stdin into the buffer pointed to by s until either a terminating newline or EOF, which it replaces with a null byte (aq\0aq). No check for buffer overrun is performed (see BUGS below).
Y el objetivo parece ser llegar a la función flag(), veremos como lo hacemos:
- Bien pues lo primero que haremos es probar el ejecutable a ver que sucede:
Vemos que nos pide la entrada, luego la imprime, y después nos da la dirección de retorno, la siguiente dirección a donde va a saltar el programa. (Como vemos no hacía falta ni saber c para comprender el programa ya que es muy simple.)
- Ahora siguendo la documentación de la función gets, el cual nos dice que no tiene ningun tipo de comprobacion en la entrada, es decir va a aceptar todo lo que le metamos, sin importar el tamaño de la variable.
(Recordemos : #define BUFFSIZE 64 )
Así que vamos a ver que pasa si nos pasamos de ese tamaño.
(Vamos a hacer todos estos paso de forma manual, sin ningun tipo de herramienta para complicar lo menos posible la solución)
Vemos que hemos superado el tamaño máximo de la variable, y nos ha dado un error.
Y si nos fijamos un poco hemos sobrescrito la dirección de retorno!!!!
Hemos pasao de 0x8048705 a 0x41414141.
Con una simple conversión online podemos ver que significa el nuevo numero que tenemos.
Como vemos hemos sobrescrito la dirección de retorno con las As que le hemos pasado como input!
- Ahora debemos comprobar exactamente cuantas As hacen falta para llegar a ese punto, para que podamos tener control total del retorno y llegar a la función flag().
Como haremos esto? Pues existen diversas técnicas, pero como el objetivo es hacer esta explicación apta para todo el mundo, vamos a hacerlo con python para comodidad pero el proceso será puramente manual. Añadiremos ahora unas cuantas As + 4Bs hasta conseguir que nuestra dirección de retorno sea todo 42(como vimos antes las As son 41, y la B es 42)
Bueno no voy a comentar demasiado del comando, y como veis podemos hacerlo de forma sencilla solo con ir probando(en este caso simple claro xD)
BIEN, sabemos que ingresando exactamente 76 As, lo siguiente que ingresemos será la dirección de retorno, como podemos ver por nuestras 4Bs (42) saliendo por pantalla.
- Que nos queda? simplemente que esa dirección de retorno que tenemos ya controlada apunte a nuestra función flag().
Otra vez hay muchas formas de hacerlo, pero no vamos a entrar en ver la memoria guardad en la pila ni nada que pueda complicar mas el asunto, vamos a tirar un simple comando que os vais a creer que funciona y el cual podeis investigar en internet, o buscar otras formas de llegar a la dirección de la función deseada.
Bien ya tenemos la dirección de nuestra función flag(). Solo nos quedaría añadirla tras exactamente las 76As (o cualquier caracter) para que la dirección de retorno sea la función deseada.
Nota: No entraremos en esto tampoco pero la dirección debe escribirse en little endian (google) por lo que nos quedaría : 080485e6 --> '\xe6\x85\x04\08'
- Por lo que como último paso solo tendremos que concatenar esa dirección en vez de las 4Bs que teníamos ya saltándonos por pantalla :
Como vemos saltamos a la función deseada, pero al no tener el txt con la flag obtenemos este mensaje, pero hemos superado el reto !!!
Espero que os guste y hayáis aprendido algo con todo esto. Yo seguiré haciendo retillos y compartiendo lo que aprenda!
Adjuntos
Última edición: