Cómo realicé ingeniería inversa a la aplicación de mi profesor

Share
Cómo realicé ingeniería inversa a la aplicación de mi profesor
audio-thumbnail
Panic Track
0:00
/153.772698

Realizar ingeniería inversa a determinado software suele estar restringido y prohibido en los términos y condiciones de dicho software, y bajo ciertas circunstancias puede incluso ser ilegal, dependiendo de los desarrolladores y distribuidores. Quedas avisado.

Además, he hablado con mi profesor sobre esto. Aprueba la idea de compartir este conocimiento, por lo que le envío un agradecimiento especial por su apoyo.


¡Bienvenidos, mis queridos hackers! Últimamente he estado aprendiendo mucho sobre ingeniería inversa y me gustaría compartir cómo empezó todo, y quizá aprendas algo sobre ingeniería inversa de programas compilados en Python (sí, puedes hacerlo usando "pyinstaller" para empaquetarlo en un ejecutable o "cython" para convertir tu programa en Python en C y poder compilarlo). En esta publicación voy a tratar una librería útil para Python y dos herramientas para descomprimir los binarios de pyinstaller y así poder inspeccionar el código fuente, así que ¡vamos a entrar en ello!

¿Qué es PyInstaller?

PyInstaller es una librería y aplicación en Python que compila tu aplicación Python junto con sus dependencias en un único ejecutable. Usar PyInstaller tiene varias ventajas, la principal es que no necesitas un intérprete de Python para ejecutar tu aplicación. Por eso se utiliza a menudo para crear malware de baja calidad. Utilicé esta aplicación para empaquetar "marrow" (el servidor C2 que programé hace un tiempo) y lo usé en el script "generate_intruder", que genera un ejecutable para el agente "intruder" del C2 (por si te lo preguntas, planeo continuar su desarrollo, pero primero me gustaría aprender a crear malware adecuado usando C++ y WinAPI, y luego, reanudar el desarrollo usando un agente codificado en C/C++).

Mientras cubrimos esta anécdota, descubrirás cómo PyInstaller empaqueta todo en un único ejecutable y cómo logré saltarme la seguridad del programa de mi profesor.

¿Cual es el propósito de la app?

La aplicación se llama "safe_exam" y se utiliza para controlar las pantallas del usuario y forzar que la página web cubra toda la pantalla, bloqueándola y impidiendo que el usuario cambie ventanas o pestañas, bloqueando todas las demás aplicaciones, obligando la pestaña de navegación a cubrir todas las demás apps. Además, te impide buscar nada porque elimina la barra de búsqueda de la ventana y solo te permite ver la página web donde se realizan los exámenes.

Explicación de la lógica de la aplicación

Para representarlo mejor, imagina que he instalado un navegador (en mi caso, "Librewolf"). Cuando abro Librewolf, así es como se ve:

La imagen de fondo es el fondo de pantalla de mi administrador de ventanas (Window Manager en inglés); en la parte superior tengo los widgets para echar un vistazo rápido a la información que necesito saber sobre mi PC, por ejemplo, la fecha, los MB de memoria consumidos, el porcentaje de uso de la CPU, el volumen, la carga de la batería, etc.

Cuando ejecuto el programa de mi profesor, aparece esto:

Te pide que introduzcas tu nombre antes de empezar el examen. Esto se hace porque, tras analizar la ejecución de la aplicación, me di cuenta de que la app genera registros que el profesor puede recuperar para comprobar qué ha hecho cada persona durante el examen (por ejemplo, si alguien empezó el examen, terminó o copió). El profesor, que tiene acceso a todos los ordenadores del aula, puede conectarse a nuestros ordenadores usando el protocolo SSH o incluso descargar los registros directamente usando el comando "scp", que para quienes no lo sepan, se utiliza para transferir archivos a través de la red mediante una comunicación cifrada.

Después de pulsar el botón "Iniciar examen" me envían a la página web del examen, que luego se muestra en una ventana creada por la aplicación que se escala automáticamente a la resolución de tu pantalla. En este caso, no puedo acceder al examen porque ya lo he hecho (y lo he aprobado), pero mostraría una serie de preguntas que tendría que responder. Así es como se ve.

A estas alturas quizá pensabas que alguien podría pulsar "alt + tab" para cambiar su ventana y buscar información en internet. Pues no, porque la app también bloquea esa combinación de teclas. Puede que estés pensando, "entonces minimiza la ventana", bueno, no tiene ningún botón para minimizar (claro, ¿por qué iba a tenerlo?), y además si sales del examen, no puedes volver a entrar porque cuenta como si ya lo hubieras hecho, y no solo eso, si sales del examen antes de terminarlo (forzando la salida de la solicitud), Las respuestas se envían todas como vacías, lo que significa suspender el examen al instante.

Aunque consigas cambiar la ventana, si la aplicación pierde el "enfoque" (lo explicaré más adelante), bloquea el acceso al examen y te dice que contactes con el profesor para desbloquear la pantalla, lo que significa, de nuevo, en un suspenso instantáneo porque eso significa que intentabas copiar o, al menos, actuaste de forma sospechosa.

Una solución alternativa a esta medida de seguridad

Antes de explicar esta parte, primero necesito que entiendas el concepto del que hemos hablado antes llamado "Enfoque".

Enfoque significa, en el contexto de aplicaciones de escritorio, cuando cambias tu interacción a otra ventana. Para representarlo, imagina que estás escribiendo en tu editor de texto (por ejemplo, "Bloc de notas") y luego seleccionas la ventana del navegador (por ejemplo, "Chrome") para buscar algo en internet. Eso significa que el Bloc de Notas está perdiendo enfoque y Chrome está ganando enfoque. Cuando interactúas con una ventana, esta gana enfoque, y cuando interactúas con otra, pierde enfoque. Así es como el programa sabe si has conseguido cambiar la ventana.

