mirror of
https://github.com/hashcat/hashcat.git
synced 2025-07-19 13:08:19 +00:00

Improve unit test for -m 8300. In optimized mode, allow longer passwords, domain names, and salts. In both optimized and pure modes, ensure the domain name does not exceed 63 characters. Fix SNMPv3 unit test to produce passwords of at least 8 characters, as required by RFC 3414. Fix file permissions in tools/ folder.
172 lines
5.5 KiB
Python
Executable File
172 lines
5.5 KiB
Python
Executable File
import argparse
|
|
import logging
|
|
import sys
|
|
|
|
__VERSION__ = '1.0.0'
|
|
|
|
# Set up logging
|
|
logger = logging.getLogger("keybag_logger")
|
|
handler = logging.StreamHandler()
|
|
formatter = logging.Formatter('%(message)s')
|
|
handler.setFormatter(formatter)
|
|
logger.addHandler(handler)
|
|
|
|
class Keybag:
|
|
def __init__(self, file_obj):
|
|
self.size = 0
|
|
self.uuid = ''
|
|
self.version = 0
|
|
self.type = 0
|
|
self.hmackey = ''
|
|
self.wrap = 0
|
|
self.salt = ''
|
|
self.iterations = 0
|
|
|
|
|
|
self._read_header(file_obj)
|
|
self.class_keys = self._read_class_keys(file_obj)
|
|
|
|
def _read_header(self, file_obj):
|
|
while True:
|
|
tag = file_obj.read(4).decode('ascii')
|
|
if tag == 'DATA': # DATA
|
|
self.size = int.from_bytes(file_obj.read(4), byteorder='big')
|
|
else:
|
|
length = int.from_bytes(file_obj.read(4), byteorder='big')
|
|
data = file_obj.read(length)
|
|
|
|
if tag == 'VERS': # VERS
|
|
self.version = int.from_bytes(data, byteorder='big')
|
|
elif tag == 'TYPE':
|
|
self.type = int.from_bytes(data, byteorder='big')
|
|
elif tag == 'UUID':
|
|
if not self.uuid:
|
|
self.uuid = data.hex()
|
|
else:
|
|
file_obj.seek(-length - 8, 1)
|
|
break
|
|
elif tag == 'HMCK':
|
|
self.hmackey = data.hex()
|
|
elif tag == 'WRAP':
|
|
self.wrap = int.from_bytes(data, byteorder='big')
|
|
elif tag == 'SALT':
|
|
self.salt = data.hex()
|
|
elif tag == 'ITER':
|
|
self.iterations = int.from_bytes(data, byteorder='big')
|
|
|
|
def _read_class_keys(self, file_obj):
|
|
class_keys = {}
|
|
|
|
for x in range(0, 10):
|
|
stop = False
|
|
while stop != True:
|
|
tag = file_obj.read(4).decode('ascii')
|
|
length = int.from_bytes(file_obj.read(4), byteorder='big')
|
|
data = file_obj.read(length)
|
|
# new class key
|
|
if tag == 'UUID':
|
|
if class_keys.get(x):
|
|
if class_keys[x].get('UUID'):
|
|
file_obj.seek(-length - 8, 1)
|
|
stop = True
|
|
else:
|
|
class_keys[x] = {}
|
|
else:
|
|
class_keys[x] = {}
|
|
if tag == 'WRAP' or tag == 'CLAS' or tag == 'KTYP':
|
|
class_keys[x][tag] = int.from_bytes(data, byteorder='big')
|
|
else:
|
|
class_keys[x][tag] = data.hex()
|
|
if file_obj.tell() > self.size:
|
|
stop = True
|
|
return class_keys
|
|
|
|
|
|
def print_keybag(self):
|
|
logger.debug(f'SIZE: {self.size}')
|
|
logger.debug(f'VERSION: {self.version}')
|
|
logger.debug(f'TYPE: {self.type}')
|
|
logger.debug(f'UUID: {self.uuid}')
|
|
logger.debug(f'HMACKEY: {self.hmackey}')
|
|
logger.debug(f'SALT: {self.salt}')
|
|
logger.debug(f'ITERATIONS: {self.iterations}')
|
|
for x, class_key in self.class_keys.items():
|
|
logger.debug(f'{x}:')
|
|
for key, value in class_key.items():
|
|
logger.debug(f' {key}: {value}')
|
|
|
|
def main():
|
|
# Create the argument parser
|
|
parser = argparse.ArgumentParser(description="Process a keybag file with a specified UID.")
|
|
|
|
# Add the UID argument
|
|
parser.add_argument(
|
|
'--uid',
|
|
type=str,
|
|
required=True,
|
|
help="Specify the device UID."
|
|
)
|
|
|
|
# Add the keybag file argument
|
|
parser.add_argument(
|
|
'keybag',
|
|
type=str,
|
|
help="Path to the keybag file."
|
|
)
|
|
|
|
# Add the debug flag
|
|
parser.add_argument(
|
|
'--debug',
|
|
action='store_true',
|
|
help="Enable debug logging."
|
|
)
|
|
|
|
# Parse the arguments
|
|
args = parser.parse_args()
|
|
|
|
if args.debug:
|
|
logger.setLevel(logging.DEBUG)
|
|
else:
|
|
logger.setLevel(logging.WARNING)
|
|
|
|
# Access the arguments
|
|
uid = args.uid[0:32]
|
|
keybag_path = args.keybag
|
|
|
|
logger.debug(f'keybag2hashcat - version {__VERSION__}')
|
|
|
|
with open(keybag_path, 'br') as keybag_file:
|
|
kb = Keybag(keybag_file)
|
|
kb.print_keybag()
|
|
if not kb.version:
|
|
logger.error('Unable to detect version of keybag, exiting.')
|
|
sys.exit(1)
|
|
if not kb.salt:
|
|
logger.error('Unable to detect salt, exiting.')
|
|
sys.exit(1)
|
|
if not kb.iterations:
|
|
logger.error('Unable to detect iterations, exiting.')
|
|
sys.exit(1)
|
|
if not kb.version in [3, 4]:
|
|
logger.error(f'This script has not been tested with version {kb.version}.')
|
|
sys.exit(1)
|
|
if not kb.class_keys:
|
|
logger.error(f'Unable to parse class keys, exiting.')
|
|
sys.exit(1)
|
|
classkey1 = 0
|
|
for x, class_key in kb.class_keys.items():
|
|
if class_key.get('WRAP') == 3:
|
|
class_type = class_key.get('CLAS')
|
|
if class_type == 1 or class_type == 33:
|
|
classkey1 = class_key.get('WPKY')
|
|
|
|
if not classkey1:
|
|
logger.error(f'Unable to find a classkey of class NSFileProtectionComplete.')
|
|
logger.error(f'You could try to get another class key, make sure it is ktyp 0 and wrap 3.')
|
|
exit(1)
|
|
print(f'$uido${uid}${kb.salt}${kb.iterations}${classkey1}')
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|