Hoy os traigo el primer Capture The Flag como todos en el mundillo conocemos o "Reto de Ciberseguridad" de esta serie de CTF con el Nivel 1 al que hemos llamado "Easy Level".
Podéis bajaros el ejecutable pinchando en la imagen:
Resolución CTF - Nivel 1 : Easy Level
Vamos a resolver el primer crackme, CTF, reto de reversing o como más os guste llamarlo.
Tenemos los siguiente binarios, compilados con Mingw (en Windows) y gcc (en Linux).
El código fuente del que se partió fue este:
#include <stdio.h>
#include <stdlib.h>
#define password "HolaHackers"
int main (int argc , char * argv [])
{
char pwd[100];
printf("Please enter the password::\n");
scanf("%s", pwd);
if ( strcmp(pwd, password) == 0 )
{
printf("Congratulation!!\n");
printf("Ready to login with: %s\n",password);
}
else
{
printf("Wrong password\n");
}
getchar();
return 0;
}
Pero este hubiera sido muy sencillo resolverlo por lo que lo compliqué un poco:
#include <stdio.h>
#include <stdlib.h>
#define error "error"
#define nop "nop"
#define password "nohackershere"
#define access "access"
#define good "Good!"
#define admin "admin"
int main (int argc , char * argv [])
{
char pwd[100];
printf("Please enter the password::\n");
scanf("%s", pwd);
if ( strcmp(pwd, error) == 0 )
{
if ( strcmp(pwd, nop) == 0 )
{
//Do nothing
}
}
if ( strcmp(pwd, password) == 0 )
{
if ( strcmp(pwd, good) == 0 )
{
//Do nothing
}
printf("Congratulation!!\n");
printf("Ready to login with: %s\n",admin);
}
else
{
printf("Wrong password\n");
if ( strcmp(pwd, access) == 0 )
{
//Do nothing
}
}
getchar();
return 0;
}
Como veis, es muy parecido, se trata de meter “basura” en el anterior.
¿Cómo lo han resuelto algunos? Con el comando “strings”. Pero eso no tiene gracia :P
Lo gracioso es hacerlo de esta otra forma. Comencemos.
IDA:
Abrimos el de Linux, en Windows, ¿no os parece gracioso?
Después de aceptar un montón de ventanas, incluídas la de tu licencia ha caducado en 2015, vemos lo siguiente:
Ya en la primera ventana nos da pistas, este IDA… Justo debajo vemos el clásico check de chico bueno y chico malo.
Por lo que habrá una comparación en algún sitio. Lo buscamos. Ponemos el código para visualizarlo mejor en modo gráfico (esta vez sí se cumple lo del botón derecho ;-))
Los que hayais seguido algún tutorial de Ricardo Narvaja, veréis que a él le gusta colorear, a mí también, así que vamos a ello.
Y llegamos al Kit (como diría Michael Knight, ¿era así?) de la cuestión. Se realiza una comparación con la función “strcmp”. Buscamos esa función para ver lo que hace y lo que devuelve: strcmp .
Bien, entonces:
loc_40069B:
lea rax, [rbp+s1] ; cargamos la dirección rbp+s1 que es lo que hemos introducido nosotros en rax.
mov esi, offset aNohackershere ; "nohackershere" ; movemos esta cadena a esi
mov rdi, rax ; s1 movemos a rdi lo que hemos introducido nosotros
call _strcmp ; llamamos a comparar las 2 strings “nohackershere” con lo que hemos introducido nosotros
test eax, eax ;el resultado se guarda en eax y los comparamos
jnz short loc_4006E1 ; si el resultado no es cero, salta a loc_4006E1
Por lo que ya está claro con qué lo compara. La cadena que buscamos es “nohackershere”. El resto, son despistes, o eso pretendía :P
Si pulsamos F5 en IDA, nos intenta traducir el código a C:
Para ser sincero, se parece bastante al original y se me mejor aún lo que buscabamos.
OllyDBG:
Lo cargamos en el Olly y paramos aquí, en el Entry Point:
De nuevo el botón derecho nos salvará.
Podemos ver las strings.
Si pulsamos en la “Congratulation!!”, por ejemplo, iríamos a la parte del código que nos dará la enhorabuena, subimos un poco y vemos donde se realiza la comprobación. Doble click y…
Subimos para ver todo el código:
Si nos fijamos, vemos como el “Congratulation!!” está justo después de este “strcmp”.
Por lo que lo compara con “nohackershere”. Visualmente se ve peor que en IDA. Juguemos con Olly para verlo. Breakpoint (F2) en 004014BA y F9 para llegar a ahí, pero antes pararemos en introducir nuestra contraseña…
Ponemos, “niidea” y pulsamos “enter” o lo que más os guste.
Paramos y vamos pulsando F8.
Vemos como en EAX aparece nuestro “niidea”.
Mirad la comparación que va a realizar:
Por lo que ya tenemos con Olly el resultado: “nohackershere”.
Vemos el valor de EAX que no es cero por lo que saltará a chico malo.
Reiniciemos el Olly y pongamos la contraseña buena.
Pongo un breakpoint (F2) en el salto para ver el valor de EAX.
F9 para ejecurtarlo y parar en él:
Y vemos como EAX vale 0, por lo que debería continuar y no saltar, F8 para comprobarlo:
Y aquí nos dan la enhorabuena:
Radare2:
Para ello utilizaré un GUI para el Framework de Radare2 llamado radare2gui:
Voy a abrir el de Linux, si no os importa :P
Fijaros en esas instrucciones, son las que carga en cada pestañam, por lo que si queréis hacerlo sin este GUI, podeis ponerlas directamente en radare2.
En las “strings”, vemos lo siguiente:
Como veis, es parecido al Olly.
Si pulsamod doble click en “Congratulation!!”, por detrás ejecuta lo siguiente:
Se posiciona en 0x004007d1, es decir, donde se encuentra la cadena y le da un tamaño al bloque para visualizarlo (4000) en la pestaña de hexview y además lo visualiza en la pestaña de graficos. Como podeis suponer, cada vez que se realiza una acción, el GUI lo hace tantas veces y de formas diferentes para cada pestaña.
Esto es lo que vemos en Hexview:
Es solamente un ejemplo de como podemos llegar a donde queramos según las “strings” y siguiendo la filosofía OllyDBG. En este caso lo mejor es darle doble click a la función “main”.
Si bajamos un poco, como en IDA, vemos lo siguiente:
Chico bueno y chico malo, de nuevo.
Y vemos claramente una cadena, en este caso “str.nohackershere”. En Radare2, es la forma de ponerte el conenido de las cadenas, “str.cadena”, por lo que ya sabes la solución.
En “local_70h” va a guardar lo que le pongamos nosotros. Primero acaba en rax y después en rdi, igual que habíamos visto en IDA. Y lo mismo con la cadena que buscamos.
Como veis hay muchas formas de resolverlo, desde un strings, lo más sencillo, hasta 3 herramientas muy potentes como IDA, OLLYDBG y Radare2.
Ya sé lo que pensareis algunos con lo del GUI de Radare2… Vale…
También se ve.
Cambios en binarios
Hola a todos!!
Alguno me he preguntado como se hacen los cambios en el binario para que se hagan persistentes y meta lo que meta siempre funcione. Explicaré 2 formas.
Hiew:
Arrastramos el binario (“easy-level1.exe”) a Hiew.exe (Drag and Drop).
Necesitamos verlo de otra forma, por lo que pulsamos F4.
Y ahora F2 para que nos cambie la vista a ensamblador. Esta forma es más bonita y tratable :P
Necesitamos ir a una dirección de memoria, por lo que pulsamos F5, pero antes, ¿a qué dirección de memoria?
A esta: 0x004014D0. En OllyDBG…
El caso es que hay que hacer un cambio para que esto funcione. F4 para pasar de 16 a 32 bits
Vemos la diferencia, ¿verdad? ¿Ahora ya podemos ir a 14D0?
Debe ser la versi´n de Hiew, demasiado antigua. Esta debe tener como 15 años o más…
Buscamos los opcodes que nos identifiquen el salto:
Me cuadra, ahora bien,¿ JNE lo queremos cambiar a JE? ¿Qué pasaría si alguien introduce la buena? Pues que saltaría a chico malo y no queremos eso.
Es mejor un JMP a la siguiente dirección, es decir, que continúe con el programa, que no salte. Cambiamos con F3:
Por:
Que es la dirección siguiente. Pongas lo que pongas, continúa. Pulsamos ENTER.
F9 (actualizar el binario) Y F10 pasa salir (igual no le gusta…)
O bien… juguemos con NOP (no operation). Ponemos 4.
F9 (actualizar el binario) Y F10 pasa salir.
Pare que funciona.
Segundo método y con menos quebraderos de cabeza.
OllyDBG:
Lo mismo que antes, el JNZ lo tenemos que cambiar a otra cosa. Un JMP a la siguiente dirección, la de los NOP ya lo hemos visto antes.
Lo cambio:
Botón derecho:
Confirmamos:
Ya está guardado y comprobamos que lo hemos hecho bien, F8 y:
Sí, ha continuado… F9 para finalizar.
Ahora vamos al que hemos guardado y…
Funciona ;-)
Espero que os haya gustado y hasta otra.