Crypt-Decrypt Tool

Colaborador: Vasco

Buenos días hackers, ésta es la primera, de una serie de entradas, en las que mostraré algunos de los scripts que tengo hechos en Python y mediante los cuales he ido aprendiendo a programar. «La práctica hace al maestro«.

Quiero dejar claro que no soy un experto programador, como he dicho antes, he ido aprendiendo a base de hacer scripts y sigo aprendiendo, por tanto es posible que el código tenga errores o haya mejores formas de hacer lo mismo. Se admiten todo tipo de consejos, críticas, modificaciones, etc.

Dicho esto continuamos. En la entrada de hoy traigo un script mediante el cual vamos a poder cifrar o descifrar varios tipos de hash. ¿Cuantas veces hemos tenido que probar un hash en varias webs para descifrarlo?. Pues eso es lo que hace Crypt-Decrypt, prueba un hash o hashes dado/s en varias webs con el fin de que alguna consiga descifrarlo, además de otras opciones que iremos viendo.
Como todos los scripts, tenemos la ayuda con las diferentes opciones disponibles.


Además si escribimos solo ./crypt-decrypt  nos muestra los ejemplos de uso.


Vamos a ir viendo las diferentes partes del código para conocer su funcionamiento.

from argparse import ArgumentParser
import urllib2
import urllib
import re
import os
import commands
import hashlib
from passlib.hash import lmhash
import binascii

 

  • Argparse: es el encargado de leer los argumentos que le pasamos al script al ejecutarlo. Además genera automáticamente la ayuda y mensajes de error de uso del mismo.
  • Urllib/Urllib2: mediante estos dos módulos podemos hacer consultas a webs. Soportan varios protocolos como pueden ser HTTP, HTTPS, FTP, etc.
  • Re: nos permite buscar subcadenas en un texto mediante expresiones regulares o patrones, similar a «found» en Perl. En este caso lo utilizo para buscar la línea con el resultado del hash en el código html que nos devuelven las webs.
  • Os: podemos acceder a funcionalidades del Sistema Operativo: información sobre el mismo, manipulación de archivos y directorios, variables de entorno, etc.
  • Commands: no va permitir ejecutar comandos externos, los que ejecutaríamos por consola. Esto mismo podemos hacerlo con  Os, pero con Commands y su opción .getoutput me resulta muy fácil obtener la salida de dicho comando, para así poder guardarla en una variable y consultarla o editarla cuando lo necesite.
  • Hashlib: permite realizar cifrados con algoritmos como Md5, Sha1, Sha224, Sha256, Sha384 y Sha512.
  • Passlib: disponible para Python 2 y 3, proporciona implementaciones para mas de 30 algoritmos de hashing, así como administración de hashes existentes o la verificación de un hash en el archivo /etc/shadow.
  • Binascii: dispone de varios métodos para convertir entre binario y ascii. Se usa normalmente junto con módulos como base64, binhex, etc.

 

La primera opción que vamos a ver es descifrar los hashes, podemos hacerlo tanto de forma online (consultando webs) u offline (mediante fuerza bruta con diccionario). En el caso de la opción online, he creado varias funciones que hacen las consultas a las webs. Todas tienen la misma estructura, la diferencia es la url y el texto a buscar (puesto que cada web tiene un código html diferente).

def md5OnDecrypt(hashs):
     website = 'http://md5decryption.com/'
     weburl = urllib.urlencode({'hash': hashs, 'submit': 'Decrypt+It!'})
     req = urllib2.Request(website)
     try:
          fd = urllib2.urlopen(req, weburl)
	  data = fd.read()
	  match = re.search(r'(Decrypted Text: </b>)(.+[^>])(</font><br/><center>)', data)
	  if match:
	       print(colors.GREEN + " [i]" + colors.INFO + " Site: " + colors.ENDC + website + colors.INFO + "\t\t Password: " + colors.GREEN + (match.group(2)) + colors.ENDC)
	  else:
	       print(colors.FAIL + " [!]" + colors.INFO + " Site: " + colors.ENDC + website + colors.INFO + "\t\t Password: " + colors.FAIL + "Not found" + colors.ENDC)
     except urllib2.URLError:
	  print(" [!]" + colors.INFO + " Site: " + colors.ENDC + website + colors.FAIL + "\t\tError: seems to be down" + colors.ENDC)

 

  • Linea 1: declaramos la variable website con la url de la web.
  • Linea 2: codificamos con el método urlencode los parámetros que necesitamos enviar a la web.
  • Linea 3: el objeto Request representa la petición HTTP que se está realizando. Si no se incluyen datos, sería una petición GET, en el caso de incluirlos, se trata de una petición POST.
  • Linea 4: mediante urlopen creamos un objeto parecido a un archivo con el html de la respuesta web. Le pasamos los argumentos request y weburl antes creados.
  • Linea 5: leemos el contenido del objeto creado anteriormente y lo asignamos a la variable data.
  • Linea 6: con el módulo re buscamos la línea donde se encuentra nuestro hash descifrarlo.
  • Linea 7 y siguientes: en caso de tener una coincidencia en la línea anterior, imprimimos por pantalla la url y el hash descifrado. En caso contrario, mostramos un mensaje de «Not Found».

