#!/usr/bin/env python3 from argparse import ArgumentParser, ArgumentTypeError SALT_LENGTH = 64 DATA_LENGTH = 448 HEADER_LENGTH = SALT_LENGTH + DATA_LENGTH SIGNATURE = "$veracrypt$" BOOTABLE_OFFSET = 31744 # 62 * 512 HIDDEN_OFFSET = 65536 # 64K def validate_offset(offset): # see also https://hashcat.net/wiki/doku.php?id=frequently_asked_questions#how_do_i_extract_the_hashes_from_veracrypt_volumes if offset == "bootable": offset = BOOTABLE_OFFSET elif offset == "hidden": offset = HIDDEN_OFFSET elif offset == "bootable+hidden": offset = BOOTABLE_OFFSET + HIDDEN_OFFSET try: offset = int(offset) assert offset >= 0 except (AssertionError, ValueError): raise ArgumentTypeError("offset is nether non-negative number nor bootable, hidden or bootable+hidden value") return offset if __name__ == "__main__": parser = ArgumentParser(description="veracrypt2hashcat extraction tool") parser.add_argument( "--offset", default=0, type=validate_offset, required=False, help="select between bootable, hidden, bootable+hidden or custom one (default: 0)", ) parser.add_argument("path", type=str, help="path to VeraCrypt container") args = parser.parse_args() with open(args.path, "rb") as file: file.seek(args.offset) header = file.read(HEADER_LENGTH) assert len(header) == HEADER_LENGTH, "less data than needed" salt, data = header[:SALT_LENGTH], header[SALT_LENGTH:] hash = SIGNATURE + salt.hex() + "$" + data.hex() print(hash)