Convertidor de formato Python Hash -- python campo con python-3.x campo con parsing campo con formatting campo con hashcode camp codereview Relacionados El problema

Python hash format converter


10
vote

problema

Español

Este programa debe convertir un archivo que contenga MANA, hashcat o John los hashes Ripper NTLMV1 a otro archivo que contiene Hashcat o Juan los hashes de Ripper. ¿Tiene alguna sugerencia sobre cómo hacer que el código Cleaner? El código de selección de formato hash se siente un poco sucio.

  #!/usr/bin/env python3  # Takes a file of NTLMv1 hashes in mana format and spits out a #  file of hashes in JtR or hashcat format.   import sys import re  class Hash():     pass  class HashcatHash(Hash):     @staticmethod     def parse(line):         m = re.match("(.*?)::::([0-9a-f]{48}):([0-9a-f]{16})", line)         if m:             return {"username": m.group(1), "response": m.group(2), "challenge": m.group(3)}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         return "{username}::::{response}:{challenge}".format(             username=d["username"],             response=d["response"],             challenge=d["challenge"])  class JohnHash(Hash):     @staticmethod     def parse(line):         m = re.match("(.*?):$NETNTLM$([0-9a-f]{16})$([0-9a-f]{48})", line)         if m:             return {"username": m.group(1), "response": m.group(3), "challenge": m.group(2)}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         return "{username}:$NETNTLM${challenge}${response}".format(             username=d["username"],             response=d["response"],             challenge=d["challenge"])  class ManaHash(Hash):     @staticmethod     def parse(line):         m = re.match("CHAP|(.*?)|([0-9a-f:]{23})|([0-9a-f:]{71})", line)         if m:             return {"username": m.group(1), "response": remove_colons(m.group(3)), "challenge": remove_colons(m.group(2))}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         raise NotImplementedError  def print_usage():     print("Usage:")     print("exportlog.py <informat> <infile> <outformat> <outfile>")  def remove_colons(hexstr):     return ''.join(hexstr.split(':'))  if __name__ == '__main__':     if (len(sys.argv) != 5) or (sys.argv[1] not in ['john', 'hashcat', 'mana']) or (sys.argv[3] not in ['john', 'hashcat']):         print_usage()         quit()     import_format = sys.argv[1]     export_format = sys.argv[3]     with open(sys.argv[2], 'r') as infile, open(sys.argv[4], 'w') as outfile:         for line in infile:             if import_format == 'john':                 d = JohnHash.parse(line)             elif import_format == 'hashcat':                 d = HashcatHash.parse(line)             elif import_format == 'mana':                 d = ManaHash.parse(line)             if export_format == 'john':                 outline = JohnHash.format(d)             elif export_format == 'hashcat':                 outline = HashcatHash.format(d)             outfile.write(outline + " ")   
Original en ingles

This program should convert a file containing Mana, Hashcat or John the Ripper NTLMv1 hashes to another file containing Hashcat or John the Ripper hashes. Do you have any suggestions on how to make the code cleaner? The hash format selection code feels kinda dirty.

#!/usr/bin/env python3  # Takes a file of NTLMv1 hashes in mana format and spits out a #  file of hashes in JtR or hashcat format.   import sys import re  class Hash():     pass  class HashcatHash(Hash):     @staticmethod     def parse(line):         m = re.match("(.*?)::::([0-9a-f]{48}):([0-9a-f]{16})", line)         if m:             return {"username": m.group(1), "response": m.group(2), "challenge": m.group(3)}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         return "{username}::::{response}:{challenge}".format(             username=d["username"],             response=d["response"],             challenge=d["challenge"])  class JohnHash(Hash):     @staticmethod     def parse(line):         m = re.match("(.*?):\$NETNTLM\$([0-9a-f]{16})\$([0-9a-f]{48})", line)         if m:             return {"username": m.group(1), "response": m.group(3), "challenge": m.group(2)}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         return "{username}:$NETNTLM${challenge}${response}".format(             username=d["username"],             response=d["response"],             challenge=d["challenge"])  class ManaHash(Hash):     @staticmethod     def parse(line):         m = re.match("CHAP\|(.*?)\|([0-9a-f:]{23})\|([0-9a-f:]{71})", line)         if m:             return {"username": m.group(1), "response": remove_colons(m.group(3)), "challenge": remove_colons(m.group(2))}         else:             raise ValueError("Couldn't find hash in line")      @staticmethod     def format(d):         raise NotImplementedError  def print_usage():     print("Usage:")     print("exportlog.py <informat> <infile> <outformat> <outfile>")  def remove_colons(hexstr):     return ''.join(hexstr.split(':'))  if __name__ == '__main__':     if (len(sys.argv) != 5) or (sys.argv[1] not in ['john', 'hashcat', 'mana']) or (sys.argv[3] not in ['john', 'hashcat']):         print_usage()         quit()     import_format = sys.argv[1]     export_format = sys.argv[3]     with open(sys.argv[2], 'r') as infile, open(sys.argv[4], 'w') as outfile:         for line in infile:             if import_format == 'john':                 d = JohnHash.parse(line)             elif import_format == 'hashcat':                 d = HashcatHash.parse(line)             elif import_format == 'mana':                 d = ManaHash.parse(line)             if export_format == 'john':                 outline = JohnHash.format(d)             elif export_format == 'hashcat':                 outline = HashcatHash.format(d)             outfile.write(outline + "\n") 
              

