Descifrado de .zip protegido mediante diccionario de DNIs

12 de septiembre de 2016 • fjbalon

Me he encontrado con esta prueba de concepto: debía descifrar un archivo comprimido ZIP que contenía un PDF secreto, que sólo podría abrir la persona propietaria. Llevando a cabo una breve investigación, descubro que la clave es siempre el DNI (Documento Nacional de Identidad -en España-), formado por ocho dígitos y un carácter alfabético de control, del propietario. Esto facilita las cosas, pues sabemos cómo se compone:

El carácter alfabético se obtiene a partir del resto de la división entre número completo y 23. Así, donde n es el número:

n mod 23 = n - 23 n 23

Al resto resultante de dicha división, que estará comprendido entre 0 y 22, se le asigna la letra de control según una equivalencia. Las equivalencias son:

mod     0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22
array   T   R   W   A   G   M   Y   F   P   D   X   B   N   J   Z   S   Q   V   H   L   C   K   E

Entonces, escribimos un pequeño código en Python que itera todas las posibilidades de DNI habidas (100.000.000), y de cada una calcula su carácter de control. Además, escribirá cada opción en un fichero dni.code, obteniendo así el diccionario.

#!/bin/python
def calculate_letter(nif):
    seq = 'TRWAGMYFPDXBNJZSQVHLCKE'
    return seq[nif % len(seq)]

def generate_nif(d):
    return str(d).rjust(8,'0') + calculate_letter(d) + "\n"

with open("dni.code","w") as f:
    for i in range(100000000):
        print(generate_nif(i))
        f.write(generate_nif(i))
f.closed

Después, usaremos la herramienta fcrackzip para probar cada una de las palabras del diccionario.

$ fcrackzip -v -u -D -p dni.code crypted.zip
found file 'secret.pdf', (size cp/uc 254198/262378, flags 9)
checking pw 00000000T
checking pw 00000001R
checking pw 00000002W

[...]

PASSWORD FOUND!!!!: pw == 84671735H

Owned!