Reversim MIPS y Golang: los fundamentos del reverso. Resolviendo problemas para revertir con r0ot-mi. Parte 2

imagen

En este artículo, trataremos de descompilar el binario MIPS en Ghidra y revertir el programa escrito en golang en la IDA.

Parte 1: C, C ++ y DotNet se descompilan.

Información organizacional
Especialmente para aquellos que desean aprender algo nuevo y desarrollarse en cualquiera de las áreas de información y seguridad informática, escribiré y hablaré sobre las siguientes categorías:

  • PWN;
  • criptografía (criptografía);
  • tecnologías de red (Red);
  • inversa (ingeniería inversa);
  • esteganografía (Stegano);
  • búsqueda y explotación de vulnerabilidades WEB.

Además de esto, compartiré mi experiencia en informática forense, análisis de malware y firmware, ataques a redes inalámbricas y redes de área local, realización de pentests y escritura de exploits.

Para que pueda conocer nuevos artículos, software y otra información, creé un canal en Telegram y un grupo para discutir cualquier problema en el campo de ICD. Además, consideraré personalmente sus solicitudes personales, preguntas, sugerencias y recomendaciones personalmente y responderé a todos .

Toda la información se proporciona solo con fines educativos. El autor de este documento no tiene ninguna responsabilidad por los daños causados ​​a alguien como resultado del uso del conocimiento y los métodos obtenidos como resultado de estudiar este documento.

MIPS DE ELF


imagen

Descargue y verifique el archivo.

imagen

Este es un archivo ejecutable de 32 bits para procesadores de arquitectura MIPS. Para resolver este problema, usaremos Ghidra. Abra la hidra, cree un nuevo proyecto y agréguelo a nuestro archivo ejecutable.

imagen

Ahora abra el archivo investigado y vaya a la ventana del Árbol de símbolos. En la búsqueda, escriba main para encontrar el punto de entrada del programa.

imagen

Cuando selecciona una función, se abre inmediatamente en el descompilador.

imagen

Vamos a convertir el código.

imagen

Vemos que se leen 64 bytes en la variable local_54, cambiemos el nombre a input (tecla de acceso rápido L) y creemos una matriz de caracteres de 64 caracteres (tecla de acceso rápido Ctrl + L). También puede cambiar el nombre de la variable sVar1.

imagen

imagen

Después de alguna conversión, el código comenzó a verse un poco más hermoso.

imagen

Analizamos el código. La cadena que ingresamos debe tener 19 caracteres de longitud. En qué posición, qué carácter debe quedar claro del código. En este caso, del 8 al 17 debe ser el símbolo 'i'. Nos recuperamos, pasamos la contraseña.

Golang basic


imagen

En esta tarea, se nos proporciona un archivo ejecutable escrito en Go. Incluso puedes averiguar qué versión. Lanzo la IDA. Debe decirse de inmediato que la función principal no se llama main, sino que se llama main_main. Por lo tanto, realizamos una búsqueda por función y vamos a la principal real.

imagen

Analicemos el código. Comencemos desde el principio.

imagen

Hay definiciones de una clave, entrada. El bloque izquierdo es responsable de completar la función main_main. Considera el bloque izquierdo.

imagen

La función fmt_Scanln está diseñada para leer una línea desde la consola. También observamos los datos main_statictmp_2 ya guardados en el programa.

imagen

A continuación, se llama a la función runtime_stringtoslicebyte, de acuerdo con el código, podemos suponer que toma los primeros 6 bytes de la siguiente línea.

imagen

Key.ptr apuntará al comienzo de este segmento. Veamos que viene después.

imagen

Dependiendo de la comparación del registro anulado r9 y el registro rsi, donde se encuentra la longitud de la entrada del usuario. De esto podemos concluir que r9 probablemente será un contador. Miremos el bloque correcto, donde irá el control, después de la venta en la línea que ingresamos.

imagen

Se llama a la función bytes_Comparar, que, según el resultado de la comparación, muestra una de las líneas.

imagen

imagen

Descubrimos la salida del programa, ahora veamos los saltos de línea (en la rama izquierda).

imagen

El carácter de la entrada del usuario se ingresa en el registro r10, y luego hay un montón de código complejo para comparaciones para controlar excepciones como división de pánico e índice de pánico. Destaqué la rama de ejecución del programa.

imagen

Por lo tanto, un byte de una cadena especificada estáticamente se coloca en EDX y pelea con r10, donde es el byte del segmento. A continuación, el contador r9 aumenta. Es probable que se necesiten dos bloques adyacentes del medio para controlar la longitud del corte.

Combinemos todo: la línea ingresada está contaminada con un corte y se compara con una línea especificada estáticamente. Proxy para encontrar la contraseña correcta.

imagen

Recibimos la respuesta. La complejidad del reverso de los binarios Go es que existen factores complicados como la ausencia de un carácter nulo al final de las líneas, la presentación de sus tipos, el recolector de basura, etc.

Eso es todo por ahora. Continuará ... Puede unirse a nosotros en Telegram . Allí puede proponer sus propios temas y votar sobre la elección de los temas para los siguientes artículos.

Source: https://habr.com/ru/post/474656/


All Articles