Lista de respuestas

5
 
vote
vote
La mejor respuesta
 

En primer lugar, puede mejorar la lectura de los argumentos de la línea de comandos y, en lugar de analizar manualmente el sys.argv , use argparse Módulo . Algo así como:

  import argparse   def parse_args():     """Parses command-line arguments."""      parser = argparse.ArgumentParser()      parser.add_argument('infile', type=argparse.FileType('r'))     parser.add_argument('informat', action='store', choices=HASH_FORMATS)     parser.add_argument('outfile', type=argparse.FileType('w'))     parser.add_argument('outformat', action='store', choices=HASH_FORMATS)      return parser.parse_args()  if __name__ == '__main__':     args = parse_args()     # ...   

La lógica de selección de formato se puede simplificar si usaría un diccionario :

  HASH_FORMATS = {     'john': JohnHash,     'hashcat': HashcatHash,     'mana': ManaHash }  # get the input and output hash classes beforehand input_hash_class = HASH_FORMATS[args.informat] output_hash_class = HASH_FORMATS[args.outformat]  for line in args.infile:     parsed_line = input_hash_class.parse(line)     converted_line = output_hash_class.format(parsed_line)     args.outfile.write(converted_line)   

y, como nota lateral sobre la definición de las clases 9988777665544334 , creo que puede hacer uso de Clases de base abstractas con métodos abstractos que pueden llevar a un diseño más limpio orientado a objetos.

 

First of all, you can improve on reading the command-line arguments and, instead of manually parsing the sys.argv, use argparse module. Something like:

import argparse   def parse_args():     """Parses command-line arguments."""      parser = argparse.ArgumentParser()      parser.add_argument('infile', type=argparse.FileType('r'))     parser.add_argument('informat', action='store', choices=HASH_FORMATS)     parser.add_argument('outfile', type=argparse.FileType('w'))     parser.add_argument('outformat', action='store', choices=HASH_FORMATS)      return parser.parse_args()  if __name__ == '__main__':     args = parse_args()     # ... 

The format selection logic can be simplified if you would use a dictionary:

HASH_FORMATS = {     'john': JohnHash,     'hashcat': HashcatHash,     'mana': ManaHash }  # get the input and output hash classes beforehand input_hash_class = HASH_FORMATS[args.informat] output_hash_class = HASH_FORMATS[args.outformat]  for line in args.infile:     parsed_line = input_hash_class.parse(line)     converted_line = output_hash_class.format(parsed_line)     args.outfile.write(converted_line) 

And, as a side note about defining the Hash-based classes - I think you can make use of Abstract Base Classes with abstract methods which may lead to a cleaner object-oriented design.

 
 
   
   
5
 
vote

Si vas a escribir muchas clases de hash, entonces querrás simplificar la creación de la clase. TOMAR, por ejemplo, HashcatHash , lo siguiente es mucho más simple para crear, que lo que está haciendo:

  class HashcatHash(Hash):     _regex = "(.*?)::::([0-9a-f]{48}):([0-9a-f]{16})"     _format = "{d[username]}::::{d[response]}:{d[challenge]}"     def parse(m):         return {             "username": m.group(1),             "response": m.group(2),             "challenge": m.group(3)         }   

Para hacer esto, querrías hacer Hash predeterminado parse y format9 Para levantar 99887766555443310 , y para crear un metaclass, basado en esta respuesta , que Muta su entrada para organizar dinámicamente estas funciones estáticas. Esto es algo horrible, pero hace que la creación de las clases sea mucho más limpia. Y así podrías obtener:

  argparse1  

Después de esto, desea simplificar su IFS, en lugar de escribir manualmente un IF / ELIF / else para cada uno, puede crear un hash del nombre del hash, y la clase. Esto significa que puede simplificar todo el IFS a una línea legible:

  argparse2  

Después de esto, es posible que desee usar argparse3 Para simplificar su entrada de argumento.

 

If you're going to write a lot of Hash classes, then you'll want to simplify the creation of the class. Take for example HashcatHash, the following is much simpler to create, than what you're doing:

class HashcatHash(Hash):     _regex = "(.*?)::::([0-9a-f]{48}):([0-9a-f]{16})"     _format = "{d[username]}::::{d[response]}:{d[challenge]}"     def parse(m):         return {             "username": m.group(1),             "response": m.group(2),             "challenge": m.group(3)         } 

