Hace unos días se me ocurrió una idea de algo que programar en Python. Crear una herramienta en Python que ayude a descifrar hashes MD5
No suelo programar mucho, precisamente por eso, por falta de ideas. Pero hace un par de días estaba viendo un vídeo de YouTube acerca de Ethical Hacking, y los hashes en MD5 llamaron mi atención.
Este tipo de hashes son irrevertibles, es decir, podemos cifrar una cadena de texto en MD5 fácilmente. Sin embargo, no podemos averiguar la cadena que se esconde detrás de un hash de este tipo, a no ser que tengamos una cadena con la que compararla.
Es por ello que me decidí a investigar un poco más sobre hashes MD5.
Índice
¿Qué son los hashes MD5?
MD5 es un algoritmo creado por Ronald Rivest y cuyo significado es «Message Digest Algorithm 5». En él se cifra una cadena cualquiera en otra cadena de 32 caracteres (128 bits).
Uno de los usos que más se da a este algoritmo es para comprobar que los archivos que han pasado de un usuario a otro no han sido alterados. Si comparamos el hash del archivo de salida con el del archivo de llegada y son distintos, se debe a que ha habido alguna alteración en el archivo durante el envío.
Mi idea fue crear un programa en Python que creara todos los hashes MD5 de un diccionario de contraseñas dado. Por otra parte, también debía descubrir una contraseña dado un hash que estuviera en ese archivo resultante.
Es decir, el objetivo es crear un diccionario de hashes para poder comprobar si un hash se encuentra en dicho diccionario. Si es así, el algoritmo debe devolver la contraseña asociada a ese hash.
Con esta pequeña explicación, voy a proceder a mostraros el código. Este algoritmo guarda los hashes de una lista de contraseñas de un archivo en otro archivo.
Primera parte: Guardando los hashes MD5
import hashlib
def to_md5():
file1 = input("Introduce la ruta del archivo del diccionario de contraseñas: ")
file2 = input("Introduce la ruta del archivo donde quieres guardar los hashes: ")
f = open(file1, "r", encoding='latin-1')
h = open(file2, "a")
for line in f:
string_to_hash = line
hash_md5 = hashlib.md5(str(string_to_hash).encode('utf-8'))
h.write(hash_md5.hexdigest() + "\n")
Explicación
En esta primera parte del código, leemos dos rutas de archivo. El primer archivo es el diccionario de contraseñas ya creado, como puede ser por ejemplo «rockyou». El segundo archivo guardará los hashes de dichas contraseñas.
Una vez hemos abierto ambos archivos, el algoritmo procede a cifrar en MD5 cada una de las líneas del diccionario. En cada línea ha de haber una cadena de texto, ya sea una palabra o una frase.
El hecho es que al final del algoritmo, se guardan en el segundo archivo todos los hashes creados, uno por cada línea de texto del archivo .txt pasado.
Con esto conseguimos un archivo con todos los hashes. Personalmente, he probado el algoritmo con diccionarios propios y con rockyou, y funciona.
Para usar la función, solo hemos de llamarla con to_md5() y ella misma nos pedirá los archivos de origen y destino.
Segunda parte: Descubriendo contraseñas
def check_md5(hash):
file1 = input("Introduce la ruta del archivo de los hashes del diccionario: ")
file2 = input("Introduce la ruta del archivo del diccionario de contraseñas: ")
h = open(file1, 'r', encoding='latin-1')
p = open(file2, 'r', encoding='latin-1')
lineas1 = h.readlines()
lineas2 = p.readlines()
i = 0
for line in lineas1:
if hash in line:
print("El hash " + hash + " pertenece al password " + lineas2[i])
else:
i = i + 1
Explicación
En esta ocasión, llamaremos a la función check_md5 pasándole el hash que queremos comprobar como parámetro.
Al arrancar, nos pedirá la rutas de dos archivos. Ahora el primero es el archivo donde hemos guardado los hashes anteriores, en mi caso los creados con rockyou.txt. El segundo archivo es el diccionario de contraseñas, de donde extraerá la contraseña que coincida con ese hash.
El algoritmo comienza por abrir ambos archivos y leer todas sus líneas. Después lee cada línea del primer archivoy la compara con el hash pasado como parámetro. Si coincide, entonces nos devuelve la contraseña que hay en la misma línea del arhivo del diccionario. Si no coincide, pasa a la siguiente línea.
En caso de que el programa no devolviera respuesta, significaría que dicho hash no se encuentra en la lista. Eso quiere decir que no hay una contraseña en ese diccionario que coincida con ese hash.
Y bueno, hasta aquí mi post de hoy. Sé que ha sido algo breve, pero creo que puede ser útil para mucha gente tener este código que, aunque no es demasiado complicado, me ha llevado un buen rato diseñar. Espero que os sea de utilidad y no dudéis en visitar la sección Hacking y más para más tips y consejos.