Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Intro
This crackme is for the crack challenge 6 of canyouhack.it.
In this crackme the goal is to turn on all the lights. Note that a light off to the next, so if we interrupt this, we win.
Tools
Exeinfo (For crackme info)
Delphi Decompiler (For decompile)
OllyDbg (For debug)
Decompiling
With Delphi Decompiler we can found easy the buttons and his offsets.
Go to the offset 401A64 in OllyDbg and analyze the code.
We view two jumps, one turn ON the light and the other Turn OFF the next light. Patching the call from offset 401A8B we get the serial.
Los retos de criptografía pueden ser muy variados como he dicho anteriormente. El secreto suele estar en saber a que te enfrentas y posteriormente construir una herramienta para descifrarlo o usar una ya existente (la mayoría de los casos).
Una web con la que suelo resolver la mayoría de retos es dcode.fr. Si os fijáis en el enlace, la lista de categorías asciende a 48 y disponéis de unos 800 algoritmos para rebanaros los sesos.
A continuación veamos unos cuantos retos que podéis encontrar por la red. Cabe destacar que normalmente el título del reto dice mucho del algoritmo.
Solución: Aquí nuestro primer impulso es utilizar fuerza bruta a MD5, pero cuando nos damos contra la pared el siguiente candidato es LAN Manager. Aquí la opción que más os guste, Cain, John The Ripper, etc.
Con John The Ripper tenemos que preparar un archivo de texto del estilo: deurus.info:1011:4C240DDAB17D1796AAD3B435B51404EE:4C240DDAB17D1796AAD3B435B51404EE:::
Solución: Para la primera parte la conversión es directa. Para la segunda, la dificultad reside en darse cuenta que hay que separar en grupos de cinco y decodificar por separado.
Conversiones, cifra clásica, hash, simétricos, asimétricos, combinaciones de varios algoritmos y un largo etcetera. Como veis los hay para todos los gustos, ten en cuenta que aquí os muestro una pequeñísima parte de lo que os encontrareis en las webs de retos, pero para despertar la curiosidad es suficiente.
Acabo de montar AperiSolve en una Raspi que tenía por casa pensando que sería coser y cantar, pero me he encontrado con que el repositorio no estaba preparado para todas las distros Linux de forma estándar. El resultado lo he colgado en Github, de modo que para montarlo en vuestra propia Raspi solo tenéis que seguir estos pasos:
1. Clonar el repositorio
git clone https://github.com/deurus/AperiSolve-Raspi3.git
cd AperiSolve-Raspi3/AperiSolve
2. Construir los contenedores
docker compose build
docker compose up -d
3. Abrir la web
http://<IP_RASPI>:5000
Si tenéis curiosidad de la adaptación que he tenido que hacer aquí están los pasos que he seguido:
1. Preparar el sistema
sudo apt update
sudo apt install -y git docker.io docker-compose
sudo usermod -aG docker $USER
newgrp docker
2. Clonar AperiSolve
git clone https://github.com/Zeecka/AperiSolve.git
cd AperiSolve
3. Crear la estructura de build para la imagen ARM/x86
nano docker-compose.yml
y pega este contenido:
FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
zip \
p7zip-full \
binwalk \
foremost \
exiftool \
steghide \
ruby \
binutils \
pngcheck \
&& rm -rf /var/lib/apt/lists/*
COPY aperisolve/ /aperisolve/
RUN pip install --no-cache-dir -r /aperisolve/requirements.txt
WORKDIR /aperisolve
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "wsgi:app"]
4. Arreglar docker-compose.yml para ser válido y compatible
services:
web:
image: aperisolve-local
build: .
container_name: aperisolve-web
ports:
- "5000:5000"
depends_on:
- redis
- postgres
environment:
DB_URI: "postgresql://aperiuser:aperipass@postgres:5432/aperisolve"
worker:
image: aperisolve-local
container_name: aperisolve-worker
depends_on:
- redis
- postgres
environment:
DB_URI: "postgresql://aperiuser:aperipass@postgres:5432/aperisolve"
redis:
image: redis:7
container_name: aperisolve-redis
postgres:
image: postgres:16
container_name: aperisolve-postgres
environment:
POSTGRES_USER: aperiuser
POSTGRES_PASSWORD: aperipass
POSTGRES_DB: aperisolve
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
5. Modificar aperisolve/config.py
nano config.py
y pega este contenido:
from pathlib import Path
IMAGE_EXTENSIONS = [".png", ".jpg", ".jpeg", ".gif", ".bmp", ".webp", ".tiff"]
WORKER_FILES = ["binwalk", "foremost", "steghide", "zsteg"]
RESULT_FOLDER = Path(__file__).parent.resolve() / "results"
RESULT_FOLDER.mkdir(parents=True, exist_ok=True)
6. Modificación de aperisolve/app.py
Sustituir la línea: app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DB_URI")
por:
default_db = "postgresql://aperiuser:aperipass@postgres:5432/aperisolve"
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("DB_URI", default_db)
7. Construir la imagen
docker build -t aperisolve-local .
8. Levantar los contenedores
docker compose down
docker compose up -d
9. Comprobar logs
docker logs aperisolve-web --tail=50
docker logs aperisolve-worker --tail=50
10. Acceder a la web
- Desde cualquier máquina de la red local: http://IP-DE-LA-MAQUINA:5000
- Desde la Raspi: http://localhost:5000
11. Limpieza (cuando necesites)
- Reiniciar contenedores:
docker compose restart
- Borrar resultados antiguos:
sudo rm -r aperisolve/results/*
Hoy vamos a enfrentarnos a cuatro retos de esteganografía relativamente sencillos, y digo relativamente, debido a que hay tantas formas de esconder información en un archivo, ya sea imagen, vídeo o sonido, que afrontarlos suele ser desesperante. Las cuatro imágenes son aparentemente las mismas que la que se ve en portada.
Una buena práctica cuando te enfrentas a retos stego de tipo imagen es realizar una búsqueda inversa. Una búsqueda inversa consiste en buscar la imagen original mediante buscadores especializados como TinEye o Google. Si conseguimos la imagen original podemos resolver el reto simplemente comparando o nos puede dar una idea del tipo de modificación por su diferencia de tamaño, colores, degradados, etc.
Stego 1
Descargamos la imagen del reto. Se trata de una imagen JPEG de 526×263 y 76.6 KB (78445 bytes). Su hash SHA1 es «89aed5bbc3542bf5c60c4c318fe99cb1489f267a«
Realizamos una búsqueda inversa de la imagen y encontramos sin dificultad la imagen original mediante TinEye.
Por lo que vemos ha cambiado el tamaño de 78447 bytes a 78445 bytes y su hash SHA1 tampoco coincide obviamente, lo que nos confirma que ha sufrido alguna modificación. Echando un vistazo con un editor hexadecimal te puedes volver loco por lo que vamos a realizar una comparación mediante la herramienta online DiffNow.
Al realizar la comparación sale a relucir lo que buscamos. La clave es una simple cadena de texto.
Stego 2
Lo primero es realizar de nuevo la comparación.
Imagen
Tamaño
SHA1
Original
78447 bytes
8924676317077fc07c252ddeec04bd2a0ecfdda4
imagen2.jpeg
116386 bytes
7641e3906f795c137269cefef29f30fcb9cb1b07
Como vemos, la imagen ha aumentado significativamente, de 76,6 KB a 113 KB. Cuando el aumento de tamaño llama la atención normalmente tenemos otro archivo insertado. Lo primero que suelo hacer yo es fijarme si ha sido modificado el final del archivo con un editor hexadecimal. Los bytes de cola de un archivo jpg/jpeg son FFD9 y en este caso no vemos modificación alguna al final del archivo. Si el archivo no está al final requiere realizar una búsqueda más exhaustiva. Para estos casos tengo una herramienta de creación propia que se llama Ancillary y que sirve para buscar cierto tipo de archivos dentro de otros como imágenes, documentos de Office, Open Office, pdf, etc. Ancillary encuentra otro jpg que es el que le daba el peso extra y que vemos a continuación. La clave es el título de la película (ojo a las mayúsculas/minúsculas).
Stego 3
El tercer reto parece que tiene algún error debido a que el archivo coincide completamente con el original. Pienso que se ha subido la imagen original por error. Se lo he comunicado al admin del dominio y si algún día obtengo respuesta actualizaré la entrada.
Imagen
Tamaño
SHA1
Original
78447 bytes
8924676317077fc07c252ddeec04bd2a0ecfdda4
imagen3.jpeg
78447 bytes
8924676317077fc07c252ddeec04bd2a0ecfdda4
Actualización 21/08/2016
Al parecer, la solución de este reto es llegar a la conclusión de que la imagen no está modificada. La respuesta del Administrador de la web así lo confirma.
desingsecurity [at] gmail [dot] com – Sorry about the delay, is precisely what is intended with that challenge, they can determine if the image is changed or not , the challenge was solved you . We’ll be equal way improving this point.
Greetings and Thanks
Stego 4
Lo primero es realizar de nuevo la comparación.
Imagen
Tamaño
SHA1
Original
78447 bytes
8924676317077fc07c252ddeec04bd2a0ecfdda4
imagen4.jpeg
93174 bytes
a6329ea4562ef997e5afd067f3b53bdab4665851
Al igual que en el caso dos el tamaño ha aumentado significativamente de modo que miramos al final del archivo y esta vez si vemos que hay insertado unos bytes tras el final del jpg (recordemos FFD9)
El archivo tiene pinta de ser una hoja de cálculo de Open Office o Libre Office según indica la palabra «spreadsheet«. Lo abrimos con Excel y tras analizar la maraña de datos enseguida vemos una clave que llama la atención.
Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.
Resumen RSA
Parámetros
p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))
De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.
Funciones de Cifrado/Descifrado
cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n
OllyDbg
Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.
Referencias de texto
A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.
A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.
descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933
Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.
Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.
Obteniendo p, q y d
Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.
cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885
SERIAL = 71676223196885