index.html (3318B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Descifrado de .zip protegido mediante diccionario de DNIs</title> 7 <link rel="icon" type="image/png" href="/favicon.png" /> 8 <link rel="stylesheet" type="text/css" href="../article.css" /> 9 </head> 10 <body> 11 <header> 12 <p class="title">Descifrado de <i>.zip</i> protegido mediante diccionario de DNIs</p> 13 <p class="date">12 de septiembre de 2016 • fjbalon</p> 14 </header> 15 <p>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:</p> 16 <p>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:</p> 17 18 <math xmlns="http://www.w3.org/1998/Math/MathML" alttext="n\bmod 23=n-23\lfloor\frac{n}{23}\rfloor" display="block"> 19 <mrow> 20 <mrow> 21 <mi>n</mi> 22 <mo lspace="2.5pt" rspace="2.5pt">mod</mo> 23 <mn>23</mn> 24 </mrow> 25 <mo>=</mo> 26 <mrow> 27 <mi>n</mi> 28 <mo>-</mo> 29 <mrow> 30 <mn>23</mn> 31 <mo></mo> 32 <mrow> 33 <mo stretchy="false">⌊</mo> 34 <mfrac> 35 <mi>n</mi> 36 <mn>23</mn> 37 </mfrac> 38 <mo stretchy="false">⌋</mo> 39 </mrow> 40 </mrow> 41 </mrow> 42 </mrow> 43 </math> 44 <p>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:</p> 45 46 <pre><code>mod 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 47 array T R W A G M Y F P D X B N J Z S Q V H L C K E</code></pre> 48 <p>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.</p> 49 <pre><code>#!/bin/python 50 def calculate_letter(nif): 51 seq = 'TRWAGMYFPDXBNJZSQVHLCKE' 52 return seq[nif % len(seq)] 53 54 def generate_nif(d): 55 return str(d).rjust(8,'0') + calculate_letter(d) + "\n" 56 57 with open("dni.code","w") as f: 58 for i in range(100000000): 59 print(generate_nif(i)) 60 f.write(generate_nif(i)) 61 f.closed</code></pre> 62 <p>Después, usaremos la herramienta <a href="https://www.kali.org/tools/fcrackzip/">fcrackzip</a> para probar cada una de las palabras del diccionario.</p> 63 64 <pre><code>$ fcrackzip -v -u -D -p dni.code crypted.zip 65 found file 'secret.pdf', (size cp/uc 254198/262378, flags 9) 66 checking pw 00000000T 67 checking pw 00000001R 68 checking pw 00000002W 69 70 [...] 71 72 PASSWORD FOUND!!!!: pw == 84671735H</code></pre> 73 <p>Owned!</p> 74 75 </body> 76 </html>