Vamos a ver algunos ejemplos de uso para esta opción.

Descifrar Md5 online.

  • -d : indica que queremos descifrar un hash.
  • -o : modo online.
  • -t : tipo de algoritmo.
  • -w : hash a descifrar

 

Crypt-Decrypt también nos permite indicar un archivo con un hash por línea para descifrarlos mediante la opción -F .

Descifrar hashes Sha1 desde archivo.

 

Para el modo offline, consta solamente de dos funciones, una se encarga de descifrar el tipo LM mientras que la otra todos los demás tipos de algoritmos soportados.

 

def MultiOffDecrypt(hashs, wordlist, htype):
     try:
         if check_file(wordlist):
	      with open(wordlist) as wordlistfile:
	          for line in wordlistfile:
		      if htype == "md5":
		           algorithm = hashlib.md5()
		      elif htype == "sha1":
		           algorithm = hashlib.sha1()
		      elif htype == "sha224":
			   algorithm = hashlib.sha224()
		      elif htype == "sha256":
			   algorithm = hashlib.sha256()
		      elif htype == "sha384":
			   algorithm = hashlib.sha384()
		      elif htype == "sha512":
			   algorithm = hashlib.sha512()
		      else:
			   print(colors.FAIL + colors.BOLD + "\n[!] Error hash type!!" + colors.ENDC)
                      line = line.replace("\n", "")
		      algorithm.update(line)
		      wordlistdecrypted = algorithm.hexdigest()
		      if wordlistdecrypted == hashs:
			   print(colors.GREEN + " [i]" + colors.INFO + " Password: " + colors.GREEN + line + colors.ENDC + "\n")
		      else:
			   print(colors.FAIL + colors.BOLD + "\n[!] Dicctionary not found!!" + colors.ENDC)
     except:
          print(colors.BOLD + colors.FAIL + "\n\t[!] Error \n" + colors.ENDC)

 

En esta función se utiliza la librería Hashlib para cifrar las palabras del diccionario y comparar el hash resultante con que deseamos descifrar. Le pasamos tres argumentos:

  • hashs : el hash para descifrar.
  • wordlist : archivo del diccionario.
  • htype : tipo de algoritmo del hash.

Explicación del código.

  • Linea 1: check_file es una pequeña función que comprueba si existe un archivo, en este caso el diccionario indicado.
  • Linea 2: si existe, lo abrimos para leerlo.
  • Linea 3: por cada linea en el diccionario hacemos lo siguiente…
  • Linea 4 – 17: comprobamos el tipo de algoritmo para actuar en consecuencia.
  • Linea 18: quitamos el salto de linea que hay al final de cada palabra.
  • Linea 19 – 20: ciframos la palabra.
  • Linea 21…: comparamos si los hashes son iguales, de ser así, muestra el resultado.

Algunos ejemplos de uso.

Descifrar Sha1 offline.

Indicamos modo offline con -f y añadimos el argumento -l para indicar el diccionario, por lo demás es igual que con el modo online. También podemos leer los hashes desde un archivo (deben ser todos del mismo tipo).

Descifrar hashes Sha1 desde archivo.

Si os fijáis, hay un hash que no ha descifrado (porque no estaba incluido en el diccionario). En este caso no muestra ningún mensaje de error porque entonces lo haría con cada palabra del diccionario, lo que puede ser una locura.

 

Hasta aquí la parte de descifrar hashes. Ahora vamos a ver el caso contrario, Crypt-Decrypt también cuenta con la opción de cifrar pero esta vez solo de modo offline, para que vamos a conectarnos a internet si podemos hacerlo de forma offline…

En esta ocasión no ha sido necesario crear una función, basta con una linea de código y la librería Hashlib.

alg = args.type.lower()
word = args.word
print("\n [+]" + colors.INFO + " Word: " + colors.ENDC + word)
print(" [+]" + colors.INFO + " Type: " + colors.ENDC + alg)
if alg == "md5":
    encrypted = hashlib.md5(word).hexdigest()
    print(colors.GREEN + " [i]" + colors.INFO + " Hash: " + colors.GREEN + encrypted + colors.ENDC + "\n")