Ahora bien, ¿cómo es posible hacer ingeniería inversa de algo así? Literalmente bloquea tu pantalla y no puedes escribir ni ver nada que no sea una página web de examen. Lo conseguí gracias al poder de mi increíble gestor de ventanas llamado "Awesome" y a la ayuda de los "espacios de trabajo". Piénsalo como diferentes pantallas que puedes navegar a tu gusto y poner ciertas aplicaciones en cada una de ellas.

Así que si abro la aplicación en el espacio de trabajo "1" y luego cambio al espacio "2" pulsando "Super" (tecla Windows) + "2", y vuelvo al espacio de trabajo "1" pulsando "Super" + "1". Puedo interactuar libremente con mi terminal en el espacio de trabajo "2" porque la aplicación de examen está ejecutada en el espacio de trabajo "1". Sin embargo, cambiar de espacio de trabajo significa perder el enfoque en la aplicación del examen, lo que bloquea el programa y me impide continuar con el examen. Así es como se ve cuando la pantalla se bloquea al intentar cambiar de espacio de trabajo para volver a la aplicación (aunque en español dice que salí del "modo examen" muchas veces, solo cambié el enfoque una vez y se bloqueó).

Aquí es donde empieza lo interesante.

La única contra-medida que queda, la ingeniería inversa

¿Recuerdas cuando dije antes que, si la aplicación bloquea tu acceso al examen, tienes que llamar al profesor para desbloquear la pantalla? Eso significa que debe haber una función dentro del código que desbloquee tu sesión y te permita reanudar el examen, por lo que puedes buscar lo que quieras en internet sin importar las veces que hayas bloqueado el examen. ¿Recuerdas también los registros de los que hablaba antes? Lo único que tienes que hacer es crear un script bash simple de menos de 100 líneas para detectar este tipo de entradas dentro del log:

Y bórralas usando un bucle que compruebe cada 0,1 segundos si esa expresión existe, y si existe, borra las líneas de advertencias y sesiones bloqueadas.

Comenzando con la ingeniería inversa

Primero, empecé a comprobar qué tipo de archivo estaba manejando. Para eso, usé el comando "file".

Como podemos ver, es un archivo ejecutable (nada sorprendente teniendo en cuenta que ya ejecutamos la aplicación antes). Está en formato ELF. Sabía que el script estaba escrito en Python porque el propio repositorio del que nuestro profesor nos dijo que descargaramos el binario lo indica.

Ahora, sabiendo esto, hay algunas herramientas de Python que te permiten extraer el paquete ejecutable a su código fuente para analizarlo. La primera herramienta que utilicé para comprobar si podía encontrar algo o no se llama "pyi-archive_viewer", que te permite ver qué hay dentro del ejecutable empaquetado. Lo usé así:

pyi-archive_viewer -l ./safe_exam | less

Y me dió la siguiente salida:

Si has analizado la imagen atentamente, puede que ya hayas visto cosas interesantes. Lo primero que llamó mi atención fue esto:

La 's' indica que es un script (un programa), y que el nombre 'exam' puede indicar que es el script principal. De hecho, tenía razón. ¿Por qué digo esto? Porque usé otra herramienta llamada pyinstxtractor-ng para extraer los contextos del binario y poder comprobarlos.

Ahora solo tenía que mirar "exam.pyc". Sin embargo, como estaba compilado, tuve que usar un descompilador para poder leer el código, porque se veía así.

Esto, por supuesto, es ilegible, pero pude ver algunas secuencias que indicaban que este era el código que se usaba para bloquear/desbloquear la pantalla durante el examen gracias a esta frase;

Revirtiendo la aplicación a código pseudo-ensamblador

Ahora, para poder leer el código, debo volver a ensamblar el código compilado. Esto se puede hacer usando un script sencillo con la librería "marshal" para convertir el código compilado en código pseudo-ensamblador. Dejaré el código abajo para que veáis lo fácil que es hacerlo.

#!/usr/bin/env python3

import argparse
import marshal
import dis

parser = argparse.ArgumentParser(
    prog='decompylex',
    description='Turn .pyc files into readable pseudo-assembly code',
    epilog='Thanks for supporting me!',
    formatter_class=argparse.RawTextHelpFormatter,
    )

parser.add_argument('file')
args = parser.parse_args()

# Load a .pyc file
with open(args.file, 'rb') as f:
    f.read(16)
    code_obj = marshal.load(f)

# Disassemble the code object
dis.dis(code_obj)

Con esto, solo tendrías que crear el archivo nombrándolo como decompilex.py o como quieras llamarlo, y luego ejecutarlo.

./decompilex.py safe_exam_extracted/exam.pyc 

Esto me permitió revisar el código pseudo-ensamblador. Para que veas cómo es, esta es una captura de pantalla de ejemplo del cóígo desensamblado exam.pyc:

Ahora solo tengo que buscar la cadena anterior que vi antes y, aplicando lógica de programación, si aparece un mensaje que literalmente dice "Sesión de examen desbloqueada por el profesor", lo que desbloquea la sesión debe estar encima del mensaje.

Y como dije antes, encima de esa línea hay una combinación de teclas.

Pulsar estas combinaciones de teclas permite al estudiante continuar el examen, teniendo así la posibilidad de hacer trampas y borrar registros por sí mismo.

Si tienes alguna pregunta, puedes dejarla abajo. ¡Gracias por leer, y que te diviertas hackeando!

Read more