Datos del reto
| Campo | Valor |
|---|---|
| CTF | Nullcon CTF 2026 |
| Reto | Matrixfun II |
| Categoría | Crypto |
| Flag | ENO{l1ne4r_alg3br4_i5_ev3rywh3re} |
Descripción del reto
El servidor cifraba bloques sobre el alfabeto Base64 usando una transformación afín del estilo c = A·x + b (mod 65). Además, no solo mostraba el ciphertext de la flag: también dejaba cifrar mensajes arbitrarios con la misma clave. Ese servicio de cifrado era justo lo que hacía falta para reconstruir A y b.
Reconocimiento
Cada bloque de 16 símbolos Base64 se convertía a índices 0..64, y sobre ese vector el servidor aplicaba:
c = A·x + b (mod 65)
Cuando un esquema así te deja cifrar texto elegido con la misma matriz y el mismo vector, recuperar la clave suele ser cuestión de mandar bloques bien preparados.
Análisis
Había dos observaciones sencillas:
- Si el bloque de entrada es todo ceros, la salida es directamente
b. - Si el bloque de entrada tiene un único
1en la posiciónj, la salida es la columnajdeAsumada conb.
Como en Base64 el índice 0 corresponde a 'a', bastaba construir mensajes cuya primera salida en Base64 representara:
aaaaaaaaaaaaaaaapara obtenerb;- un bloque con un único
1en la posición deseada para recuperar cada columna deA.
Con b y las 16 columnas de A, ya solo faltaba invertir la matriz módulo 65 y descifrar el ciphertext inicial.
Resolución
El procedimiento completo fue:
- Guardar el ciphertext de la flag.
- Pedir el cifrado de un bloque que se traduzca a 16 ceros y extraer
b. - Repetir el proceso 16 veces con bloques que tengan un único
1para recuperar cada columna deA. - Calcular
A^-1 mod 65. - Aplicar
x = A^-1(c - b)a cada bloque del ciphertext. - Reconstruir la cadena Base64 y decodificarla.
En el código, la parte importante era una función para recuperar A y b desde el servicio, otra para invertir matrices módulo 65 y una última para transformar los bloques cifrados de vuelta al texto original.
Flag
ENO{l1ne4r_alg3br4_i5_ev3rywh3re}