1
0
mirror of https://github.com/hashcat/hashcat.git synced 2025-07-19 13:08:19 +00:00
hashcat/tools/keybag2hashcat.py
Jens Steube 51e47daa1d Fix detection of argon2 kernel_accel_new. Ensure user-defined -n value does not exceed available memory; reduce it if necessary. On devices with unified memory (iGPU), only half of the memory is made available.
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.
2025-07-14 11:30:21 +02:00

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()