diff --git a/run/pse2john.py b/run/pse2john.py index fec37472ef..f3dc31d2c2 100755 --- a/run/pse2john.py +++ b/run/pse2john.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 """pysap - Python library for crafting SAP's network protocols packets""" @@ -19,52 +19,93 @@ # details. # Standard imports -import os -import sys +from argparse import ArgumentParser from binascii import hexlify +from os import path +from sys import stderr, stdout # Custom imports -from pysap.SAPPSE import (SAPPSEFile, PKCS12_ALGORITHM_PBE1_SHA_3DES_CBC) - - -def parse_pse(filename): - """Parses a PSE file and produces a JtR compatible hash""" - with open(filename, "rb") as fp: - data = fp.read() - - pse_file = SAPPSEFile(data) - - if pse_file.enc_cont.algorithm_identifier.alg_id == PKCS12_ALGORITHM_PBE1_SHA_3DES_CBC: - pbe_algo = 1 - salt = hexlify(pse_file.enc_cont.algorithm_identifier.parameters.salt.val) - salt_size = len(pse_file.enc_cont.algorithm_identifier.parameters.salt.val) - iterations = pse_file.enc_cont.algorithm_identifier.parameters.iterations.val - iv = "" - iv_size = len(iv) +try: + import pysap + from pysap.SAPPSE import (SAPPSEFile, PKCS12_ALGORITHM_PBE1_SHA_3DES_CBC) +except ImportError: + stderr.write("pysap is missing, run 'pip install --user pysap' to install it!\n") + raise SystemExit(1) + + +def parse_options(argv=None): + """Parse command line options.""" + description = ("This script can be used to parse PSE files and extract " + "encrypted material and data in a format that John the " + "Ripper or other cracking tools can use to look for the " + "decryption PIN.") + + parser = ArgumentParser( + usage="%(prog)s ", description=description, + epilog=pysap.epilog) + parser.add_argument( + "-o", "--output", help="Filename to write the output to [stdout]") + parser.add_argument( + "input_files", metavar="input_file", nargs="+", + help="PSE file to parse") + return parser.parse_args(argv) + + +def process_file(filename, output_file=stdout, error_file=stderr): + """Process a PSE file and write John the Ripper material if supported.""" + try: + with open(filename, "rb") as fp: + data = fp.read() + + pse_file = SAPPSEFile(data) + + if not pse_file.is_encrypted(): + raise Exception("PSE file is already unencrypted") + + if pse_file.enc_cont.algorithm_identifier.alg_id == \ + PKCS12_ALGORITHM_PBE1_SHA_3DES_CBC: + pbe_algo = 1 + salt = hexlify( + pse_file.enc_cont.algorithm_identifier.parameters.salt.val + ).decode("ascii") + salt_size = len( + pse_file.enc_cont.algorithm_identifier.parameters.salt.val) + iterations = pse_file.enc_cont.algorithm_identifier.parameters.iterations.val + iv = "" + iv_size = len(iv) + else: + raise Exception("Unsupported encryption algorithm") + + encrypted_pin = hexlify(pse_file.enc_cont.encrypted_pin.val).decode("ascii") + encrypted_pin_length = len(pse_file.enc_cont.encrypted_pin.val) + except Exception as e: + error_file.write("{}: {}\n".format(filename, e)) + return False + + output_file.write( + "{}:$pse${}${}${}${}${}${}${}${}:::::\n".format( + path.basename(filename), pbe_algo, iterations, salt_size, salt, + iv_size, iv, encrypted_pin_length, encrypted_pin)) + return True + + +def main(argv=None): + options = parse_options(argv) + + if options.output: + output_file = open(options.output, "w") else: - raise Exception("Unsupported encryption algorithm") + output_file = stdout - encrypted_pin = hexlify(pse_file.enc_cont.encrypted_pin.val) - encrypted_pin_length = len(pse_file.enc_cont.encrypted_pin.val) + try: + for input_file in options.input_files: + process_file(input_file, output_file) + finally: + if options.output: + output_file.close() - return "{}:$pse${}${}${}${}${}${}${}${}:::::\n".format(os.path.basename(filename), - pbe_algo, iterations, salt_size, salt, iv_size, iv, - encrypted_pin_length, encrypted_pin) + return 0 if __name__ == "__main__": - DESCRIPTION = """This script can be used to parse PSE files and extract encrypted material and -data in a format that John the Ripper or other cracking tools can use to look -for the decryption PIN.\n""" - - - USAGE = "Usage: %s <.pse file(s)>\n" - - if len(sys.argv) < 2: - sys.stderr.write("%s\n" % DESCRIPTION) - sys.stderr.write(USAGE % sys.argv[0]) - sys.exit(1) - - for i in range(1, len(sys.argv)): - line = parse_pse(sys.argv[i]) - sys.stdout.write(line) + raise SystemExit(main())