elif alg == "sha1":
    encrypted = hashlib.sha1(word).hexdigest()
    print(colors.GREEN + " [i]" + colors.INFO + " Hash: " + colors.GREEN + encrypted + colors.ENDC + "\n")

 

  • Linea 1: obtenemos el tipo de algoritmo y lo ponemos en minúsculas con lower().
  • Linea 2: asignamos a la variable word la palabra que deseamos cifrar.
  • Linea 3 – 4: mostramos palabra y tipo de hash.
  • Linea 5: en caso de que el tipo sea Md5…
  • Linea 6: ciframos con Hashlib en Md5 y asignamos el resultado a la variable encrypted.
  • Linea 7: muestra el hash por pantalla.

A continuación tenemos el caso del Sha1 que es exactamente igual que con Md5 pero con su tipo correspondiente, y así con todos los demás.
Ejemplos de uso.

Cifrar en Sha224.

 

Esta opción no cuenta con lectura desde archivo, no le veía ninguna utilidad. Lo que si podemos hacer es cifrar una sola palabra con todos los tipos de algoritmos disponibles mediante -a .

Cifrar con todos los algoritmos.

 

Por último nos queda la opción para identificar que tipo de hash/es estamos tratando. Para esto he usado el archiconocido script Hash-Identifier con algunas modificaciones personales para que encajara con el mio. La intención es llamarlo desde Crypt-Decrypt mediante commands.getoutput() pasándole el hash en cuestión y así guardar la salida en una variable, para ello, he eliminado el menú que aparece al ejecutarlo puesto que no es necesario y le pasamos el hash por linea de comandos.

if args.file:
    with open(args.file, 'r') as f:
         for h in f.readlines():
	     print("\n [+]" + colors.INFO + " Hash: " + colors.GREEN + h.strip("\n") + colors.ENDC)
	     r = commands.getoutput('./hash-identifier.py %s' % h.strip('\n'))
	     for x in r.split("\n"):
	         if not "Least Possible" in x:
		     print(x + "\n"),
		 else:
		     break
else:
     r = commands.getoutput('./hash-identifier.py %s' % args.word)
     print(r)

 

Al igual que con descifrar y cifrar, podemos pasarle un archivo con varios hashes para identificar, o indicarle solo uno.

  • Linea 1: en caso de que indiquemos un archivo…
  • Linea 2: lo abrimos para leerlo.
  • Linea 3: por cada linea o hash se ejecuta lo siguiente (hasta la linea 10).
  • Linea 4: lo mostramos por pantalla con print.
  • Linea 5: aquí es donde llamamos a Hash-Identifier pasándole el hash y guardamos la salida en la variable r . Mediante strip(«\n») lo que estamos haciendo es eliminar el salto de linea que hay al final de cada hash (pulsación de la tecla enter).
  • Linea 6 – 10: para no mostrar la salida entera de Hash-Identifier (puede ser muy larga en caso de que el archivo contenga muchos hashes) he hecho un bucle que imprime las primeras lineas hasta llegar a una concreta donde se detiene.
  • Linea 11…: esta parte es la que se ejecuta si le indicamos un solo hash. Simplemente lo manda a Hash-Identifier, guarda la salida y la muestra por pantalla.

Ejemplos de uso.

Identificar un solo hash.

Identificar hashes desde archivo.

En este último ejemplo, solo muestra los dos tipos mas probables de algoritmo de cada hash para no extender mucho el resultado.

 

En caso de que tengáis problemas con las librerías, he añadido un archivo installer.py que los instala automáticamente.

 

Hasta aquí la entrada de hoy, espero que os sea de utilidad y le deis uso al script. Una muy buena opción para añadir sería poder indicarle que identifique y descifre un hash dado o varios de una sola vez, además de añadirle mas webs (sin captcha) para que consulte, e incluso una barra de progreso (igual que la del script Steghide Brute Force Tool) según vaya leyendo el diccionario. Ahí lo dejo como posible tarea.

Un saludo, vasco.

6 comentarios en «Crypt-Decrypt Tool»

  1. Me ayudan con esto no se en que esta encriptado, la clave de mi router
    219e0e0c0c143e7e1c18ca857ac9c9fe025de86522faed184c4274dc49b3c4f8

    1. Hola Juan, si usas la opción «identify» del script verás que se trata de un Sha256, también he probado con alguna web y he obtenido el mismo resultado. Espero haberte sido de ayuda.

      Un saludo.

    1. Muchas gracias Sanpu, me alegro que te haya gustado, como digo en la entrada yo también he aprendido, y sigo aprendiendo, a base de leer código y modificar scripts.

      Un saludo.

  2. Hola Jonathan,
    me puedes guiar para modificar el script para que lea desde archivo y cada linea y genere según el tipo de algoritmo que se elija ?
    Gracias de antemano.
    Un saludo

Los comentarios están cerrados.