To do this, you'd want to make Hash default parse and format to raise NotImplementedError, and to create a metaclass, based on this answer, that mutates your input to dynamically crate these static functions. This is somewhat horrible, but it makes creation of the classes much cleaner. And so you could get:

import re from types import FunctionType   class HashMetaclass(type):     def __new__(meta, classname, bases, class_dict):         class_dict = class_dict.copy()          # Wrap parse, to use _regex and pass a match.         regex = class_dict.get("_regex")         if regex is not None:             parse = class_dict["parse"]             def _parse(line, _match=re.match):                 m = _match(regex, line)                 if not m:                     raise ValueError("Couldn't find hash in line")                 return parse(m)             class_dict['parse'] = _parse          # change _format to overwrite format         _format = class_dict.get("_format")         if _format is not None:             class_dict['format'] = lambda d: _format.format(d=d)          for key, attr in class_dict.items():             if isinstance(attr, FunctionType):                 class_dict[key] = staticmethod(attr)         return type.__new__(meta, classname, bases, class_dict)   class Hash(metaclass=HashMetaclass):     def parse(m):         raise NotImplementedError()      def format(d):         raise NotImplementedError()   class HashcatHash(Hash):     _regex = "(.*?)::::([0-9a-f]{48}):([0-9a-f]{16})"     _format = "{d[username]}::::{d[response]}:{d[challenge]}"     def parse(m):         return {             "username": m.group(1),             "response": m.group(2),             "challenge": m.group(3)         }   class JohnHash(Hash):     _regex = "(.*?):\$NETNTLM\$([0-9a-f]{16})\$([0-9a-f]{48})"     _format = "{d[username]}:$NETNTLM${d[challenge]}${d[response]}"     def parse(m):         return {             "username": m.group(1),             "response": m.group(3),             "challenge": m.group(2)         }   class ManaHash(Hash):     _regex = "CHAP\|(.*?)\|([0-9a-f:]{23})\|([0-9a-f:]{71})"     def parse(m):         return {             "username": m.group(1),             "response": remove_colons(m.group(3)),             "challenge": remove_colons(m.group(2))         } 

After this you want to simplify your ifs, rather than manually writing an if/elif/else for each one, you can create a hash of the hash's name, and the class. This means that you can simplify all the ifs to one readable line:

HASHES = {     'john': JohnHash,     'hashcat': HashcatHash,     'mana': ManaHash } parse = HASHES[import_format].parse format = HASHES[export_format].format 

After this you may want to use argparse to simplify your argument input.

 
 

Relacionados problema

5  Implementación iguales y hahcode  ( Equals and hashcode implementation ) 
Esta es la clase de dominio llamada WordType que tiene ID como su valor y nombre generado por DB único y la descripción como otros valores. Me estaba pasa...

6  Función de hash Fowler-Noll-VO en Lua  ( Fowler noll vo hash function in lua ) 
Recientemente codificé este FNV-1A Función hash en Lua. ¿Hay alguna mejoras aparentes de rendimiento que podrían implementarse? local bit = require(game....

10  Anular es igual () y Hashcode () utilizando la reflexión  ( Override equals and hashcode using reflection ) 
Escribí un método de utilidad para anular WriteableBitmap5 usando la reflexión. Esto funciona bien, pero me pregunto si este código pasará todas las pruebas...

2  Buscar archivos con contenidos similares  ( Find files with similar contents ) 
Normalmente, no soy un programador de C, pero pensé que me gustaría tomar algo útil. Esta es una utilidad C que escribí para juzgar qué tan similares están ut...

2  COMPUTANDO HASH DE STRING  ( Computing hash of string ) 
Quiero que mi código se revise y me gustaría escuchar sus opiniones. Código Sun para calcular hash de cadena: Option Explicit Private Type ViewModel ...

1  Internedstring como alternativa a la cadena regular  ( Internedstring as alternative to regular string ) 
Necesito usar cadenas grandes como teclas de diccionario, y quiero optimizar el 9988776665555443310 99887766555443311 Llamadas en ello. El número de clav...

5  Compruebe el sitio web para la actualización  ( Check website for update ) 
He escrito un programa en Python que verifica los sitios web de actualizaciones (verifica cualquier cosa en los cambios en el sitio web) y notifica al usuario...

1  Implementación de la función Hashing usando Guava  ( Implementing feature hashing using guava ) 
Estoy tratando de implementar Funciona Hashing en Java. Para esto, estoy tratando de usar las funciones de hashing de Guava. Así es como lo estoy haciendo...

9  Una forma de codificar una contraseña  ( One way encoding a password ) 
Escribí un script que una forma cifra la contraseña de un usuario generando una tecla, y se multiplica por el valor ASCII del carácter y el valor ASCII del ca...

4  Actualizando los registros de archivos de datos  ( Updating data file records ) 
Aprendí a codificar un largo, hace mucho tiempo. preocupaciones El enfoque existente es desordenado y será difícil de mantener. Los errores del sistema ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos