Instalá ghidra: sudo apt install -y ghidra
O lo podés descargar e instalar desde acá: https://github.com/NationalSecurityAgency/ghidra
Descargá el archivo del desafío unlock_me1
, acá: https://secur3.us/GhidraFiles/unlock_me1
Los pasos básicos para afrontar un desafío como este son:
unlock_me1
en CodeBrowser e inicia el análisis automático.__libc_start_main()
Después de importar y analizar unlock_me1
, necesitarás ubicar el punto de entrada para la función. Para una aplicación libc como ésta, __libc_start_main()
se utiliza para cargar main()
dentro de un entorno apropiado. Puedes encontrar esto en el binario usando el método abreviado de teclado ‘G’ desde la vista de listado de Ghidra para unlock_me1
y saltando a __libc_start_main()
que se encontrará como una función Thunked como se muestra aquí:
Thunked-Function tiene un XREF de FUN_00101080
Al abrir el XREF de llamada desde FUN_00101080:001010a4
se muestra lo siguiente:
Entrada descompilada en main()
Según la documentación, el primer argumento de __libc_start_main()
es la función main(). Puede hacer doble clic en FUN_00101165
para acceder a la vista descompilada de esta función y actualizar la firma para que coincida con la convención estándar:
Ahora podemos mirar el resultado descompilado y comenzar a buscar variables para cambiar el nombre dentro de la función. Para empezar Ghidra nos muestra el siguiente código:
Comenzando desde arriba, vemos que la entrada del usuario se recopila mediante scanf en la línea 13 y se almacena en local_38
y la longitud de la cadena se coloca en sVar2. A estas variables se les puede cambiar el nombre de input
y input_len
respectivamente, generando el resultado descompilado como se muestra aquí:
Ahora está claro que la línea 15 está verificando la longitud de la entrada y rechazará cualquier entrada a menos que tenga una longitud exacta de 0x14 (20 en decimal). Podemos ver que local_1c
y local_20
se inicializan a 0 antes de ingresar a un ciclo while. Dentro del bucle podemos ver que local_20
se utiliza como índice en la entrada en la línea 22 y luego local_20
se incrementa en la línea 23. También en la línea 22 vemos que los caracteres de la cadena de entrada se suman en local_1c
, lo que nos da la lógica nombres input_sum
e index
para local_1c
y local_20
respectivamente, como se muestra en la descompilación actualizada:
Al leer el código ahora, debería quedar claro que la entrada debe satisfacer dos propiedades para llegar al mensaje ‘Unlock!’ en la línea 26. Por línea 15, la entrada debe tener exactamente 20 bytes de longitud. Según la línea 25, la suma de los bytes en la entrada debe ser un múltiplo de 7.
A partir de este punto, el desafío crackme se ha transformado en un problema matemático básico. Debería ser posible sumar 20 caracteres imprimibles y luego usar el módulo para determinar cuántos bytes sumar o restar para producir un múltiplo de 7.
Por ejemplo, podemos calcular la suma de 20 caracteres “0” y encontrar que es uno de un múltiplo de 7.
>>> ord("0")*20 % 7
1
Esto significa que sólo necesitamos agregar 6 bytes a la suma total. Esto se hace fácilmente cambiando un ‘0’ (0x30) por ‘6’ (0x36) dándonos la siguiente solución:
$ ./unlock_me1
Enter the unlock key: 00000000000000000006
Unlocked!
El ejemplo de tarea para esta publicación sigue la misma idea básica, pero tiene algunas comprobaciones adicionales que necesitarás realizar para producir una entrada válida. La función principal descompilada en este ejemplo se muestra a continuación:
Fuente: https://medium.com/@cy1337/reversing-a-simple-crackme-with-ghidra-decompiler-5dd1b1c3c0ba
https://youtube.com/channel/UCPNPSP20z4FGfgMJ71VOJjw/playlists
O miralo en alguna instanacia de invidious: https://redirect.invidious.io/channel/UCPNPSP20z4FGfgMJ71VOJjw/playlists