From a925545354f40f9ca4ec6daf6092d149fc870a80 Mon Sep 17 00:00:00 2001 From: jsteube Date: Thu, 21 Feb 2019 16:50:50 +0100 Subject: [PATCH] No longer require legacy_test.pl --- tools/legacy_test.pl | 13462 ----------------------------------------- 1 file changed, 13462 deletions(-) delete mode 100755 tools/legacy_test.pl diff --git a/tools/legacy_test.pl b/tools/legacy_test.pl deleted file mode 100755 index ed03680b0..000000000 --- a/tools/legacy_test.pl +++ /dev/null @@ -1,13462 +0,0 @@ -#!/usr/bin/env perl - -## -## Author......: See docs/credits.txt -## License.....: MIT -## - -## -## Installation script for all perl and python modules: -## -## tools/install_modules.sh -## - -## -## If you want to add a new hash mode, follow the STEP comments. -## - -use strict; -use warnings; - -use Authen::Passphrase::LANManager; -use Authen::Passphrase::MySQL323; -use Authen::Passphrase::NTHash; -use Authen::Passphrase::PHPass; -use Convert::EBCDIC qw (ascii2ebcdic); -use Crypt::CBC; -use Crypt::DES; -use Crypt::Digest::RIPEMD160 qw (ripemd160_hex); -use Crypt::Digest::Whirlpool qw (whirlpool_hex); -use Crypt::ECB qw (encrypt); -use Crypt::Eksblowfish::Bcrypt qw (bcrypt en_base64); -use Crypt::GCrypt; -use Crypt::Mode::CBC; -use Crypt::Mode::ECB; -use Crypt::MySQL qw (password41); -use Crypt::OpenSSH::ChachaPoly; -use Crypt::PBKDF2; -use Crypt::RC4; -use Crypt::Rijndael; -use Crypt::ScryptKDF qw (scrypt_hash scrypt_raw scrypt_b64); -use Crypt::Skip32; -use Crypt::Twofish; -use Crypt::UnixCrypt_XS qw (crypt_rounds fold_password base64_to_int24 block_to_base64 int24_to_base64); -use Digest::MD4 qw (md4 md4_hex); -use Digest::MD5 qw (md5 md5_hex); -use Digest::SHA qw (sha1 sha256 sha384 sha512 sha1_hex sha224_hex sha256_hex sha384_hex sha512_hex hmac_sha1 hmac_sha256 hmac_sha512); -use Digest::SHA1; -use Digest::SHA3 qw (sha3_224_hex sha3_256_hex sha3_384_hex sha3_512_hex); -use Digest::Keccak qw (keccak_224_hex keccak_256_hex keccak_384_hex keccak_512_hex); -use Digest::HMAC qw (hmac hmac_hex); -use Digest::BLAKE2 qw (blake2b_hex); -use Digest::GOST qw (gost gost_hex); -use Digest::HMAC_MD5 qw (hmac_md5); -use Digest::CRC qw (crc32); -use Digest::CMAC; -use Digest::SipHash qw (siphash); -use Digest::Perl::MD5; -use Encode; -use JSON; -use MIME::Base32 qw (encode_base32 decode_base32); -use MIME::Base64 qw (encode_base64 decode_base64 encode_base64url decode_base64url); -use Net::DNS::RR::NSEC3; -use Net::DNS::SEC; -use POSIX qw (strftime ceil); -use Text::Iconv; - -my $hashcat = "./hashcat"; - -my $MAX_LEN = 55; - -## STEP 1: Add your hash mode to this array. -# -# This array contains all supported hash modes. -# -## - -my $MODES = -[ - 0, 10, 11, 12, 20, 21, 22, 23, 30, 40, 50, - 60, 100, 101, 110, 111, 112, 120, 121, 122, 125, 130, - 131, 132, 133, 140, 141, 150, 160, 200, 300, 400, 500, - 600, 900, 1000, 1100, 1300, 1400, 1410, 1411, 1420, 1430, 1440, - 1441, 1450, 1460, 1500, 1600, 1700, 1710, 1711, 1720, 1730, 1740, - 1722, 1731, 1750, 1760, 1800, 2100, 2400, 2410, 2500, 2600, 2611, - 2612, 2711, 2811, 3000, 3100, 3200, 3710, 3711, 3300, 3500, 3610, - 3720, 3800, 3910, 4010, 4110, 4210, 4300, 4400, 4500, 4520, 4521, - 4522, 4600, 4700, 4800, 4900, 5100, 5300, 5400, 5500, 5600, 5700, - 5800, 6000, 6100, 6300, 6400, 6500, 6600, 6700, 6800, 6900, 7000, - 7100, 7200, 7300, 7400, 7500, 7700, 7701, 7800, 7801, 7900, 8000, - 8100, 8200, 8300, 8400, 8500, 8600, 8700, 8900, 9100, 9200, 9300, - 9400, 9500, 9600, 9700, 9800, 9900, 10000, 10100, 10200, 10300, 10400, - 10500, 10600, 10700, 10800, 10900, 11000, 11100, 11200, 11300, 11400, 11500, - 11600, 11700, 11750, 11760, 11800, 11850, 11860, 11900, 12000, 12001, 12100, - 12200, 12300, 12400, 12600, 12700, 12800, 12900, 13000, 13100, 13200, 13300, - 13400, 13500, 13600, 13800, 13900, 14000, 14100, 14400, 14700, 14800, 14900, - 15000, 15100, 15200, 15300, 15400, 15500, 15600, 15700, 15900, 16000, 16100, - 16200, 16300, 16400, 16500, 16600, 16700, 16800, 16900, 17300, 17400, 17500, - 17600, 17700, 17800, 17900, 18000, 18100, 18200, 18300, 18400, 18500, 18600, - 99999 -]; - -## STEP 2a: If your hash mode does not need a salt, add it to this array. -# -# This array contains all unsalted hash-modes that are handled in the 'default' -# branches in all three single, passthrough and verify test functions. There -# still are some unsalted hash-modes which are handled differently and are not -# listed here; they are caught in separate if conditions accordingly. -# -## - -my $COMMON_UNSALTED_MODES = -[ - 0, 100, 101, 133, 200, 300, 600, 900, 1000, 1300, 1400, - 1700, 2600, 3500, 4300, 4400, 4500, 4600, 4700, 5100, 5700, 6000, - 6100, 6900, 9900, 10800, 11500, 11700, 11800, 16400, 17300, 17400, 17500, - 17600, 17700, 17800, 17900, 18000, 18500, 99999 -]; - -## STEP 2b: If your hash-mode has a salt without any specific syntax, -## add it to this array. Else look for STEP 2c (several spots). -# -# Same as above, only for salted hashes without specific salt formats. -# -## - -my $COMMON_DEFAULT_SALTED_MODES = -[ - 10, 20, 23, 30, 40, 50, 60, 110, 120, 130, 140, - 150, 160, 1410, 1420, 1430, 1440, 1450, 1460, 1710, 1720, 1730, - 1740, 1750, 1760, 3610, 3710, 3720, 3910, 4010, 4110, 4210, 11750, - 11760, 11850, 11860, 18100 -]; - -# Arrays for hash modes with maximum password length 15 - -my $LESS_FIFTEEN = [500, 1600, 1800, 3200, 6300, 7400, 10500, 10700]; - -# Arrays for hash modes with unusual salts - -my $ALLOW_LONG_SALT = -[ - 2500, 4520, 4521, 5500, 5600, 7100, 7200, 7300, 9400, 9500, 9600, - 9700, 9800, 10400, 10500, 10600, 10700, 1100, 11000, 11200, 11300, 11400, - 11600, 12600, 13500, 13800, 15000, 16900 -]; - -my $IS_UTF16LE = -[ - 30, 40, 130, 131, 132, 133, 140, 141, 1000, 1100, 1430, - 1440, 1441, 1730, 1740, 1731, 5500, 5600, 8000, 9400, 9500, 9600, - 9700, 9800, 11600, 13500, 13800 -]; - -my $LOTUS_MAGIC_TABLE = -[ - 0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, - 0x1b, 0x33, 0xfd, 0xd0, 0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, - 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a, 0x41, 0x9f, 0xe1, 0xd9, - 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36, - 0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, - 0xa6, 0x3f, 0xd8, 0x0c, 0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, - 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60, 0x48, 0xe6, 0x1e, 0x53, - 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa, - 0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, - 0xba, 0x3c, 0x06, 0x4e, 0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, - 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf, 0x3a, 0xde, 0x96, 0x0e, - 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6, - 0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, - 0x75, 0xd5, 0x61, 0xe3, 0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, - 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c, 0xb4, 0xc5, 0xcc, 0x70, - 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2, - 0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, - 0x82, 0xf9, 0x40, 0xb5, 0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, - 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5, 0x64, 0x6d, 0x7a, 0xd4, - 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f, - 0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, - 0x4c, 0xff, 0x43, 0xab -]; - -my $PDF_PADDING = -[ - 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, - 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, - 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a -]; - -my $CISCO_BASE64_MAPPING = -{ - 'A', '.', 'B', '/', 'C', '0', 'D', '1', 'E', '2', 'F', '3', 'G', '4', 'H', - '5', 'I', '6', 'J', '7', 'K', '8', 'L', '9', 'M', 'A', 'N', 'B', 'O', 'C', - 'P', 'D', 'Q', 'E', 'R', 'F', 'S', 'G', 'T', 'H', 'U', 'I', 'V', 'J', 'W', - 'K', 'X', 'L', 'Y', 'M', 'Z', 'N', 'a', 'O', 'b', 'P', 'c', 'Q', 'd', 'R', - 'e', 'S', 'f', 'T', 'g', 'U', 'h', 'V', 'i', 'W', 'j', 'X', 'k', 'Y', 'l', - 'Z', 'm', 'a', 'n', 'b', 'o', 'c', 'p', 'd', 'q', 'e', 'r', 'f', 's', 'g', - 't', 'h', 'u', 'i', 'v', 'j', 'w', 'k', 'x', 'l', 'y', 'm', 'z', 'n', '0', - 'o', '1', 'p', '2', 'q', '3', 'r', '4', 's', '5', 't', '6', 'u', '7', 'v', - '8', 'w', '9', 'x', '+', 'y', '/', 'z' -}; - -if (scalar @ARGV < 1) -{ - usage_die (); -} - -my $type; -my $mode; -my $len; - -$type = shift @ARGV; - -if ($type ne "verify") -{ - if (scalar @ARGV > 1) - { - $mode = shift @ARGV; - $len = shift @ARGV; - } - elsif (scalar @ARGV == 1) - { - $mode = shift @ARGV; - $len = 0; - } - else - { - $len = 0; - } - - if ($type eq "single") - { - single ($mode); - } - elsif ($type eq "passthrough") - { - passthrough ($mode); - } - else - { - usage_die (); - } -} -else -{ - if (scalar @ARGV != 4) - { - usage_die (); - } - - my $mode = shift @ARGV; - my $hash_file = shift @ARGV; - my $in_file = shift @ARGV; - my $out_file = shift @ARGV; - - my $db; - - open (IN, "<", $hash_file) or die ("$hash_file: $!\n"); - - # clever ? the resulting database could be huge - # but we need some way to map lines in hashfile w/ cracks - # maybe rli2 way would be more clever (needs sorted input) - - while (my $line = ) - { - $line =~ s/[\n\r]*$//; - - $db->{$line} = undef; - } - - close (IN); - - verify ($mode, $db, $in_file, $out_file); -} - -# Array lookup -sub is_in_array -{ - my $value = shift; - my $array = shift; - - return grep { $_ eq $value } @{$array}; -} - -sub verify -{ - my $mode = shift; - my $db = shift; - my $in_file = shift; - my $out_file = shift; - - my $hash_in; - my $hash_out; - my $iter; - my $salt; - my $word; - my $param; - my $param2; - my $param3; - my $param4; - my $param5; - my $param6; - my $param7; - my $param8; - my $param9; - my $param10; - my $param11; - - open (IN, "<", $in_file) or die ("$in_file: $!\n"); - open (OUT, ">", $out_file) or die ("$out_file: $!\n"); - - my $len; - - my $base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - my $itoa64_1 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - my $itoa64_2 = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - while (my $line = ) - { - chomp ($line); - - $line =~ s/\n$//; - $line =~ s/\r$//; - - # remember always do "exists ($db->{$hash_in})" checks as soon as possible and don't forget it - - # unsalted - if (is_in_array ($mode, $COMMON_UNSALTED_MODES) - || $mode == 2400 || $mode == 3000 - || $mode == 8600 || $mode == 16000) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $word = substr ($line, $index + 1); - } - # hash:salt - elsif (is_in_array ($mode, $COMMON_DEFAULT_SALTED_MODES) - || $mode == 11 || $mode == 12 || $mode == 21 || $mode == 22 - || $mode == 112 || $mode == 121 || $mode == 1100 || $mode == 2410 - || $mode == 2611 || $mode == 2711 || $mode == 2811 || $mode == 3100 - || $mode == 3800 || $mode == 4520 || $mode == 4521 || $mode == 4522 - || $mode == 4900 || $mode == 5800 || $mode == 8400 || $mode == 11000 - || $mode == 12600 || $mode == 13500 || $mode == 13800 || $mode == 13900 - || $mode == 14000 || $mode == 14100 || $mode == 14400 || $mode == 14900 - || $mode == 15000) - { - # get hash - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - - # identify lenghts of both salt and plain - - my $salt_plain = substr ($line, $index1 + 1); - - my $num_cols = () = $salt_plain =~ /:/g; - - my $index2; - my $matched = 0; - my $start = 0; - - $word = undef; - - # fuzzy - foreach (my $i = 0; $i < $num_cols; $i++) - { - $index2 = index ($salt_plain, ":", $start); - - next if $index2 < 0; - - $start = $index2 + 1; - - $salt = substr ($salt_plain, 0, $index2); - $word = substr ($salt_plain, $index2 + 1); - - # can't be true w/ wrong $hash:$salt, otherwise the - # algo must have many collisions - - if (exists ($db->{$hash_in . ":" . $salt})) - { - $hash_in = $hash_in . ":" . $salt; - $matched = 1; - last; - } - } - - next unless ($matched); # therefore: true == exists ($db->{$hash_in} - next unless (! defined ($db->{$hash_in})); - } - # dcc2 - elsif ($mode == 2100) - { - # get hash - my $index1 = index ($line, "\$DCC2\$"); - - next if $index1 != 0; - - # iterations - my $index2 = index ($line, "#", $index1 + 1); - - next if $index2 < 1; - - $iter = substr ($line, $index1 + 6, $index2 - $index1 - 6); - - # get hash - $index1 = index ($line, "#"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1 + 1); - - # identify lenghts of both salt and plain - - my $salt_plain = substr ($line, $index2 + 1); - - my $num_cols = () = $salt_plain =~ /:/g; - - my $matched = 0; - my $start = 0; - my $index3 = 0; - my $raw_hash; - - $word = undef; - - # fuzzy - foreach (my $i = 0; $i < $num_cols; $i++) - { - $index2 = index ($salt_plain, ":", $start); - - next if $index2 < 0; - - $start = $index2 + 1; - - $index3 = rindex ($salt_plain, "#", $index2); - - $raw_hash = substr ($salt_plain, $index3 + 1, $index2 - $index3 - 1); - $salt = substr ($salt_plain, 0, $index3); - $word = substr ($salt_plain, $index2 + 1); - - if (exists ($db->{$hash_in . $salt . "#" .$raw_hash})) - { - $hash_in = $hash_in . $salt . "#" . $raw_hash; - $matched = 1; - last; - } - } - - next unless ($matched); # therefore: true == exists ($db->{$hash_in} - next unless (! defined ($db->{$hash_in})); - } - # salt:hash guaranteed only : because of hex salt - elsif ($mode == 7300) - { - # split hash and plain - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $salt = substr ($line, 0, $index1); - - $salt = pack ("H*", $salt); - - my $rest = substr ($line, $index1 + 1); - - my $index2 = index ($rest, ":"); - - next if $index2 < 1; - - $hash_in = substr ($rest, 0, $index2); - - $word = substr ($rest, $index2 + 1); - - next unless (exists ($db->{$salt . ":" . $hash_in}) and (! defined ($db->{$hash_in}))); - } - # 1salthash fixed - elsif ($mode == 8100) - { - # split hash and plain - $salt = substr ($line, 1, 8); - - my $rest = substr ($line, 1 + 8); - - my $index2 = index ($rest, ":"); - - next if $index2 < 1; - - $hash_in = substr ($rest, 0, $index2); - - $word = substr ($rest, $index2 + 1); - - next unless (exists ($db->{"1" . $salt . $hash_in}) and (! defined ($db->{$hash_in}))); - } - # base64 and salt embedded SSHA1, salt length = total lenght - 20 - elsif ($mode == 111) - { - # split hash and plain - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - # remove signature - my $plain_base64 = substr ($hash_in, 6); - - # base64 decode to extract salt - my $decoded = decode_base64 ($plain_base64); - - $salt = substr ($decoded, 20); - } - # base64 and salt embedded SSHA512, salt length = total length - 64 - elsif ($mode == 1711) - { - # split hash and plain - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - # remove signature - my $plain_base64 = substr ($hash_in, 9); - - # base64 decode to extract salt - my $decoded = decode_base64 ($plain_base64); - - $salt = substr ($decoded, 64); - } - # macOS (first 8 hex chars is salt) - # ArubaOS (the signature gets added in gen_hash) - elsif ($mode == 122 || $mode == 1722 || $mode == 125) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 0, 8); - } - # MSSQL (2000, 2005 AND 2012), salt after version number - elsif ($mode == 131 || $mode == 132 || $mode == 1731) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 6, 8); - } - # Sybase ASE - elsif ($mode == 8000) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 6, 16); - } - # episerver salts - elsif ($mode == 141 || $mode == 1441) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($line, "*", 14); - - #extract salt from base64 - my $plain_base64 = substr ($hash_in, 14, $index2 - 14); - - $salt = decode_base64 ($plain_base64); - } - # phpass (first 8 after $P$/$H$ -- or $S$ with drupal7) - elsif ($mode == 400 || $mode == 7900) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 4, 8); - - # iterations = 2 ^ cost (where cost == $iter) - $iter = index ($itoa64_1, substr ($hash_in, 3, 1)); - } - # $something$[rounds=iter$]salt$ (get last $, then check iter) - elsif ($mode == 500 || $mode == 1600 || $mode == 1800 || $mode == 3300 || $mode == 7400) - { - my $index1 = index ($line, ":", 30); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $index1 = index ($hash_in, ",", 1); - my $index2 = index ($hash_in, "\$", 1); - - if ($index1 != -1) - { - if ($index1 < $index2) - { - $index2 = $index1; - } - } - - $param = substr ($hash_in, $index2, 1); - - $index2++; - - # rounds= if available - $iter = 0; - - if (substr ($hash_in, $index2, 7) eq "rounds=") - { - my $old_index = $index2; - - $index2 = index ($hash_in, "\$", $index2 + 1); - - next if $index2 < 1; - - $iter = substr ($hash_in, $old_index + 7, $index2 - $old_index - 7); - - $index2++; - } - - # get salt - my $index3 = rindex ($hash_in, "\$"); - - next if $index3 < 1; - - $salt = substr ($hash_in, $index2, $index3 - $index2); - } - # descrypt (salt in first 2 char) - elsif ($mode == 1500) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 0, 2); - } - # bcrypt $something$something$salt.hash - elsif ($mode == 3200) - { - my $index1 = index ($line, ":", 33); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($hash_in, "\$", 4); - - $iter = substr ($hash_in, 4, $index2 - 4); - - my $plain_base64 = substr ($hash_in, $index2 + 1, 22); - - # base64 mapping - my $encoded = ""; - - for (my $i = 0; $i < length ($plain_base64); $i++) - { - my $char = substr ($plain_base64, $i, 1); - $encoded .= substr ($base64, index ($itoa64_2, $char), 1); - } - - $salt = decode_base64 ($encoded); - } - # md5 (chap) - elsif ($mode == 4800) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - my $index3 = index ($line, ":", $index2 + 1); - - next if $index3 < 1; - - $salt = substr ($line, $index1 + 1, $index3 - $index1 - 1); - - $word = substr ($line, $index3 + 1); - - $hash_in = substr ($line, 0, $index3); - } - # IKE (md5 and sha1) - elsif ($mode == 5300 || $mode == 5400) - { - my $num_cols = () = $line =~ /:/g; - - next unless ($num_cols >= 9); - - my $index1 = -1; - my $failed = 0; - - for (my $j = 0; $j < 9; $j++) - { - $index1 = index ($line, ":", $index1 + 1); - - if ($index1 < 1) - { - $failed = 1; - last; - } - } - - next if ($failed); - - $word = substr ($line, $index1 + 1); - - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = rindex ($line, ":", $index1 - 1); - - $salt = substr ($line, 0, $index2); - } - # NetNTLMv1 - elsif ($mode == 5500) - { - my $index1 = index ($line, "::"); - - next if $index1 < 1; - - my $index2 = index ($line, ":", $index1 + 2); - - next if $index2 < 1; - - $index2 = index ($line, ":", $index2 + 1); - - next if $index2 < 1; - - $salt = substr ($line, 0, $index2); - - $index2 = index ($line, ":", $index2 + 1); - - next if $index2 < 1; - - $salt .= substr ($line, $index2 + 1, 16); - - $index2 = index ($line, ":", $index2 + 1); - - next if $index2 < 1; - - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $word = substr ($line, $index2 + 1); - } - # NetNTLMv2 - elsif ($mode == 5600) - { - my $index1 = index ($line, "::"); - - next if $index1 < 1; - - my $index2 = index ($line, ":", $index1 + 2); - - next if $index2 < 1; - - $index2 = index ($line, ":", $index2 + 1); - - next if $index2 < 1; - - $salt = substr ($line, 0, $index2); - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt .= substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $hash_in = substr ($line, 0, $index2); - - # do it later on for this hash mode: - # next unless ((exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))) or (exists ($db->{$mod}) and (! defined ($db->{$mod})))); - - $word = substr ($line, $index2 + 1); - } - # AIX smd5 something BRACE salt$ - elsif ($mode == 6300) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($hash_in, "}"); - my $index3 = rindex ($hash_in, "\$"); - - $salt = substr ($hash_in, $index2 + 1, $index3 - $index2 - 1); - } - # AIX: something$salt$ (no $ at position 1) - elsif ($mode == 6400 || $mode == 6500 || $mode == 6700) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($hash_in, "}"); - my $index3 = index ($hash_in, "\$"); - my $index4 = rindex ($hash_in, "\$"); - - $salt = substr ($hash_in, $index3 + 1, $index4 - $index3 - 1); - - $iter = substr ($hash_in, $index2 + 1, $index3 - $index2 - 1); - } - # 1Password, agilekeychain - elsif ($mode == 6600) - { - my $num_cols = () = $line =~ /:/g; - - next unless ($num_cols > 2); - - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $iter = substr ($line, 0, $index1); - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - $salt .= substr ($line, $index2 + 1, $index1 - $index2 - 33); - - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $word = substr ($line, $index1 + 1); - } - # 1Password, cloudkeychain - elsif ($mode == 8200) - { - my @datas = split (":", $line); - - next if scalar @datas < 4; - - my $hash = shift @datas; - $salt = shift @datas; - $iter = shift @datas; - my $data = shift @datas; - - $hash_in = $hash . ":" . $salt . ":" . $iter . ":" . $data; - - $salt .= $data; - - $word = join (":", @datas); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # lastpass (hash:iter:salt) - elsif ($mode == 6800) - { - my $index1 = index ($line, ":", 34); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - - # identify lenghts of both salt and plain - - my $salt_plain = substr ($line, $index1 + 1); - - my $num_cols = () = $salt_plain =~ /:/g; - - my $index2; - my $matched = 0; - my $start = 0; - - $word = undef; - - # fuzzy - foreach (my $i = 0; $i < $num_cols; $i++) - { - $index2 = index ($salt_plain, ":", $start); - - next if $index2 < 1; - - $start = $index2 + 1; - - $salt = substr ($salt_plain, 0, $index2); - $word = substr ($salt_plain, $index2 + 1); - - # can't be true w/ wrong $hash:$salt, otherwise the - # algo must have many collisions - - if (exists ($db->{$hash_in . ":" . $salt})) - { - $hash_in = $hash_in . ":" . $salt; - $matched = 1; - last; - } - } - - next unless ($matched); # therefore: true == exists ($db->{$hash_in} - next unless (! defined ($db->{$hash_in})); - - $index1 = index ($hash_in, ":"); - $index2 = index ($hash_in, ":", $index1 + 1); - - $iter = substr ($hash_in, $index1 + 1, $index2 - $index1 - 1); - $salt = substr ($hash_in, $index2 + 1); - } - # Fortigate - elsif ($mode == 7000) - { - my $index1 = index ($line, ":"); - - next if $index1 != 47; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (substr ($hash_in, 0, 3) eq "AK1"); - - my $decoded = decode_base64 (substr ($hash_in, 3)); - - $salt = substr ($decoded, 0, 12); - $salt = unpack ("H*", $salt); - } - # macOS 10.* : $something$iter$salt$ - elsif ($mode == 7100) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($hash_in, "\$", 5); - - next if $index2 < 1; - - my $index3 = index ($hash_in, "\$", $index2 + 1); - - $salt = substr ($hash_in, $index2 + 1, $index3 - $index2 - 1); - - $iter = substr ($hash_in, 4, $index2 - 4); - - next if (int ($iter) < 1); - } - # grub: something1.something2.something3.iter.salt. - elsif ($mode == 7200) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index2 = index ($hash_in, ".", 19); - - next if $index2 < 1; - - my $index3 = index ($hash_in, ".", $index2 + 1); - - $salt = substr ($hash_in, $index2 + 1, $index3 - $index2 - 1); - - $iter = substr ($hash_in, 19, $index2 - 19); - - next if (int ($iter) < 1); - } - # $something1$something2$something3$something4$salt$ - elsif ($mode == 7500 ) - { - my $index1 = index ($line, "\$", 11); - - next if $index1 < 1; - - my $index2 = index ($line, "\$", $index1 + 1); - - next if $index2 < 1; - - my $index3 = index ($line, "\$", $index2 + 1); - - next if $index3 < 1; - - $index2 = index ($line, ":", $index3 + 1); - - next if $index2 < 1; - - $hash_in = substr ($line, 0, $index2); - $word = substr ($line, $index2 + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = substr ($hash_in, 11, $index3 - 10); - $salt .= substr ($hash_in, $index2 - 32) . "\$\$"; - $salt .= substr ($hash_in, $index3 + 1, $index2 - $index3 - 32 - 1); - } - # $salt$$hash - elsif ($mode == 7700 || $mode == 7800 || $mode == 7701 || $mode == 7801) - { - my $index1 = index ($line, ":"); - - next if $index1 < 1; - - my @split1 = split (":", $line); - - my @split2 = split ('\$', $split1[0]); - - next unless scalar @split2 == 2; - - $hash_in = $split1[0]; - - if (scalar @split1 > 1) - { - $word = $split1[1]; - } - else - { - $word = ""; - } - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = $split2[0]; - } - # DNSSEC - elsif ($mode == 8300) - { - my @datas = split (":", $line); - - next if scalar @datas != 5; - - my $hash; - my $domain; - - ($hash, $domain, $salt, $iter, $word) = @datas; - - $hash_in = $hash . ":" . $domain . ":" . $salt . ":" . $iter; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - $salt = $domain . ":" . $salt; - } - # RACF - elsif ($mode == 8500) - { - my @line_elements = split (":", $line); - - next if scalar @line_elements < 2; - - # get hash and word - - $hash_in = shift @line_elements; - - $word = join (":", @line_elements); - - # get signature - - my @hash_elements = split ('\*', $hash_in); - - next unless ($hash_elements[0] eq '$racf$'); - - $salt = $hash_elements[1]; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # DOMINO 6 - elsif ($mode == 8700) - { - # split hash and plain - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $plain_base64 = substr ($hash_in, 2, -1); - - ($_, $salt, $param) = domino_decode ($plain_base64); - } - # PHPS - elsif ($mode == 2612) - { - next unless (substr ($line, 0, 6) eq '$PHPS$'); - - # get hash - my $index1 = index ($line, "\$", 6); - - next if $index1 < 1; - - $salt = substr ($line, 6, $index1 - 6); - - $salt = pack ("H*", $salt); - - my $index2 = index ($line, "\:", $index1 + 1); - - next if $index2 < 1; - - $word = substr ($line, $index2 + 1); - - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Mediawiki B type - elsif ($mode == 3711) - { - next unless (substr ($line, 0, 3) eq '$B$'); - - # get hash - my $index1 = index ($line, "\$", 3); - - next if $index1 < 1; - - $salt = substr ($line, 3, $index1 - 3); - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $word = substr ($line, $index2 + 1); - - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # scrypt - elsif ($mode == 8900) - { - next unless (substr ($line, 0, 7) eq 'SCRYPT:'); - - # get hash - my $index1 = index ($line, ":", 7); - - next if $index1 < 1; - - # N - my $N = substr ($line, 7, $index1 - 7); - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - # r - my $r = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # p - my $p = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - $param = $N; - $param2 = $r; - $param3 = $p; - - $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - # salt - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = decode_base64 ($salt); - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # digest - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # LOTUS 8 - elsif ($mode == 9100) - { - # split hash and plain - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $base64_part = substr ($hash_in, 2, -1); - - ($_, $salt, $iter, $param) = domino_85x_decode ($base64_part); - - next if ($iter < 1); - } - # Cisco $8$ - PBKDF2-HMAC-SHA256 - elsif ($mode == 9200) - { - next unless (substr ($line, 0, 3) eq '$8$'); - - # get hash - my $index1 = index ($line, "\$", 3); - - next if $index1 != 17; - - my $index2 = index ($line, "\$", $index1 + 1); - - # salt - $salt = substr ($line, 3, $index1 - 3); - - $index1 = index ($line, ":", $index1 + 1); - - next if $index1 < 1; - - # digest - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Cisco $9$ - scrypt - elsif ($mode == 9300) - { - next unless (substr ($line, 0, 3) eq '$9$'); - - # get hash - my $index1 = index ($line, "\$", 3); - - next if $index1 != 17; - - my $index2 = index ($line, "\$", $index1 + 1); - - # salt - $salt = substr ($line, 3, $index1 - 3); - - $index1 = index ($line, ":", $index1 + 1); - - next if $index1 < 1; - - # digest - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Office 2007 - elsif ($mode == 9400) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 8; - - next unless (shift @data eq '$office$'); - next unless (shift @data eq '2007'); - next unless (shift @data eq '20'); - - my $aes_key_size = shift @data; - - next unless (($aes_key_size eq '128') || ($aes_key_size eq '256')); - next unless (shift @data eq '16'); - - next unless (length $data[0] == 32); - next unless (length $data[1] == 32); - next unless (length $data[2] == 40); - - $salt = shift @data; - $param = shift @data; - $param2 = $aes_key_size; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Office 2010 - elsif ($mode == 9500) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 8; - - next unless (shift @data eq '$office$'); - next unless (shift @data eq '2010'); - next unless (shift @data eq '100000'); - next unless (shift @data eq '128'); - next unless (shift @data eq '16'); - - next unless (length $data[0] == 32); - next unless (length $data[1] == 32); - next unless (length $data[2] == 64); - - $salt = shift @data; - $param = shift @data; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Office 2013 - elsif ($mode == 9600) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 8; - - next unless (shift @data eq '$office$'); - next unless (shift @data eq '2013'); - next unless (shift @data eq '100000'); - next unless (shift @data eq '256'); - next unless (shift @data eq '16'); - - next unless (length $data[0] == 32); - next unless (length $data[1] == 32); - next unless (length $data[2] == 64); - - $salt = shift @data; - $param = shift @data; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Office Old $1 $2 - elsif ($mode == 9700) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 4; - - my $signature = shift @data; - - next unless (($signature eq '$oldoffice$0') || ($signature eq '$oldoffice$1')); - - next unless (length $data[0] == 32); - next unless (length $data[1] == 32); - next unless (length $data[2] == 32); - - $salt = shift @data; - $param = shift @data; - $param2 = substr ($signature, 11, 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Office Old $3 $4 - elsif ($mode == 9800) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 4; - - my $signature = shift @data; - - next unless (($signature eq '$oldoffice$3') || ($signature eq '$oldoffice$4')); - - next unless (length $data[0] == 32); - next unless (length $data[1] == 32); - next unless (length $data[2] == 40); - - $salt = shift @data; - $param = shift @data; - $param2 = substr ($signature, 11, 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Django (PBKDF2-SHA256) - elsif ($mode == 10000) - { - next unless (substr ($line, 0, 14) eq 'pbkdf2_sha256$'); - - # get hash - my $index1 = index ($line, "\$", 14); - - next if $index1 < 1; - - my $index2 = index ($line, "\$", $index1 + 1); - - # iter - - $iter = substr ($line, 14, $index1 - 14); - - - # salt - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - # digest - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # SipHash - elsif ($mode == 10100) - { - my $hash; - - ($hash, undef, undef, $salt, $word) = split ":", $line; - - next unless defined $hash; - next unless defined $salt; - next unless defined $word; - - next unless (length $hash == 16); - next unless (length $salt == 32); - - my $hash_in = sprintf ("%s:2:4:%s", $hash, $salt); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Cram MD5 - elsif ($mode == 10200) - { - next unless (substr ($line, 0, 10) eq '$cram_md5$'); - - # get hash - my $index1 = index ($line, "\$", 10); - - next if $index1 < 1; - - # challenge - - my $challengeb64 = substr ($line, 10, $index1 - 10); - $salt = decode_base64 ($challengeb64); - - # response - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - my $responseb64 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - my $response = decode_base64 ($responseb64); - - $param = substr ($response, 0, length ($response) - 32 - 1); # -1 is for space - - $word = substr ($line, $index2 + 1); - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # SAP CODVN H (PWDSALTEDHASH) iSSHA-1 - elsif ($mode == 10300) - { - next unless (substr ($line, 0, 10) eq '{x-issha, '); - - # get iterations - - my $index1 = index ($line, "}", 10); - - next if $index1 < 1; - - $iter = substr ($line, 10, $index1 - 10); - - $iter = int ($iter); - - # base64 substring - - my $base64_encoded = substr ($line, $index1 + 1); - my $base64_decoded = decode_base64 ($base64_encoded); - - $salt = substr ($base64_decoded, 20); - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $word = substr ($line, $index2 + 1); - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PDF 1.1 - 1.3 (Acrobat 2 - 4) - elsif ($mode == 10400) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 11; - - next unless (shift @data eq '$pdf$1'); - next unless (shift @data eq '2'); - next unless (shift @data eq '40'); - my $P = shift @data; - next unless (shift @data eq '0'); - next unless (shift @data eq '16'); - my $id = shift @data; - next unless (shift @data eq '32'); - my $u = shift @data; - next unless (shift @data eq '32'); - my $o = shift @data; - - $salt = $id; - $param = $u; - $param2 = $o; - $param3 = $P; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PDF 1.4 - 1.6 (Acrobat 5 - 8) - elsif ($mode == 10500) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data == 11; - - my $V = shift @data; $V = substr ($V, 5, 1); - my $R = shift @data; - next unless (shift @data eq '128'); - my $P = shift @data; - my $enc = shift @data; - next unless (shift @data eq '16'); - my $id = shift @data; - next unless (shift @data eq '32'); - my $u = shift @data; - next unless (shift @data eq '32'); - my $o = shift @data; - - $salt = $id; - $param = $u; - $param2 = $o; - $param3 = $P; - $param4 = $V; - $param5 = $R; - $param6 = $enc; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PDF 1.7 Level 3 (Acrobat 9) - elsif ($mode == 10600) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data >= 11; - - next unless (shift @data eq '$pdf$5'); - next unless (shift @data eq '5'); - next unless (shift @data eq '256'); - next unless (shift @data eq '-1028'); - next unless (shift @data eq '1'); - next unless (shift @data eq '16'); - my $id = shift @data; - my $rest = join "*", @data; - - $salt = $id; - $param = $rest; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PDF 1.7 Level 8 (Acrobat 10 - 11) - elsif ($mode == 10700) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\*/, $hash_in; - - next unless scalar @data >= 11; - - next unless (shift @data eq '$pdf$5'); - next unless (shift @data eq '6'); - next unless (shift @data eq '256'); - next unless (shift @data eq '-1028'); - next unless (shift @data eq '1'); - next unless (shift @data eq '16'); - my $id = shift @data; - my $rest = join "*", @data; - - $salt = $id; - $param = $rest; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PBKDF2-HMAC-SHA256 - elsif ($mode == 10900) - { - next unless (substr ($line, 0, 7) eq 'sha256:'); - - # iterations - my $index1 = index ($line, ":", 7); - - next if $index1 < 1; - - $iter = substr ($line, 7, $index1 - 7); - - # salt - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = decode_base64 ($salt); - - # end of digest - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # additional param = output len of pbkdf2 - - my $digest64_encoded = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - my $digest = decode_base64 ($digest64_encoded); - - $param = length ($digest); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PostgreSQL MD5 Authentication - elsif ($mode == 11100) - { - next unless (substr ($line, 0, 10) eq '$postgres$'); - - my $index1 = index ($line, "*", 10); - - next if $index1 < 1; - - # the user name - - $param = substr ($line, 10, $index1 - 10); - - # get the 4 byte salt - - my $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - # word / hash - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # MySQL MD5 Authentication - elsif ($mode == 11200) - { - next unless (substr ($line, 0, 9) eq '$mysqlna$'); - - my $index1 = index ($line, "*", 9); - - next if $index1 < 1; - - # salt - - $salt = substr ($line, 9, $index1 - 9); - - # word / hash - - $index1 = index ($line, ":", $index1 + 1); - - next if $index1 < 1; - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # WPA-EAPOL-PBKDF2 - elsif ($mode == 2500) - { - print "ERROR: verify currently not supported for WPA-EAPOL-PBKDF2 (because of hashcat's output format)\n"; - - exit (1); - } - # Bitcoin/Litecoin wallet.dat - elsif ($mode == 11300) - { - print "ERROR: verify currently not supported for Bitcoin/Litecoin wallet.dat because of unknown crypt data\n"; - - exit (1); - } - # SIP digest authentication (MD5) - elsif ($mode == 11400) - { - next unless (substr ($line, 0, 6) eq '$sip$*'); - - # URI_server: - - my $index1 = index ($line, "*", 6); - - next if $index1 < 0; - - $param10 = substr ($line, 6, $index1 - 6); - - next if (length ($param10) > 32); - - # URI_client: - - my $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param11 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param11) > 32); - - # user: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - $param = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next if (length ($param) > 12); - - # realm: - - $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param2 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param2) > 20); - - # method: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - $param6 = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next if (length ($param6) > 24); - - # URI_prefix: - - $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param7 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param7) > 10); - - # URI_resource: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - $param8 = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next if (length ($param8) > 32); - - # URI_suffix: - - $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param9 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param9) > 32); - - # nonce: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - $salt = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next if (length ($salt) > 34); - - # nonce_client: - - $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param4 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param4) > 12); - - # nonce_count: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - $param3 = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next if (length ($param3) > 10); - - # qop: - - $index2 = index ($line, "*", $index1 + 1); - - next if $index2 < 0; - - $param5 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next if (length ($param5) > 8); - - # directive: - - $index1 = index ($line, "*", $index2 + 1); - - next if $index1 < 0; - - my $directive = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - next unless ($directive eq "MD5"); - - # hash_buf: - - $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 0; - - my $hex_digest = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - next unless (length ($hex_digest) == 32); - - $word = substr ($line, $index2 + 1); - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # 7-Zip - elsif ($mode == 11600) - { - next unless (substr ($line, 0, 4) eq '$7z$'); - - # p - - my $index1 = index ($line, '$', 4); - - next if $index1 < 0; - - my $p = substr ($line, 4, $index1 - 4); - - next unless ($p eq "0"); - - # num cycle power - - my $index2 = index ($line, '$', $index1 + 1); - - next if $index2 < 0; - - $iter = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - # seven zip salt length - - $index1 = index ($line, '$', $index2 + 1); - - next if $index1 < 0; - - $param = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - # seven zip salt - - $index2 = index ($line, '$', $index1 + 1); - - next if $index2 < 0; - - $param2 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - # salt len - - $index1 = index ($line, '$', $index2 + 1); - - next if $index1 < 0; - - $param3 = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - # salt - - $index2 = index ($line, '$', $index1 + 1); - - next if $index2 < 0; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = pack ("H*", $salt); - - # crc / hash - - $index1 = index ($line, '$', $index2 + 1); - - next if $index1 < 0; - - my $crc = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - # ignore this crc, we don't need to pass it to gen_hash () - - # data len - - $index2 = index ($line, '$', $index1 + 1); - - next if $index2 < 0; - - $param4 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - # unpack size - - $index1 = index ($line, '$', $index2 + 1); - - next if $index1 < 0; - - $param5 = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - # data - - $index2 = index ($line, ':', $index1 + 1); - - next if $index2 < 0; - - $param6 = substr ($line, $index1 + 1, $index2 - $index1 - 1); - $param6 = pack ("H*", $param6); - - $word = substr ($line, $index2 + 1); - $hash_in = substr ($line, 0, $index2); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PBKDF2-HMAC-MD5 - elsif ($mode == 11900) - { - next unless (substr ($line, 0, 4) eq 'md5:'); - - # iterations - my $index1 = index ($line, ":", 4); - - next if $index1 < 1; - - $iter = substr ($line, 4, $index1 - 4); - - # salt - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = decode_base64 ($salt); - - # end of digest - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # additional param = output len of pbkdf2 - - my $digest64_encoded = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - my $digest = decode_base64 ($digest64_encoded); - - $param = length ($digest); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PBKDF2-HMAC-SHA1 - elsif ($mode == 12000) - { - next unless (substr ($line, 0, 5) eq 'sha1:'); - - # iterations - my $index1 = index ($line, ":", 5); - - next if $index1 < 1; - - $iter = substr ($line, 5, $index1 - 5); - - # salt - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = decode_base64 ($salt); - - # end of digest - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # additional param = output len of pbkdf2 - - my $digest64_encoded = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - my $digest = decode_base64 ($digest64_encoded); - - $param = length ($digest); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # PBKDF2-HMAC-SHA512 - elsif ($mode == 12100) - { - next unless (substr ($line, 0, 7) eq 'sha512:'); - - # iterations - my $index1 = index ($line, ":", 7); - - next if $index1 < 1; - - $iter = substr ($line, 7, $index1 - 7); - - # salt - - my $index2 = index ($line, ":", $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $salt = decode_base64 ($salt); - - # end of digest - - $index1 = index ($line, ":", $index2 + 1); - - next if $index1 < 1; - - # additional param = output len of pbkdf2 - - my $digest64_encoded = substr ($line, $index2 + 1, $index1 - $index2 - 1); - - my $digest = decode_base64 ($digest64_encoded); - - $param = length ($digest); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # ecryptfs - elsif ($mode == 12200) - { - next unless (substr ($line, 0, 12) eq '$ecryptfs$0$'); - - # check if default salt - - $param = 1; - - $param = 0 if (substr ($line, 12, 2) eq '1$'); - - # salt - - $salt = ""; - - my $index1 = 12; - - if ($param == 0) # we need to extract the salt - { - $index1 = index ($line, '$', $index1); - - next if $index1 < 1; - - my $index2 = index ($line, '$', $index1 + 1); - - next if $index2 < 1; - - $salt = substr ($line, $index1 + 1, $index2 - $index1 - 1); - - $index1 = $index2; - } - - $index1 = index ($line, ':', $index1 + 1); - - next if $index1 < 1; - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Oracle T: Type (Oracle 12+) - elsif ($mode == 12300) - { - my $index1 = index ($line, ':'); - - next if ($index1 != 160); - - # salt - - $salt = substr ($line, 128, 32); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # BSDi Crypt, Extended DES - elsif ($mode == 12400) - { - next unless (substr ($line, 0, 1) eq '_'); - - my $index1 = index ($line, ':', 20); - - next if ($index1 != 20); - - # iter - - $iter = substr ($line, 1, 4); - - $iter = base64_to_int24 ($iter); - - # salt - - $salt = substr ($line, 5, 4); - - # word / hash - - $word = substr ($line, $index1 + 1); - $hash_in = substr ($line, 0, $index1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Blockchain, My Wallet - elsif ($mode == 12700) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - my (undef, $signature, $data_len, $data_buf) = split '\$', $hash_in; - - next unless ($signature eq "blockchain"); - - next unless (($data_len * 2) == length $data_buf); - - $salt = substr ($data_buf, 0, 32); - $param = substr ($data_buf, 32); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 12800) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split /\,/, $hash_in; - - next unless scalar @data == 4; - - next unless (shift @data eq 'v1;PPH1_MD4'); - - $salt = shift @data; - $iter = shift @data; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 12900) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - next unless length $hash_in == 160; - - $param = substr ($hash_in, 0, 64); - $salt = substr ($hash_in, 128, 32); - $iter = 4096; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 13000) - { - my $hash_line; - - ($hash_line, $word) = split ":", $line; - - next unless defined $hash_line; - next unless defined $word; - - my @data = split ('\$', $hash_line); - - next unless scalar @data == 8; - - shift @data; - - my $signature = shift @data; - my $salt_len = shift @data; - my $salt_buf = shift @data; - my $iterations = shift @data; - my $iv = shift @data; - my $pswcheck_len = shift @data; - my $pswcheck = shift @data; - - next unless ($signature eq "rar5"); - next unless ($salt_len == 16); - next unless ($pswcheck_len == 8); - - $salt = $salt_buf; - $iter = $iterations; - $hash_in = $pswcheck; - $param = $iv; - - next unless (exists ($db->{$hash_line}) and (! defined ($db->{$hash_line}))); - } - elsif ($mode == 13100) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 8; - - shift @data; - - my $signature = shift @data; - my $algorithm = shift @data; - my $user = shift @data; - $user = substr ($user, 1); - my $realm = shift @data; - my $spn = shift @data; - $spn = substr ($spn, 0, length ($spn) - 1); - my $checksum = shift @data; - my $edata2 = shift @data; - - next unless ($signature eq "krb5tgs"); - next unless (length ($checksum) == 32); - next unless (length ($edata2) >= 64); - - $salt = $user . '$' . $realm . '$' . $spn . '$'; - - $param = $checksum; - $param2 = $edata2; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 13200) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless scalar @data == 5; - - my $signature = shift @data; - my $version = shift @data; - my $iteration = shift @data; - my $mysalt = shift @data; - my $digest = shift @data; - - next unless ($signature eq '$axcrypt$'); - next unless (length ($mysalt) == 32); - next unless (length ($digest) == 48); - - $salt = $iteration . '*' . $mysalt; - $param = $digest; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 13300) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 3; - - shift @data; - - my $signature = shift @data; - my $digest = shift @data; - - $param = length ($digest); - - next unless ($signature eq 'axcrypt_sha1'); - next unless (($param == 32) || ($param == 40)); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 13400) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless (scalar @data == 9 - || scalar @data == 11 - || scalar @data == 12 - || scalar @data == 14); - - my $signature = shift @data; - next unless ($signature eq '$keepass$'); - - my $version = shift @data; - next unless ($version == 1 || $version == 2); - - my $iteration = shift @data; - - my $algorithm = shift @data; - - my $final_random_seed = shift @data; - - if ($version == 1) - { - next unless (length ($final_random_seed) == 32); - } - elsif ($version == 2) - { - next unless (length ($final_random_seed) == 64); - } - - my $transf_random_seed = shift @data; - next unless (length ($transf_random_seed) == 64); - - my $enc_iv = shift @data; - next unless (length ($enc_iv) == 32); - - if ($version == 1) - { - my $contents_hash = shift @data; - next unless (length ($contents_hash) == 64); - - my $inline_flags = shift @data; - next unless ($inline_flags == 1); - - my $contents_len = shift @data; - - my $contents = shift @data; - next unless (length ($contents) == $contents_len * 2); - } - elsif ($version == 2) - { - my $expected_bytes = shift @data; - next unless (length ($expected_bytes) == 64); - - my $contents_hash = shift @data; - next unless (length ($contents_hash) == 64); - } - - if (scalar @data == 12 || scalar @data == 14) - { - my $inline_flags = shift @data; - next unless ($inline_flags == 1); - - my $keyfile_len = shift @data; - next unless ($keyfile_len == 64); - - my $keyfile = shift @data; - next unless (length ($keyfile) == $keyfile_len); - } - - $salt = substr ($hash_in, length ("*keepass*") + 1); - $param = 1; # distinguish between encrypting vs decrypting - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 13600) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless scalar @data == 10; - - my $tag_start = shift @data; - my $type = shift @data; - my $mode = shift @data; - my $magic = shift @data; - my $salt = shift @data; - my $verify_bytes = shift @data; - my $length = shift @data; - my $data = shift @data; - my $auth = shift @data; - my $tag_end = shift @data; - - next unless ($tag_start eq '$zip2$'); - next unless ($tag_end eq '$/zip2$'); - - $param = $type; - $param2 = $mode; - $param3 = $magic; - $param4 = $salt; - $param5 = $length; - $param6 = $data; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # itunes backup 9/10 - elsif (($mode == 14700) || ($mode == 14800)) - { - ($hash_in, $word) = split ":", $line; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - my $index1 = index ($hash_in, '*'); - - next unless ($index1 == 15); - - # signature - - my $signature = substr ($hash_in, 0, $index1); - - next unless ($signature eq '$itunes_backup$'); - - my $index2 = index ($hash_in, '*', $index1 + 1); - - next unless ($index2 >= 0); - - # version - - my $version = substr ($hash_in, $index1 + 1, $index2 - $index1 - 1); - - if ($mode == 14700) - { - next unless ($version eq "9"); - } - else - { - next unless ($version eq "10"); - } - - $index1 = index ($hash_in, '*', $index2 + 1); - - next unless ($index1 >= 0); - - # wpky - - my $wpky = substr ($hash_in, $index2 + 1, $index1 - $index2 - 1); - - next unless (length ($wpky) == 80); - - $wpky = pack ("H*", $wpky); - - $param = $wpky; - - $index2 = index ($hash_in, '*', $index1 + 1); - - next unless ($index2 >= 0); - - # iterations - - $iter = substr ($hash_in, $index1 + 1, $index2 - $index1 - 1); - $iter = int ($iter); - - next unless ($iter > 0); - - $index1 = index ($hash_in, '*', $index2 + 1); - - next unless ($index1 >= 0); - - # salt - - $salt = substr ($hash_in, $index2 + 1, $index1 - $index2 - 1); - - next unless (length ($salt) == 40); - - # dpic and dpsl - - if ($mode == 14700) - { - $index2 = index ($hash_in, '**', $index1 + 1); - - next unless ($index2 != $index1 + 1); - } - else - { - $index2 = index ($hash_in, '*', $index1 + 1); - - next unless ($index2 >= 0); - - # dpic - - my $dpic = substr ($hash_in, $index1 + 1, $index2 - $index1 - 1); - - $dpic = int ($dpic); - - next unless ($dpic > 0); - - $param2 = $dpic; - - # dpsl - - my $dpsl = substr ($hash_in, $index2 + 1); - - next unless (length ($dpsl) == 40); - - $dpsl = pack ("H*", $dpsl); - - $param3 = $dpsl; - } - } - # base64 and salt embedded SSHA256, salt length = total length - 32 - elsif ($mode == 1411) - { - # split hash and plain - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - - # remove signature - my $plain_base64 = substr ($hash_in, 9); - - # base64 decode to extract salt - my $decoded = decode_base64 ($plain_base64); - - $salt = substr ($decoded, 32); - } - # Atlassian (PBKDF2-HMAC-SHA1) - elsif ($mode == 12001) - { - my $index = index ($line, ":"); - - next if $index < 1; - - $hash_in = substr ($line, 0, $index); - $word = substr ($line, $index + 1); - - next unless (substr ($hash_in, 0, 9) eq '{PKCS5S2}'); - - # base64 buf - - my $base64_buf = substr ($hash_in, 9); - my $base64_buf_decoded = decode_base64 ($base64_buf); - - next if (length ($base64_buf_decoded) != (16 + 32)); - - $salt = substr ($base64_buf_decoded, 0, 16); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 15100) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 5; - - shift @data; - - my $signature = shift @data; - - next unless ($signature eq 'sha1'); - - $iter = shift @data; - $salt = shift @data; - $param = shift @data; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 15200) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - my (undef, $signature, $version, $iter_count, $data_len, $data_buf) = split '\$', $hash_in; - - next unless ($signature eq "blockchain"); - - next unless ($version eq "v2"); - - next unless (($data_len * 2) == length $data_buf); - - $iter = $iter_count; - $salt = substr ($data_buf, 0, 32); - $param = substr ($data_buf, 32); - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 15300 || $mode == 15900) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @tmp_data = split ('\$', $hash_in); - - my $signature = $tmp_data[1]; - - next unless ($signature eq 'DPAPImk'); - - my @data = split ('\*', $tmp_data[2]); - - next unless (scalar @data == 9); - - my $version = shift @data; - - next unless ($version == 1 || $version == 2); - - my $context = shift @data; - - my $SID = shift @data; - - my $cipher_algorithm = shift @data; - - my $hash_algorithm = shift @data; - - my $iteration = shift @data; - - my $iv = shift @data; - - my $cipher_len = shift @data; - - my $cipher = shift @data; - - next unless (length ($cipher) == $cipher_len); - - if ($version == 1) - { - next unless ($cipher_len == 208); - } - elsif ($version == 2) - { - next unless ($cipher_len == 288); - } - - $salt = substr ($hash_in, length ('$DPAPImk$')); - - $param = $cipher; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # chacha - elsif ($mode == 15400) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next if (length ($hash_in) < 11); - - next unless (substr ($hash_in, 0, 11) eq "\$chacha20\$\*"); - - my @data = split ('\*', $hash_in); - - next unless (scalar (@data) == 6); - - $param = $data[1]; # counter - $param2 = $data[2]; # offset - $param3 = $data[3]; # iv - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # jksprivk - elsif ($mode == 15500) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless scalar @data == 7; - - my $signature = shift @data; - - next unless ($signature eq '$jksprivk$'); - - my $checksum = shift @data; - my $iv = shift @data; - my $enc_key = shift @data; - my $DER1 = shift @data; - my $DER2 = shift @data; - my $alias = shift @data; - - $param = $iv; - $param2 = $enc_key; - $param3 = $alias; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Ethereum - PBKDF2 - elsif ($mode == 15600) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next if (length ($hash_in) < 12); - - next unless (substr ($hash_in, 0, 12) eq "\$ethereum\$p\*"); - - my @data = split ('\*', $hash_in); - - next unless (scalar (@data) == 5); - - $iter = $data[1]; - - $salt = pack ("H*", $data[2]); - - $param = pack ("H*", $data[3]); # ciphertext - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Ethereum - Scrypt - elsif ($mode == 15700) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next if (length ($hash_in) < 12); - - next unless (substr ($hash_in, 0, 12) eq "\$ethereum\$s\*"); - - my @data = split ('\*', $hash_in); - - next unless (scalar (@data) == 7); - - $param = $data[1]; # scrypt_N - $param2 = $data[2]; # scrypt_r - $param3 = $data[3]; # scrypt_p - - $salt = pack ("H*", $data[4]); - - $param4 = pack ("H*", $data[5]); # ciphertext - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # tacacs-plus - elsif ($mode == 16100) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 6; - - shift @data; - - my $signature = shift @data; - - next unless ($signature eq "tacacs-plus"); - - my $auth_version = shift @data; - - next unless ($auth_version eq "0"); - - my $session_id = shift @data; - my $encrypted_data = shift @data; - my $sequence = shift @data; - - $param = $session_id; - $param2 = $encrypted_data; - $param3 = $sequence; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # apple secure notes - elsif ($mode == 16200) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless scalar @data == 5; - - my $signature = shift @data; - - next unless ($signature eq '$ASN$'); - - my ($Z_PK, $ZCRYPTOITERATIONCOUNT, $ZCRYPTOSALT, $ZCRYPTOWRAPPEDKEY) = @data; - - $salt = $ZCRYPTOSALT; - $iter = $ZCRYPTOITERATIONCOUNT; - - $param = $Z_PK; - $param2 = $ZCRYPTOWRAPPEDKEY; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Ethereum Pre-Sale - PBKDF2 - elsif ($mode == 16300) - { - my $index1 = index ($line, ':'); - - next if ($index1 < 0); - - $hash_in = substr ($line, 0, $index1); - $word = substr ($line, $index1 + 1); - - next if (length ($hash_in) < 12); - - next unless (substr ($hash_in, 0, 12) eq "\$ethereum\$w\*"); - - my @data = split ('\*', $hash_in); - - next unless (scalar (@data) == 4); - - $param = pack ("H*", $data[1]); # encseed - - $salt = $data[2]; # ethaddr - - $param2 = pack ("H*", $data[3]); # bpk (the iv + keccak digest) - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # JWT - elsif ($mode == 16500) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split (/\./, $hash_in); - - next unless scalar @data == 3; - - my ($header, $payload, $signature) = @data; - - $salt = $header . "." . $payload; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Electrum Wallet (Salt-Type 1-3) - elsif ($mode == 16600) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split (/\*/, $hash_in); - - next unless scalar @data == 3; - - my ($mode, $iv, $encrypted) = @data; - - my (undef, $signature, $salt_type) = split ('\$', $mode); - - next unless ($signature eq "electrum"); - - $param = $salt_type; - $param2 = $iv; - $param3 = $encrypted; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # FileVault 2 - elsif ($mode == 16700) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 7; - - shift @data; - - my $signature = shift @data; - - next unless ($signature eq 'fvde'); - - my $Z_PK = shift @data; - - next unless ($Z_PK eq '1'); - - my $salt_length = shift @data; - - next unless ($salt_length eq '16'); - - my ($ZCRYPTOSALT, $ZCRYPTOITERATIONCOUNT, $ZCRYPTOWRAPPEDKEY) = @data; - - $salt = $ZCRYPTOSALT; - $iter = $ZCRYPTOITERATIONCOUNT; - - $param = $Z_PK; - $param2 = $ZCRYPTOWRAPPEDKEY; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # WPA-PMKID-PMKDF2 - elsif ($mode == 16800) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split (/\*/, $hash_in); - - next unless scalar @data == 4; - - my ($pmkid, $macap, $macsta, $essid) = @data; - - $param = $macap; - $param2 = $macsta; - $param3 = $essid; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # Ansible Vault - elsif ($mode == 16900) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\*', $hash_in); - - next unless scalar @data == 5; - - my ($signature_tmp, $cipher, $salt, $ciphertext, $hmac) = @data; - - my ($signature, undef) = split ('\$', $signature_tmp); - - next unless ($signature eq "ansible"); - - $param = $ciphertext; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 18200) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 8; - - shift @data; - - my $signature = shift @data; - my $algorithm = shift @data; - my $user_principal_name = shift @data; - my $checksum = shift @data; - my $edata2 = shift @data; - - next unless ($signature eq "krb5asrep"); - next unless (length ($checksum) == 32); - next unless (length ($edata2) >= 64); - - $salt = $user_principal_name; - - $param = $checksum; - $param2 = $edata2; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - # FileVault 2 - elsif ($mode == 18300) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - my @data = split ('\$', $hash_in); - - next unless scalar @data == 7; - - shift @data; - - my $signature = shift @data; - - next unless ($signature eq 'fvde'); - - my $Z_PK = shift @data; - - next unless ($Z_PK eq '2'); - - my $salt_length = shift @data; - - next unless ($salt_length eq '16'); - - my ($ZCRYPTOSALT, $ZCRYPTOITERATIONCOUNT, $ZCRYPTOWRAPPEDKEY) = @data; - - $salt = $ZCRYPTOSALT; - $iter = $ZCRYPTOITERATIONCOUNT; - - $param = $Z_PK; - $param2 = $ZCRYPTOWRAPPEDKEY; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 18400) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - # tokenize - my @data = split ('\*', $hash_in); - - next unless scalar @data == 12; - - my $signature = shift @data; - my $cipher_type = shift @data; - my $cs_type = shift @data; - $iter = shift @data; - my $cs_len = shift @data; - my $cs = shift @data; - my $iv_len = shift @data; - my $iv = shift @data; - my $salt_len = shift @data; - $salt = shift @data; - my $unused = shift @data; - my $ciphertext = shift @data; - - # validate - next unless ($signature eq '$odf$'); - next unless ($cipher_type eq '1'); - next unless ($cs_type eq '1'); - next unless ($cs_len eq '32'); - next unless ($iv_len eq '16'); - next unless ($salt_len eq '16'); - next unless ($unused eq '0'); - next unless defined $ciphertext; - - # decrypt - my $b_iv = pack ("H*", $iv); - my $b_salt = pack ("H*", $salt); - my $b_ciphertext = pack ("H*", $ciphertext); - - my $kdf = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iter, - output_len => 32 - ); - - my $pass_hash = sha256 ($word); - my $derived_key = $kdf->PBKDF2 ($b_salt, $pass_hash); - my $cbc = Crypt::Mode::CBC->new ('AES', 0); - my $b_plaintext = $cbc->decrypt ($b_ciphertext, $derived_key, $b_iv); - - my $plaintext = unpack ("H*", $b_plaintext); - - $param = $iv; - $param2 = $plaintext; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - elsif ($mode == 18600) - { - ($hash_in, $word) = split ":", $line; - - next unless defined $hash_in; - next unless defined $word; - - # tokenize - my @data = split ('\*', $hash_in); - - next unless scalar @data == 12; - - my $signature = shift @data; - my $cipher_type = shift @data; - my $cs_type = shift @data; - $iter = shift @data; - my $cs_len = shift @data; - my $cs = shift @data; - my $iv_len = shift @data; - my $iv = shift @data; - my $salt_len = shift @data; - $salt = shift @data; - my $unused = shift @data; - my $ciphertext = shift @data; - - # validate - next unless ($signature eq '$odf$'); - next unless ($cipher_type eq '0'); - next unless ($cs_type eq '0'); - next unless ($cs_len eq '16'); - next unless ($iv_len eq '8'); - next unless ($salt_len eq '16'); - next unless ($unused eq '0'); - next unless defined $ciphertext; - - # decrypt - my $b_iv = pack ("H*", $iv); - my $b_salt = pack ("H*", $salt); - my $b_ciphertext = pack ("H*", $ciphertext); - - my $kdf = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iter, - output_len => 16 - ); - - my $pass_hash = sha1 ($word); - my $derived_key = $kdf->PBKDF2 ($b_salt, $pass_hash); - - my $cfb = Crypt::GCrypt->new( - type => 'cipher', - algorithm => 'blowfish', - mode => 'cfb' - ); - - $cfb->start ('decrypting'); - $cfb->setkey ($derived_key); - $cfb->setiv ($b_iv); - - my $b_plaintext = $cfb->decrypt ($b_ciphertext); - - $cfb->finish (); - - my $plaintext = unpack ("H*", $b_plaintext); - - $param = $iv; - $param2 = $plaintext; - - next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); - } - ## STEP 2c: Add your custom hash parser branch here - else - { - print "ERROR: hash mode is not supported\n"; - - exit (1); - } - - if ($word =~ m/^\$HEX\[[0-9a-fA-F]*\]$/) - { - $word = pack ("H*", substr ($word, 5, -1)); - } - - # finally generate the hash - - # special case: - if ($mode == 6800) - { - # check both variations - $hash_out = gen_hash ($mode, $word, $salt, $iter, 1); - - $len = length $hash_out; # == length $alternative - - if (substr ($line, 0, $len) ne $hash_out) - { - my $alternative = gen_hash ($mode, $word, $salt, $iter, 2); - - return unless (substr ($line, 0, $len) eq $alternative); - } - } - elsif ($mode == 8700) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 8900) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 9100) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 3300) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 5100) - { - # check 3 variants (start, middle, end) - - my $idx = 0; - - $hash_out = gen_hash ($mode, $word, $salt, $iter, $idx++); - - $len = length $hash_out; # == length $alternative - - if (substr ($line, 0, $len) ne $hash_out) - { - my $alternative = gen_hash ($mode, $word, $salt, $iter, $idx++); - - if (substr ($line, 0, $len) ne $alternative) - { - my $alternative = gen_hash ($mode, $word, $salt, $iter, $idx++); - - return unless (substr ($line, 0, $len) eq $alternative); - } - } - } - elsif ($mode == 9400) - { - $hash_out = gen_hash ($mode, $word, $salt, 50000, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 9500) - { - $hash_out = gen_hash ($mode, $word, $salt, 100000, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 9600) - { - $hash_out = gen_hash ($mode, $word, $salt, 100000, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 9700) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 9800) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10200) - { - $hash_out = gen_hash ($mode, $word, $salt, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10400) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10500) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2, $param3, $param4, $param5, $param6); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10600) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10700) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 10900) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 11100) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 11400) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2, $param3, $param4, $param5, $param6, $param7, $param8, $param9, $param10, $param11); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 11600) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2, $param3, $param4, $param5, $param6); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 11900) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 12000) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 12100) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 12200) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 12700) - { - # this is very special, we can't call gen_hash () because the param part is not always the same - # we only know that it should contain the letters "guid" at the beginning of the decryted string - - my $pbkdf2 = Crypt::PBKDF2->new ( - hash_class => 'HMACSHA1', - iterations => 10, - output_len => 32 - ); - - my $salt_bin = pack ("H*", $salt); - - my $key = $pbkdf2->PBKDF2 ($salt_bin, $word); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $salt_bin, - literal_key => 1, - header => "none", - keysize => 32 - }); - - my $param_bin = pack ("H*", $param); - - my $decrypted = $cipher->decrypt ($param_bin); - - my $decrypted_part = substr ($decrypted, 1, 16); - - return unless ($decrypted_part =~ /"guid"/); - - $hash_out = $hash_in; - } - elsif ($mode == 12900) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13000) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13100) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13200) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13300) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13400) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 13600) - { - $hash_out = gen_hash ($mode, $word, undef, undef, $param, $param2, $param3, $param4, $param5, $param6); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 14700) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 14800) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15100) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15200) - { - # this is very special, we can't call gen_hash () because the param part is not always the same - # we only know that it should contain the letters "guid" at the beginning of the decryted string - - my $pbkdf2 = Crypt::PBKDF2->new ( - hash_class => 'HMACSHA1', - iterations => 5000, - output_len => 32 - ); - - my $salt_bin = pack ("H*", $salt); - - my $key = $pbkdf2->PBKDF2 ($salt_bin, $word); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $salt_bin, - literal_key => 1, - header => "none", - keysize => 32 - }); - - my $param_bin = pack ("H*", $param); - - my $decrypted = $cipher->decrypt ($param_bin); - - my $decrypted_part = substr ($decrypted, 1, 16); - - return unless ($decrypted_part =~ /"guid"/); - - $hash_out = $hash_in; - } - elsif ($mode == 15300 || $mode == 15900) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15400) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15500) - { - $hash_out = gen_hash ($mode, $word, undef, undef, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15600) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 15700) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2, $param3, $param4); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16100) - { - $hash_out = gen_hash ($mode, $word, undef, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16200) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16300) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16600) - { - $hash_out = gen_hash ($mode, $word, undef, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16700) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16800) - { - $hash_out = gen_hash ($mode, $word, undef, 0, $param, $param2, $param3); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 16900) - { - $hash_out = gen_hash ($mode, $word, $salt, 0, $param); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 18200) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 18300) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 18400) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - elsif ($mode == 18600) - { - $hash_out = gen_hash ($mode, $word, $salt, $iter, $param, $param2); - - $len = length $hash_out; - - return unless (substr ($line, 0, $len) eq $hash_out); - } - ## STEP 2c: Add your custom gen_hash call here - else - { - $hash_out = gen_hash ($mode, $word, $salt, $iter); - - $len = length $hash_out; - - # special cases: - if ($mode == 400) - { - # allow $P$ and $H$ for -m 400 - next unless (substr ($line, 3, $len - 3) eq substr ($hash_out, 3)); - } - elsif ($mode == 5600) - { - # hashcat outputs the user name always upper-case, we need - next unless (substr ($line, 0, $len) eq $hash_out); - - my $found = 0; - - my $hash_out_lower = lc ($hash_out); - - for my $key (keys %{$db}) - { - if (lc ($key) eq $hash_out_lower) - { - $found = 1; - - last; - } - } - - next unless $found; - } - else - { - next unless (substr ($line, 0, $len) eq $hash_out); - } - } - - # do not forget "exists ($db->$hash_out)" should be done above! - $db->{$hash_out} = $word; - print OUT $line . "\n"; - } - - close (IN); - close (OUT); -} - -sub passthrough -{ - my $mode = shift || 0; - - while (my $word_buf = <>) - { - chomp ($word_buf); - - next if length ($word_buf) > 256; - - ## - ## gen salt - ## - - my @salt_arr; - - for (my $i = 0; $i < 256; $i++) - { - my $c = get_random_chr (0x30, 0x39); - - push (@salt_arr, $c); - } - - my $salt_buf = join ("", @salt_arr); - - ## - ## gen hash - ## - - my $tmp_hash; - - # unsalted - if (is_in_array ($mode, $COMMON_UNSALTED_MODES) - || $mode == 2400 || $mode == 13300) - { - $tmp_hash = gen_hash ($mode, $word_buf, ""); - } - elsif (is_in_array ($mode, $COMMON_DEFAULT_SALTED_MODES) - || $mode == 1411 || $mode == 1711 || $mode == 3711 || $mode == 3800 - || $mode == 4900 || $mode == 8900 || $mode == 10000 || $mode == 10200 - || $mode == 10900 || $mode == 11900 || $mode == 12000 || $mode == 12100) - { - my $salt_len = get_random_num (1, 15); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 11 || $mode == 12) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 21) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 2)); - } - elsif ($mode == 22) - { - my $salt_len = get_random_num (1, 11); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 111 || $mode == 122 || $mode == 131 || $mode == 132 - || $mode == 400 || $mode == 500 || $mode == 1600 || $mode == 1722 - || $mode == 1731 || $mode == 1800 || $mode == 6300 || $mode == 7900 - || $mode == 8100 || $mode == 11100) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 8)); - } - elsif ($mode == 112) - { - next if length ($word_buf) > 30; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 20)); - } - elsif ($mode == 121) - { - my $salt_len = get_random_num (1, 9); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 125) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 8)); - } - elsif ($mode == 141 || $mode == 1441) - { - my $salt_len = get_random_num (1, 15); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 1100) - { - my $salt_len = get_random_num (1, 19); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 1500) - { - next if length ($word_buf) > 8; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 2)); - } - elsif ($mode == 2100) - { - next if length ($word_buf) > 13; - - my $salt_len = get_random_num (1, 19); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 2410) - { - my $salt_len = get_random_num (1, 4); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 2500) - { - next if length ($word_buf) < 8; - - my $salt_len = get_random_num (0, 32); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 2611) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 3)); - } - elsif ($mode == 2612) - { - my $salt_len = get_random_num (1, 22); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 2711) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 30)); - } - elsif ($mode == 2811) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 5)); - } - elsif ($mode == 3000) - { - next if length ($word_buf) > 7; - - $tmp_hash = gen_hash ($mode, $word_buf, ""); - } - elsif ($mode == 3100) - { - next if length ($word_buf) > 30; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 10)); - } - elsif ($mode == 3200 || $mode == 5800 || $mode == 6400 || $mode == 6500 || $mode == 6700 || $mode == 7400 || $mode == 3300 || $mode == 8000 || $mode == 9100 || $mode == 12001 || $mode == 12200 || $mode == 15600) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 16)); - } - elsif ($mode == 3800 || $mode == 4900) - { - my $salt_len = get_random_num (1, 11); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 4520) - { - my $salt_len = get_random_num (1, 50); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 4521 || $mode == 15700) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 4522) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 12)); - } - elsif ($mode == 4800) - { - $salt_buf = get_random_md5chap_salt (substr ($salt_buf, 0, 16)); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 5300 || $mode == 5400) - { - $salt_buf = get_random_ike_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 5500) - { - my $user_len = get_random_num (0, 15); - my $domain_len = get_random_num (0, 15); - - $salt_buf = get_random_netntlmv1_salt ($user_len, $domain_len); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 5600) - { - my $user_len = get_random_num (0, 15); - my $domain_len = get_random_num (0, 15); - - $salt_buf = get_random_netntlmv2_salt ($user_len, $domain_len); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 6600) - { - $salt_buf = get_random_agilekeychain_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 6800) - { - my $email_len = get_random_num (1, 15); - - my $email = ""; - - for (my $i = 0; $i < $email_len; $i++) - { - $email .= get_random_chr (0x61, 0x7a); - } - - $email .= '@trash-mail.com'; - - $tmp_hash = gen_hash ($mode, $word_buf, $email); - } - elsif ($mode == 7000) - { - next if length ($word_buf) > 19; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 24)); - } - elsif ($mode == 7100) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 64)); - } - elsif ($mode == 7200) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 128)); - } - elsif ($mode == 7300) - { - my $salt_len = get_random_num (32, 256); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 7500) - { - $salt_buf = get_random_kerberos5_salt (substr ($salt_buf, 0, 16)); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 7700 || $mode == 7701) - { - next if length ($word_buf) > 8; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 12)); - } - elsif ($mode == 7800 || $mode == 7801) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 12)); - } - elsif ($mode == 8200) - { - $salt_buf = get_random_cloudkeychain_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 8300) - { - $salt_buf = get_random_dnssec_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 8400 || $mode == 11200 || $mode == 16300) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 40)); - } - elsif ($mode == 8500) - { - next if length ($word_buf) > 8; - - my $salt_len = get_random_num (1, 9); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 8600) - { - next if length ($word_buf) > 16; - - $tmp_hash = gen_hash ($mode, $word_buf, ""); - } - elsif ($mode == 8700) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 5)); - } - elsif ($mode == 9200 || $mode == 9300) - { - my $salt_len = 14; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 9400 || $mode == 9500 || $mode == 9600) - { - next if length ($word_buf) > 19; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 9700 || $mode == 9800) - { - next if length ($word_buf) > 15; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 10100) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 10300) - { - my $salt_len = get_random_num (4, 15); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 10400) - { - next if length ($word_buf) > 31; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 10500) - { - next if length ($word_buf) > 15; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 10600) - { - next if length ($word_buf) > 31; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 10700) - { - next if length ($word_buf) > 15; - - my $salt_len = 32; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 11000) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 56)); - } - elsif ($mode == 11300) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 16)); - } - elsif ($mode == 11400) - { - next if length ($word_buf) > 24; - - my $salt_len = get_random_num (1, 15); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 11600) - { - my $salt_len = get_random_num (0, 16); - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, $salt_len)); - } - elsif ($mode == 12300) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 12400) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 4)); - } - elsif ($mode == 12600 || $mode == 15000) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 64)); - } - elsif ($mode == 12700) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 12800) - { - next if length ($word_buf) > 24; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 20)); - } - elsif ($mode == 12900) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 13000) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 13100) - { - $salt_buf = get_random_kerberos5_tgs_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 13200) - { - $salt_buf = get_random_axcrypt_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 13400) - { - $salt_buf = get_random_keepass_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 13500) - { - $salt_buf = get_pstoken_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 13600) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 13800) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 256)); - } - elsif ($mode == 13900) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 9)); - } - elsif ($mode == 14000) - { - next if length ($word_buf) != 8; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 16)); - } - elsif ($mode == 14100) - { - next if length ($word_buf) != 24; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 16)); - } - elsif ($mode == 14400) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 20)); - } - elsif (($mode == 14700) || ($mode == 14800)) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 40)); - } - elsif ($mode == 14900) - { - next if length ($word_buf) != 10; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 8)); - } - elsif ($mode == 15100) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 8)); - } - elsif ($mode == 15200) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 15300 || $mode == 15900) - { - my $version = 2; - - if ($mode == 15300) - { - $version = 1; - } - - $salt_buf = get_random_dpapimk_salt ($version); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 15400) - { - next if length ($word_buf) != 32; - - $tmp_hash = gen_hash ($mode, $word_buf, ""); - } - elsif ($mode == 15500) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 40)); - } - elsif ($mode == 16000) - { - next if length ($word_buf) > 8; - - $tmp_hash = gen_hash ($mode, $word_buf, ""); - } - elsif ($mode == 16100) - { - $tmp_hash = gen_hash ($mode, $word_buf, undef); - } - elsif ($mode == 16200) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 16500) - { - $salt_buf = get_random_jwt_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 16600) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 16700) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 16800) - { - next if length ($word_buf) < 8; - - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 16900) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 64)); - } - elsif ($mode == 18200) - { - $salt_buf = get_random_kerberos5_as_rep_salt (); - - $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - } - elsif ($mode == 18300) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 18400) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - elsif ($mode == 18600) - { - $tmp_hash = gen_hash ($mode, $word_buf, substr ($salt_buf, 0, 32)); - } - ## STEP 2c: Add your custom salt branch here - else - { - print "ERROR: Unsupported hash type\n"; - - exit (1); - } - - print $tmp_hash, "\n"; - } -} - -sub single -{ - my $mode = shift; - - if (defined $mode) - { - @{$MODES} = ($mode); - } - - for (my $j = 0; $j < scalar @{$MODES}; $j++) - { - my $mode = $MODES->[$j]; - - if (is_in_array ($mode, $COMMON_UNSALTED_MODES) - || $mode == 5300 || $mode == 5400 || $mode == 6600 - || $mode == 8200 || $mode == 8300 || $mode == 13300) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif (is_in_array ($mode, $COMMON_DEFAULT_SALTED_MODES) - || $mode == 121 || $mode == 1411 || $mode == 1711 || $mode == 3711 - || $mode == 8900 || $mode == 10000 || $mode == 10200 || $mode == 10900 - || $mode == 11900 || $mode == 12000 || $mode == 12100 || $mode == 16500) - { - my $salt_len = get_random_num (1, 15); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 11 || $mode == 12) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 21 || $mode == 22) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 2); - } - else - { - rnd ($mode, $i, 2); - } - } - } - elsif ($mode == 111 || $mode == 122 || $mode == 125 || $mode == 131 - || $mode == 132 || $mode == 400 || $mode == 500 || $mode == 1600 - || $mode == 1722 || $mode == 1731 || $mode == 6300 || $mode == 7900 - || $mode == 8100 || $mode == 11100) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 8); - } - else - { - rnd ($mode, $i, 8); - } - } - } - elsif ($mode == 112) - { - for (my $i = 1; $i < 31; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 20); - } - else - { - rnd ($mode, $i, 20); - } - } - } - elsif ($mode == 141 || $mode == 3300 || $mode == 1441 || $mode == 1800 - || $mode == 3200 || $mode == 4800 || $mode == 6400 || $mode == 6500 - || $mode == 6700 || $mode == 7400 || $mode == 8000 || $mode == 9100 - || $mode == 12001 || $mode == 12200 || $mode == 15600) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 1100) - { - my $salt_len = get_random_num (1, 19); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 1500) - { - for (my $i = 1; $i < 9; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 2); - } - else - { - rnd ($mode, $i, 2); - } - } - } - elsif ($mode == 2100) - { - my $salt_len = get_random_num (1, 19); - - for (my $i = 1; $i < 13; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 2400) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif ($mode == 2410) - { - my $salt_len = get_random_num (3, 4); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 2500) - { - my $salt_len = get_random_num (0, 32); - - for (my $i = 8; $i < 16; $i++) - { - if ($len != 0) - { - if ($len < 8) - { - $len += 7; - } - - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 2611) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 3); - } - else - { - rnd ($mode, $i, 3); - } - } - } - elsif ($mode == 2612) - { - my $salt_len = get_random_num (1, 22); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 2711) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 30); - } - else - { - rnd ($mode, $i, 30); - } - } - } - elsif ($mode == 2811) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 5); - } - else - { - rnd ($mode, $i, 5); - } - } - } - elsif ($mode == 3000) - { - for (my $i = 1; $i < 8; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif ($mode == 3100) - { - for (my $i = 1; $i < 31; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 10); - } - else - { - rnd ($mode, $i, 10); - } - } - } - elsif ($mode == 3800 || $mode == 4900) - { - my $salt_len = get_random_num (1, 11); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 4520) - { - my $salt_len = get_random_num (1, 50); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 4521 || $mode == 15700) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 4522) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 12); - } - else - { - rnd ($mode, $i, 12); - } - } - } - elsif ($mode == 5500 || $mode == 5600) - { - my $salt_len; - - for (my $i = 1; $i < 27; $i++) - { - $salt_len = get_random_num (1, 15); - - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 5800) - { - for (my $i = 1; $i < 14; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 6800) - { - my $salt_len = get_random_num (8, 25); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 7000) - { - for (my $i = 1; $i < 19; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 24); - } - else - { - rnd ($mode, $i, 24); - } - } - } - elsif ($mode == 7100) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 64); - } - else - { - rnd ($mode, $i, 64); - } - } - } - elsif ($mode == 7200) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 128); - } - else - { - rnd ($mode, $i, 128); - } - } - } - elsif ($mode == 7300) - { - my $salt_len = get_random_num (32, 255); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 7500) - { - for (my $i = 1; $i < 27; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 7700 || $mode == 7701) - { - my $salt_len = get_random_num (1, 12); - - for (my $i = 1; $i < 9; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 7800 || $mode == 7801) - { - my $salt_len = get_random_num (1, 12); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 8400 || $mode == 11200 || $mode == 14700 || $mode == 14800 || $mode == 16300) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 40); - } - else - { - rnd ($mode, $i, 40); - } - } - } - elsif ($mode == 8500) - { - my $salt_len = get_random_num (1, 8); - - for (my $i = 1; $i < 9; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 8600) - { - for (my $i = 1; $i < 17; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif ($mode == 8700) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 5); - } - else - { - rnd ($mode, $i, 5); - } - } - } - elsif ($mode == 9200 || $mode == 9300) - { - my $salt_len = 14; - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 9400 || $mode == 9500 || $mode == 9600) - { - my $salt_len = 32; - - for (my $i = 1; $i < 20; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 9700 || $mode == 9800) - { - my $salt_len = 32; - - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 10100) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 10300) - { - my $salt_len = get_random_num (4, 15); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 10400 || $mode == 10600) - { - my $salt_len = 32; - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 10500 || $mode == 10700) - { - my $salt_len = 32; - - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 11000) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 56); - } - else - { - rnd ($mode, $i, 56); - } - } - } - elsif ($mode == 11300) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 11400) - { - for (my $i = 1; $i < 24; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 11600) - { - my $salt_len = get_random_num (0, 16); - - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 12300) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 12400) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 4); - } - else - { - rnd ($mode, $i, 4); - } - } - } - elsif ($mode == 12600 || $mode == 15000) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 64); - } - else - { - rnd ($mode, $i, 64); - } - } - } - elsif ($mode == 12700) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 12800) - { - for (my $i = 1; $i < 25; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 20); - } - else - { - rnd ($mode, $i, 20); - } - } - } - elsif ($mode == 12900) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 13000) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 13100) - { - for (my $i = 1; $i < 27; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 13200) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 13400) - { - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 13500) - { - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 13600) - { - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 13800) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 256); - } - else - { - rnd ($mode, $i, 256); - } - } - } - elsif ($mode == 13900) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 9); - } - else - { - rnd ($mode, $i, 9); - } - } - } - elsif ($mode == 14000) - { - rnd ($mode, 8, 16); - } - elsif ($mode == 14100) - { - rnd ($mode, 24, 16); - } - elsif ($mode == 14400) - { - for (my $i = 1; $i < 24; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 20); - } - else - { - rnd ($mode, $i, 20); - } - } - } - elsif ($mode == 14900) - { - rnd ($mode, 10, 8); - } - elsif ($mode == 15100) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 8); - } - else - { - rnd ($mode, $i, 8); - } - } - } - elsif ($mode == 15200) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 15300 || $mode == 15900) - { - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 15400) - { - rnd ($mode, 32, 0); - } - elsif ($mode == 15500) - { - for (my $i = 1; $i < 16; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 40); - } - else - { - rnd ($mode, $i, 40); - } - } - } - elsif ($mode == 16000) - { - for (my $i = 1; $i < 9; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif ($mode == 16100) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 0); - } - else - { - rnd ($mode, $i, 0); - } - } - } - elsif ($mode == 16200) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 16600) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 16700) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 16800) - { - my $salt_len = get_random_num (0, 32); - - for (my $i = 8; $i < 16; $i++) - { - if ($len != 0) - { - if ($len < 8) - { - $len += 7; - } - - rnd ($mode, $len, $salt_len); - } - else - { - rnd ($mode, $i, $salt_len); - } - } - } - elsif ($mode == 16900) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 64); - } - else - { - rnd ($mode, $i, 64); - } - } - } - elsif ($mode == 18200) - { - for (my $i = 1; $i < 27; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 16); - } - else - { - rnd ($mode, $i, 16); - } - } - } - elsif ($mode == 18300) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 18400) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - elsif ($mode == 18600) - { - for (my $i = 1; $i < 32; $i++) - { - if ($len != 0) - { - rnd ($mode, $len, 32); - } - else - { - rnd ($mode, $i, 32); - } - } - } - ## STEP 2c: Add your custom salt branch here - } -} - -exit; - -## STEP 3: Implement hash generation for your hash mode here. -# -# For an example of how to use python, see mode 11700. -# For an example of how to use PHP, see mode 11900. -# -# Don't forget to add the modules you depend on to the -# installation script. -# -## -sub gen_hash -{ - my $mode = shift; - - my $word_buf = shift; - - my $salt_buf = shift; - - my $iter = shift; - - my $additional_param = shift; - - my $additional_param2 = shift; - - my $additional_param3 = shift; - - my $additional_param4 = shift; - - my $additional_param5 = shift; - - my $additional_param6 = shift; - - my $additional_param7 = shift; - - my $additional_param8 = shift; - - my $additional_param9 = shift; - - my $additional_param10 = shift; - - my $additional_param11 = shift; - - ## - ## gen hash - ## - - my $tmp_hash; - - my $hash_buf; - - if ($mode == 0) - { - $hash_buf = md5_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 10) - { - $hash_buf = md5_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11) - { - $hash_buf = md5_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 12) - { - $hash_buf = md5_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 20) - { - $hash_buf = md5_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 21) - { - $hash_buf = md5_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 22) - { - my $itoa64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - my $salt_suffix = "Administration Tools"; - - my $pass = sprintf ("%s:%s:%s", $salt_buf, $salt_suffix, $word_buf); - - $hash_buf = md5 ($pass); - - my $res = ""; - - for (my $pos = 0; $pos < 16; $pos += 2) - { - my $octet1 = ord (substr ($hash_buf, $pos + 0, 1)); - my $octet2 = ord (substr ($hash_buf, $pos + 1, 1)); - - my $num = ($octet1 <<8 & 0xff00) | ($octet2 & 0xff); - - my $idx1 = $num >> 12 & 0x0f; - my $idx2 = $num >> 6 & 0x3f; - my $idx3 = $num & 0x3f; - - $res = $res . substr ($itoa64, $idx1, 1) . substr ($itoa64, $idx2, 1) . substr ($itoa64, $idx3, 1); - } - - my $obfuscate_str = "nrcstn"; - my @obfuscate_pos = (0, 6, 12, 17, 23, 29); - - foreach my $pos (keys @obfuscate_pos) - { - my $idx = $obfuscate_pos[$pos]; - my $before = substr ($res, 0, $idx); - my $char = substr ($obfuscate_str, $pos, 1); - my $after = substr ($res, $idx); - - $res = sprintf ("%s%s%s", $before, $char, $after); - } - - $tmp_hash = sprintf ("%s:%s", $res, $salt_buf); - } - elsif ($mode == 23) - { - $hash_buf = md5_hex ($salt_buf . "\nskyper\n" . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 30) - { - $hash_buf = md5_hex (encode ("UTF-16LE", $word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 40) - { - $hash_buf = md5_hex ($salt_buf . encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 50) - { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&md5, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 60) - { - $hash_buf = hmac_hex ($word_buf, $salt_buf, \&md5, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 100) - { - $hash_buf = sha1_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 101) - { - $hash_buf = sha1 ($word_buf); - - my $base64_buf = encode_base64 ($hash_buf, ""); - - $tmp_hash = sprintf ("{SHA}%s", $base64_buf); - } - elsif ($mode == 110) - { - $hash_buf = sha1_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 111) - { - $hash_buf = sha1 ($word_buf . $salt_buf); - - my $base64_buf = encode_base64 ($hash_buf . $salt_buf, ""); - - $tmp_hash = sprintf ("{SSHA}%s", $base64_buf); - } - elsif ($mode == 112) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha1_hex ($word_buf . $salt_buf_bin); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 120) - { - $hash_buf = sha1_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 121) - { - $hash_buf = sha1_hex (lc ($salt_buf) . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 122) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha1_hex ($salt_buf_bin . $word_buf); - - $tmp_hash = sprintf ("%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 125) - { - my $signature = "01"; - - my $salt_buf_bin = pack ("H*", $salt_buf . $signature); - - $hash_buf = sha1_hex ($salt_buf_bin . $word_buf); - - $tmp_hash = sprintf ("%s%s%s", $salt_buf, $signature, $hash_buf); - } - elsif ($mode == 130) - { - $hash_buf = sha1_hex (encode ("UTF-16LE", $word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 131) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha1_hex (encode ("UTF-16LE", uc ($word_buf)) . $salt_buf_bin); - - $tmp_hash = sprintf ("0x0100%s%s%s", $salt_buf, "0" x 40, $hash_buf); - } - elsif ($mode == 132) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha1_hex (encode ("UTF-16LE", $word_buf) . $salt_buf_bin); - - $tmp_hash = sprintf ("0x0100%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 133) - { - $hash_buf = sha1 (encode ("UTF-16LE", $word_buf)); - - $hash_buf = encode_base64 ($hash_buf, ""); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 140) - { - $hash_buf = sha1_hex ($salt_buf . encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 141) - { - $hash_buf = sha1 ($salt_buf . encode ("UTF-16LE", $word_buf)); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - my $base64_hash_buf = encode_base64 ($hash_buf, ""); - - $base64_hash_buf = substr ($base64_hash_buf, 0, 27); - - $tmp_hash = sprintf ("\$episerver\$*0*%s*%s", $base64_salt_buf, $base64_hash_buf); - } - elsif ($mode == 150) - { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha1, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 160) - { - $hash_buf = hmac_hex ($word_buf, $salt_buf, \&sha1, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 200) - { - my $ppr = Authen::Passphrase::MySQL323->new (passphrase => $word_buf); - - $hash_buf = $ppr->hash_hex; - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 300) - { - $hash_buf = substr (password41 ($word_buf), 1); - - $hash_buf = lc ($hash_buf); # useful for 'not matched' check only - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 400) - { - my $cost = 11; - - if (length ($iter)) - { - $cost = $iter; - } - - my $ppr = Authen::Passphrase::PHPass->new - ( - cost => $cost, - salt => $salt_buf, - passphrase => $word_buf, - ); - - $hash_buf = $ppr->as_rfc2307; - - $tmp_hash = sprintf ("%s", substr ($hash_buf, 7)); - } - elsif ($mode == 500) - { - my $iterations = 1000; - - if (defined ($iter)) - { - if ($iter > 0) - { - $iterations = int ($iter); - } - } - - $hash_buf = md5_crypt ('$1$', $iterations, $word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 600) - { - $hash_buf = lc blake2b_hex ($word_buf); - $tmp_hash = sprintf ("\$BLAKE2\$" . $hash_buf); - } - elsif ($mode == 900) - { - $hash_buf = md4_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1000) - { - $hash_buf = md4_hex (encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1100) - { - $hash_buf = md4_hex (md4 (encode ("UTF-16LE", $word_buf)) . encode ("UTF-16LE", lc ($salt_buf))); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1300) - { - $hash_buf = sha224_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1400) - { - $hash_buf = sha256_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1410) - { - $hash_buf = sha256_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1411) - { - $hash_buf = sha256_hex ($word_buf . $salt_buf); - - my $base64_buf = encode_base64 (pack ("H*", $hash_buf) . $salt_buf, ""); - - $tmp_hash = sprintf ("{SSHA256}%s", $base64_buf); - } - elsif ($mode == 1420) - { - $hash_buf = sha256_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1430) - { - $hash_buf = sha256_hex (encode ("UTF-16LE", $word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1440) - { - $hash_buf = sha256_hex ($salt_buf . encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1441) - { - $hash_buf = sha256 ($salt_buf . encode ("UTF-16LE", $word_buf)); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - my $base64_hash_buf = encode_base64 ($hash_buf, ""); - - $base64_hash_buf = substr ($base64_hash_buf, 0, 43); - - $tmp_hash = sprintf ("\$episerver\$*1*%s*%s", $base64_salt_buf, $base64_hash_buf); - } - elsif ($mode == 1450) - { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha256, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1460) - { - $hash_buf = hmac_hex ($word_buf, $salt_buf, \&sha256, 64); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1500) - { - $hash_buf = crypt ($word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1600) - { - my $iterations = 1000; - - if (defined ($iter)) - { - if ($iter > 0) - { - $iterations = int ($iter); - } - } - - $hash_buf = md5_crypt ('$apr1$', $iterations, $word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1700) - { - $hash_buf = sha512_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 1710 || $mode == 15000) - { - $hash_buf = sha512_hex ($word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1711) - { - $hash_buf = sha512_hex ($word_buf . $salt_buf); - - my $base64_buf = encode_base64 (pack ("H*", $hash_buf) . $salt_buf, ""); - - $tmp_hash = sprintf ("{SSHA512}%s", $base64_buf); - } - elsif ($mode == 1720) - { - $hash_buf = sha512_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1730) - { - $hash_buf = sha512_hex (encode ("UTF-16LE", $word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1740) - { - $hash_buf = sha512_hex ($salt_buf . encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1722) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha512_hex ($salt_buf_bin . $word_buf); - - $tmp_hash = sprintf ("%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 1731) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha512_hex (encode ("UTF-16LE", $word_buf) . $salt_buf_bin); - - $tmp_hash = sprintf ("0x0200%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 1750) - { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha512, 128); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1760) - { - $hash_buf = hmac_hex ($word_buf, $salt_buf, \&sha512, 128); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 1800) - { - my $iterations = 5000; - - if (defined ($iter)) - { - if ($iter > 0) - { - $iterations = int ($iter); - } - } - - $hash_buf = sha512_crypt ($iterations, $word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 2100) - { - my $iterations = 10240; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $salt = encode ("UTF-16LE", lc ($salt_buf)); - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 16, - salt_len => length ($salt), - ); - - $hash_buf = unpack ("H*", $pbkdf2->PBKDF2 ($salt, md4 (md4 (encode ("UTF-16LE", $word_buf)) . $salt))); - - $tmp_hash = sprintf ("\$DCC2\$%i#%s#%s", $iterations, $salt_buf, $hash_buf); - } - elsif ($mode == 2400) - { - my $word_len = length ($word_buf); - - my $pad_len = ceil ($word_len / 16) * 16; - - my $hash_buf = Digest::MD5::md5 ($word_buf . "\0" x ($pad_len - $word_len)); - - $tmp_hash = sprintf ("%s", pseudo_base64 ($hash_buf)); - } - elsif ($mode == 2410) - { - my $word_salt_buf = $word_buf . $salt_buf; - - my $word_salt_len = length ($word_salt_buf); - - my $pad_len = ceil ($word_salt_len / 16) * 16; - - my $hash_buf = Digest::MD5::md5 ($word_buf . $salt_buf . "\0" x ($pad_len - $word_salt_len)); - - $tmp_hash = sprintf ("%s:%s", pseudo_base64 ($hash_buf), $salt_buf); - } - elsif ($mode == 2500) - { - my ($bssid, $stmac, $snonce, $anonce, $eapol, $keyver, $eapol_len, $essid_len); - - if (! defined ($additional_param)) - { - # random stuff - - $bssid = randbytes (6); - $stmac = randbytes (6); - $snonce = randbytes (32); - $anonce = randbytes (32); - - $keyver = get_random_num (1, 4); # 1, 2 or 3 - - # eapol: - # should be "validly" generated, but in theory could be anything for us also: - # $eapol = "\x00" x 121; # works too, but let's generate it correctly - - $eapol = gen_random_wpa_eapol ($keyver, $snonce); - } - else - { - $bssid = $additional_param; - $stmac = $additional_param2; - $snonce = $additional_param3; - $anonce = $additional_param4; - $keyver = $additional_param5; - $eapol = $additional_param6; - } - - $eapol_len = length ($eapol); - - # constants - - my $iterations = 4096; - - # - # START - # - - # generate the Pairwise Master Key (PMK) - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 32, - ); - - my $pmk = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - # Pairwise Transient Key (PTK) transformation - - my $ptk = wpa_prf_512 ($keyver, $pmk, $stmac, $bssid, $snonce, $anonce); - - # generate the Message Integrity Code (MIC) - - my $mic = ""; - - if ($keyver == 1) # WPA1 => MD5 - { - $mic = hmac ($eapol, $ptk, \&md5); - } - elsif ($keyver == 2) # WPA2 => SHA1 - { - $mic = hmac ($eapol, $ptk, \&sha1); - } - elsif ($keyver == 3) # WPA2 => SHA256 + AES-CMAC - { - my $omac1 = Digest::CMAC->new ($ptk, 'Crypt::Rijndael'); - - $omac1->add ($eapol); - - $mic = $omac1->digest; - } - - $mic = substr ($mic, 0, 16); - - # - # format the binary output - # - - my $HCCAPX_VERSION = 4; - - # signature - $hash_buf = "HCPX"; - - # format version - $hash_buf .= pack ("L<", $HCCAPX_VERSION); - - # authenticated - $hash_buf .= pack ("C", 0); - - # essid length - $essid_len = length ($salt_buf); - $hash_buf .= pack ("C", $essid_len); - - # essid (NULL-padded up to the first 32 bytes) - $hash_buf .= $salt_buf; - $hash_buf .= "\x00" x (32 - $essid_len); - - # key version - $hash_buf .= pack ("C", $keyver); - - # key mic - $hash_buf .= $mic; - - # access point MAC - $hash_buf .= $bssid; - - # access point nonce - $hash_buf .= $snonce; - - # client MAC - $hash_buf .= $stmac; - - # client nonce - $hash_buf .= $anonce; - - # eapol length - $hash_buf .= pack ("S<", $eapol_len); - - # eapol - $hash_buf .= $eapol; - $hash_buf .= "\x00" x (256 - $eapol_len); - - # base64 encode the output - $tmp_hash = encode_base64 ($hash_buf, ""); - } - elsif ($mode == 2600) - { - $hash_buf = md5_hex (md5_hex ($word_buf)); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 2611) - { - $hash_buf = md5_hex (md5_hex ($word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 2612) - { - my $salt_buf_hex = unpack ("H*", $salt_buf); - - $hash_buf = md5_hex (md5_hex ($word_buf) . $salt_buf); - - $tmp_hash = sprintf ("\$PHPS\$%s\$%s", $salt_buf_hex, $hash_buf); - } - elsif ($mode == 2711) - { - $hash_buf = md5_hex (md5_hex ($word_buf) . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 2811) - { - $hash_buf = md5_hex (md5_hex ($salt_buf) . md5_hex ($word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3000) - { - my $ppr = Authen::Passphrase::LANManager->new ("passphrase" => $word_buf); - - $hash_buf = $ppr->hash_hex; - - $tmp_hash = sprintf ("%s", substr ($hash_buf, 0, 16)); - } - elsif ($mode == 3100) - { - $hash_buf = oracle_hash ($salt_buf, $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3200) - { - my $cost = "05"; - - if (length ($iter)) - { - $cost = $iter; - } - - $tmp_hash = bcrypt ($word_buf, sprintf ('$2a$%s$%s$', $cost, en_base64 ($salt_buf))); - } - elsif ($mode == 3300) - { - my $iterations = 904; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $variant = "\$"; - - if (defined ($additional_param)) - { - $variant = $additional_param; - } - - my $prefix = sprintf ("\$md5%srounds=%i\$%s", $variant, $iterations, $salt_buf); - - $iterations += 4096; - - $hash_buf = sun_md5 ($word_buf, $prefix, $iterations); - - $tmp_hash = sprintf ("%s\$%s", $prefix, $hash_buf); - } - elsif ($mode == 3500) - { - $hash_buf = md5_hex (md5_hex (md5_hex ($word_buf))); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 3610) - { - $hash_buf = md5_hex (md5_hex ($salt_buf) . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3710) - { - $hash_buf = md5_hex ($salt_buf . md5_hex ($word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3711) - { - $hash_buf = md5_hex ($salt_buf . "-" . md5_hex ($word_buf)); - - $tmp_hash = sprintf ("\$B\$%s\$%s", $salt_buf, $hash_buf); - } - elsif ($mode == 3720) - { - $hash_buf = md5_hex ($word_buf . md5_hex ($salt_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3800) - { - $hash_buf = md5_hex ($salt_buf . $word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 3910) - { - $hash_buf = md5_hex (md5_hex ($word_buf) . md5_hex ($salt_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4010) - { - $hash_buf = md5_hex ($salt_buf . md5_hex ($salt_buf . $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4110) - { - $hash_buf = md5_hex ($salt_buf . md5_hex ($word_buf . $salt_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4210) - { - $hash_buf = md5_hex ($salt_buf . "\x00" . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4300) - { - $hash_buf = md5_hex (uc (md5_hex ($word_buf))); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 4400) - { - $hash_buf = md5_hex (sha1_hex ($word_buf)); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 4500) - { - $hash_buf = sha1_hex (sha1_hex ($word_buf)); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif (($mode == 4520) || ($mode == 4521) || ($mode == 4522)) - { - $hash_buf = sha1_hex ($salt_buf . sha1_hex ($word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4600) - { - $hash_buf = sha1_hex (sha1_hex (sha1_hex ($word_buf))); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 4700) - { - $hash_buf = sha1_hex (md5_hex ($word_buf)); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 4800) - { - my $index = rindex ($salt_buf, ":"); - - my $salt = substr ($salt_buf, 0, $index); - my $salt_bin = pack ("H*", $salt); - my $chap_sign = substr ($salt_buf, $index + 1); - my $chap_sign_bin = pack ("H*", $chap_sign); - - $hash_buf = md5_hex ($chap_sign_bin . $word_buf . $salt_bin); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 4900) - { - $hash_buf = sha1_hex ($salt_buf . $word_buf . $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 5100) - { - my $pos; - - if (! defined ($additional_param)) - { - $pos = 0; - } - else - { - $pos = $additional_param * 8 unless ($additional_param > 2); - } - - $hash_buf = md5_hex ($word_buf); - - $tmp_hash = sprintf ("%s", substr ($hash_buf, $pos, 16)); - } - elsif ($mode == 5300) - { - my @salt_arr = split (":", $salt_buf); - - my $msg_buf = pack ("H*", $salt_arr[0] . $salt_arr[1] . $salt_arr[2] . $salt_arr[3] . $salt_arr[4] . $salt_arr[5]); - my $nr_buf = pack ("H*", $salt_arr[6] . $salt_arr[7]); - - my $hash_buf = hmac ($nr_buf , $word_buf, \&md5, 64); - $hash_buf = hmac_hex ($msg_buf, $hash_buf, \&md5, 64); - - $tmp_hash = sprintf ("%s:%s", $salt_buf, $hash_buf); - } - elsif ($mode == 5400) - { - my @salt_arr = split (":", $salt_buf); - - my $msg_buf = pack ("H*", $salt_arr[0] . $salt_arr[1] . $salt_arr[2] . $salt_arr[3] . $salt_arr[4] . $salt_arr[5]); - my $nr_buf = pack ("H*", $salt_arr[6] . $salt_arr[7]); - - my $hash_buf = hmac ($nr_buf , $word_buf, \&sha1, 64); - $hash_buf = hmac_hex ($msg_buf, $hash_buf, \&sha1, 64); - - $tmp_hash = sprintf ("%s:%s", $salt_buf, $hash_buf); - } - elsif ($mode == 5500) - { - my $index1 = index ($salt_buf, "::"); - my $user = substr ($salt_buf, 0, $index1); - - my $index2 = index ($salt_buf, ":", $index1 + 2); - my $domain = substr ($salt_buf, $index1 + 2, $index2 - $index1 - 2); - - my $len = length (substr ($salt_buf, $index2 + 1)); - - my $c_challenge_hex; - - if ($len > 32) - { - $c_challenge_hex = substr ($salt_buf, $index2 + 1, 48); - $index2 += 32; - } - else - { - $c_challenge_hex = substr ($salt_buf, $index2 + 1, 16); - $c_challenge_hex .= 00 x 32; - } - - my $c_challenge = pack ("H*", substr ($c_challenge_hex, 0, 16)); - my $s_challenge_hex = substr ($salt_buf, $index2 + 17, 16); - my $s_challenge = pack ("H*", $s_challenge_hex); - - my $challenge = substr (md5 ($s_challenge . $c_challenge), 0, 8); - - my $ntresp; - - my $nthash = Authen::Passphrase::NTHash->new (passphrase => $word_buf)->hash . "\x00" x 5; - - $ntresp .= Crypt::ECB::encrypt (setup_des_key (substr ($nthash, 0, 7)), "DES", $challenge, "none"); - $ntresp .= Crypt::ECB::encrypt (setup_des_key (substr ($nthash, 7, 7)), "DES", $challenge, "none"); - $ntresp .= Crypt::ECB::encrypt (setup_des_key (substr ($nthash, 14, 7)), "DES", $challenge, "none"); - - $tmp_hash = sprintf ("%s::%s:%s:%s:%s", $user, $domain, $c_challenge_hex, unpack ("H*", $ntresp), $s_challenge_hex); - } - elsif ($mode == 5600) - { - my $index1 = index ($salt_buf, "::"); - my $user = substr ($salt_buf, 0, $index1); - - my $index2 = index ($salt_buf, ":", $index1 + 2); - my $domain = substr ($salt_buf, $index1 + 2, $index2 - $index1 - 2); - - my $s_challenge_hex = substr ($salt_buf, $index2 + 1, 16); - my $s_challenge = pack ("H*", $s_challenge_hex); - - my $temp_hex = substr ($salt_buf, $index2 + 17); - my $temp = pack ("H*", $temp_hex); - - my $nthash = Authen::Passphrase::NTHash->new (passphrase => $word_buf)->hash; - my $identity = Encode::encode ("UTF-16LE", uc ($user) . $domain); - - $hash_buf = hmac_hex ($s_challenge . $temp, hmac ($identity, $nthash, \&md5, 64), \&md5, 64); - - $tmp_hash = sprintf ("%s::%s:%s:%s:%s", $user, $domain, $s_challenge_hex, $hash_buf, $temp_hex); - } - elsif ($mode == 5700) - { - $hash_buf = sha256 ($word_buf); - - my $base64_buf = encode_base64 ($hash_buf, ""); - - $tmp_hash = ""; - - for (my $i = 0; $i < 43; $i++) - { - $tmp_hash .= $CISCO_BASE64_MAPPING->{substr ($base64_buf, $i, 1)}; - } - } - elsif ($mode == 5800) - { - $hash_buf = androidpin_hash ($word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 6000) - { - $hash_buf = ripemd160_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 6100) - { - $hash_buf = whirlpool_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 6300) - { - my $iterations = 1000; # hard coded by the AIX format - - $hash_buf = md5_crypt ('', $iterations, $word_buf, $salt_buf); - - $tmp_hash = sprintf ("{smd5}%s", $hash_buf); - } - elsif ($mode == 6400) - { - my $iterations = 64; - - if (length ($iter)) - { - $iterations = 1 << int ($iter); - } - - $hash_buf = aix_ssha256_pbkdf2 ($word_buf, $salt_buf, $iterations); - - $tmp_hash = sprintf ("{ssha256}%02i\$%s\$%s", log ($iterations) / log (2), $salt_buf, $hash_buf); - } - elsif ($mode == 6500) - { - my $iterations = 64; - - if (length ($iter)) - { - $iterations = 1 << int ($iter); - } - - $hash_buf = aix_ssha512_pbkdf2 ($word_buf, $salt_buf, $iterations); - - $tmp_hash = sprintf ("{ssha512}%02i\$%s\$%s", log ($iterations) / log (2), $salt_buf, $hash_buf); - } - elsif ($mode == 6600) - { - my $iterations = 1000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $salt_hex = substr ($salt_buf, 0, 16); - my $salt = pack ("H*", $salt_hex); - - my $prefix = substr ($salt_buf, 16, 2016); - - my $iv_hex = substr ($salt_buf, 2032); - my $iv = pack ("H*", $iv_hex); - - my $data = pack ("H*", "10101010101010101010101010101010"); - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 16 - ); - - my $key = $pbkdf2->PBKDF2 ($salt, $word_buf); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 16 - }); - - my $encrypted = unpack ("H*", $cipher->encrypt ($data)); - - $hash_buf = substr ($encrypted, 0, 32); - - $tmp_hash = sprintf ("%i:%s:%s%s%s", $iterations, $salt_hex, $prefix, $iv_hex, $hash_buf); - } - elsif ($mode == 6700) - { - my $iterations = 64; - - if (length ($iter)) - { - $iterations = 1 << int ($iter); - } - - $hash_buf = aix_ssha1_pbkdf2 ($word_buf, $salt_buf, $iterations); - - $tmp_hash = sprintf ("{ssha1}%02i\$%s\$%s", log ($iterations) / log (2), $salt_buf, $hash_buf); - } - elsif ($mode == 6800) - { - my $variant = $additional_param; - - if (! defined ($variant)) - { - $variant = int (rand (2)); - } - - my $iterations = 500; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $iv = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 32 - ); - - my $key = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 32 - }); - - if ($variant == 1) - { - my $encrypt = $cipher->encrypt (substr ($salt_buf, 0, 16)); - - $hash_buf = substr (unpack ("H*", $encrypt), 0, 32); - } - else - { - my $verifier = "lastpass rocks\x02\x02"; - - $hash_buf = unpack ("H*", substr ($cipher->encrypt ($verifier), 0, 16)); - } - - $tmp_hash = sprintf ("%s:%i:%s", $hash_buf, $iterations, $salt_buf); - } - elsif ($mode == 6900) - { - $hash_buf = gost_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 7000) - { - my $FORTIGATE_SIGNATURE = "AK1"; - my $FORTIGATE_MAGIC = pack ("H*", "a388ba2e424cb04a537930c13107cc3fa1329029a9815b70"); - - my $salt_bin = pack ("H*", $salt_buf); - - my $hash = sha1 ($salt_bin . $word_buf . $FORTIGATE_MAGIC); - - $hash = encode_base64 ($salt_bin . $hash, ""); - - $tmp_hash = sprintf ("%s%s", $FORTIGATE_SIGNATURE, $hash); - } - elsif ($mode == 7100) - { - my $iterations = 1024; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512), - iterations => $iterations - ); - - $hash_buf = unpack ("H*", $pbkdf2->PBKDF2 (pack ("H*", $salt_buf), $word_buf)); - - $tmp_hash = sprintf ("\$ml\$%i\$%s\$%0128s", $iterations, $salt_buf, $hash_buf); - } - elsif ($mode == 7200) - { - my $iterations = 1024; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512), - iterations => $iterations - ); - - $hash_buf = unpack ("H*", $pbkdf2->PBKDF2 (pack ("H*", $salt_buf), $word_buf)); - - $tmp_hash = sprintf ("grub.pbkdf2.sha512.%i.%s.%0128s", $iterations, $salt_buf, $hash_buf); - } - elsif ($mode == 7300) - { - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&sha1); - - $tmp_hash = sprintf ("%s:%s", unpack ("H*", $salt_buf), $hash_buf); - } - elsif ($mode == 7400) - { - my $iterations = 5000; - - if (defined ($iter)) - { - if ($iter > 0) - { - $iterations = int ($iter); - } - } - - $hash_buf = sha256_crypt ($iterations, $word_buf, $salt_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 7500) - { - my @salt_arr = split ("\\\$", $salt_buf); - - my $user = $salt_arr[0]; - - my $realm = $salt_arr[1]; - - my $salt = $salt_arr[2]; - - my $hmac_salt = $salt_arr[3]; - my $hmac_salt_bin = pack ("H*", $hmac_salt); - - my $clear_data = $salt_arr[4]; - - my $k = md4 (encode ("UTF-16LE", $word_buf)); - - my $k1 = hmac_md5 ("\x01\x00\x00\x00", $k); - - my $k3 = hmac_md5 ($hmac_salt_bin, $k1); - - if (length ($clear_data) > 1) - { - my $clear_data_bin = pack ("H*", $clear_data); - - $hash_buf = RC4 ($k3, $clear_data_bin); - } - else - { - my $hash = $salt_arr[5]; - - my $hash_bin = pack ("H*", $hash); - - my $clear_data = RC4 ($k3, $hash_bin); - - my $timestamp = substr ($clear_data, 14, 14); - - my $is_numeric = 1; - - if ($timestamp !~ /^[[:digit:]]{14}$/) - { - $is_numeric = 0; - } - - if (! $is_numeric) - { - $hash_buf = "\x00" x 36; - - if ($hash_buf eq $hash_bin) - { - $hash_buf = "\x01" x 36; - } - } - else - { - $hash_buf = $hash_bin; - } - } - - $tmp_hash = sprintf ("\$krb5pa\$23\$%s\$%s\$%s\$%s%s", $user, $realm, $salt, unpack ("H*", $hash_buf), $hmac_salt); - } - elsif ($mode == 7700 || $mode == 7701) - { - $word_buf = uc $word_buf; - $salt_buf = uc $salt_buf; - - my $word_buf_t = sapb_transcode ($word_buf); - my $salt_buf_t = sapb_transcode ($salt_buf); - - my $digest1 = md5 ($word_buf_t . $salt_buf_t); - - my $data = sapb_waldorf ($digest1, $word_buf_t, $salt_buf_t); - - my $digest2 = md5 ($data); - - my ($a, $b, $c, $d) = unpack ("N4", $digest2); - - $a ^= $c; - $b ^= $d; - - if ($mode == 7700) - { - $tmp_hash = sprintf ("%s\$%08X%08X", $salt_buf, $a, $b); - } - else - { - $tmp_hash = sprintf ("%s\$%08X%08X", $salt_buf, $a, 0); - } - } - elsif ($mode == 7800 || $mode == 7801) - { - my $theMagicArray_s = - "\x91\xac\x51\x14\x9f\x67\x54\x43\x24\xe7\x3b\xe0\x28\x74\x7b\xc2" . - "\x86\x33\x13\xeb\x5a\x4f\xcb\x5c\x08\x0a\x73\x37\x0e\x5d\x1c\x2f" . - "\x33\x8f\xe6\xe5\xf8\x9b\xae\xdd\x16\xf2\x4b\x8d\x2c\xe1\xd4\xdc" . - "\xb0\xcb\xdf\x9d\xd4\x70\x6d\x17\xf9\x4d\x42\x3f\x9b\x1b\x11\x94" . - "\x9f\x5b\xc1\x9b\x06\x05\x9d\x03\x9d\x5e\x13\x8a\x1e\x9a\x6a\xe8" . - "\xd9\x7c\x14\x17\x58\xc7\x2a\xf6\xa1\x99\x63\x0a\xd7\xfd\x70\xc3" . - "\xf6\x5e\x74\x13\x03\xc9\x0b\x04\x26\x98\xf7\x26\x8a\x92\x93\x25" . - "\xb0\xa2\x0d\x23\xed\x63\x79\x6d\x13\x32\xfa\x3c\x35\x02\x9a\xa3" . - "\xb3\xdd\x8e\x0a\x24\xbf\x51\xc3\x7c\xcd\x55\x9f\x37\xaf\x94\x4c" . - "\x29\x08\x52\x82\xb2\x3b\x4e\x37\x9f\x17\x07\x91\x11\x3b\xfd\xcd"; - - $salt_buf = uc $salt_buf; - - my $digest = sha1 ($word_buf . $salt_buf); - - my ($a, $b, $c, $d, $e) = unpack ("I*", $digest); - - my $lengthMagicArray = 0x20; - my $offsetMagicArray = 0; - - $lengthMagicArray += (($a >> 0) & 0xff) % 6; - $lengthMagicArray += (($a >> 8) & 0xff) % 6; - $lengthMagicArray += (($a >> 16) & 0xff) % 6; - $lengthMagicArray += (($a >> 24) & 0xff) % 6; - $lengthMagicArray += (($b >> 0) & 0xff) % 6; - $lengthMagicArray += (($b >> 8) & 0xff) % 6; - $lengthMagicArray += (($b >> 16) & 0xff) % 6; - $lengthMagicArray += (($b >> 24) & 0xff) % 6; - $lengthMagicArray += (($c >> 0) & 0xff) % 6; - $lengthMagicArray += (($c >> 8) & 0xff) % 6; - $offsetMagicArray += (($c >> 16) & 0xff) % 8; - $offsetMagicArray += (($c >> 24) & 0xff) % 8; - $offsetMagicArray += (($d >> 0) & 0xff) % 8; - $offsetMagicArray += (($d >> 8) & 0xff) % 8; - $offsetMagicArray += (($d >> 16) & 0xff) % 8; - $offsetMagicArray += (($d >> 24) & 0xff) % 8; - $offsetMagicArray += (($e >> 0) & 0xff) % 8; - $offsetMagicArray += (($e >> 8) & 0xff) % 8; - $offsetMagicArray += (($e >> 16) & 0xff) % 8; - $offsetMagicArray += (($e >> 24) & 0xff) % 8; - - my $hash_buf = sha1_hex ($word_buf . substr ($theMagicArray_s, $offsetMagicArray, $lengthMagicArray) . $salt_buf); - - if ($mode == 7800) - { - $tmp_hash = sprintf ("%s\$%s", $salt_buf, uc $hash_buf); - } - else - { - $tmp_hash = sprintf("%s\$%.20s%020X", $salt_buf, uc $hash_buf, 0); - } - } - elsif ($mode == 7900) - { - my $cost = 14; - - if (length ($iter)) - { - $cost = $iter; - } - - my $phpass_it = 1 << $cost; - - $hash_buf = sha512 ($salt_buf . $word_buf); - - for (my $i = 0; $i < $phpass_it; $i++) - { - $hash_buf = sha512 ($hash_buf . $word_buf); - } - - my $base64_buf = substr (Authen::Passphrase::PHPass::_en_base64 ($hash_buf), 0, 43); - - my $base64_digits = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - my $cost_str = substr ($base64_digits , $cost, 1); - - $tmp_hash = sprintf ('$S$%s%s%s', $cost_str, $salt_buf, $base64_buf); - } - elsif ($mode == 8000) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $word_buf_utf = encode ("UTF-16BE", $word_buf); - - $hash_buf = sha256_hex ($word_buf_utf . "\x00" x (510 - (length ($word_buf) * 2)) . $salt_buf_bin); - - $tmp_hash = sprintf ("0xc007%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 8100) - { - $hash_buf = sha1_hex ($salt_buf . $word_buf . "\x00"); - - $tmp_hash = sprintf ("1%s%s", $salt_buf, $hash_buf); - } - elsif ($mode == 8200) - { - my $iterations = 40000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $salt_hex = substr ($salt_buf, 0, 32); - my $salt = pack ("H*", $salt_hex); - - my $data_hex = substr ($salt_buf, 32); - my $data = pack ("H*", $data_hex); - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512), - iterations => int $iterations - ); - - my $key = $pbkdf2->PBKDF2 ($salt, $word_buf); - - $hash_buf = hmac_hex ($data, substr ($key, 32, 32), \&sha256, 64); - - $tmp_hash = sprintf ("%s:%s:%d:%s", $hash_buf, $salt_hex, $iterations, $data_hex); - } - elsif ($mode == 8300) - { - my ($domain, $salt_hex) = split (":", $salt_buf); - - my $hashalg = Net::DNS::SEC->digtype ("SHA1"); - - my $salt = pack ("H*", $salt_hex); - - my $iterations = 1; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $name = lc ($word_buf . $domain); - - my $hash_buf = Net::DNS::RR::NSEC3::name2hash ($hashalg, $name, $iterations, $salt); - - $tmp_hash = sprintf ("%s:%s:%s:%d", $hash_buf, $domain, $salt_hex, $iterations); - } - elsif ($mode == 8400 || $mode == 13900) - { - $hash_buf = sha1_hex ($salt_buf . sha1_hex ($salt_buf . sha1_hex ($word_buf))); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 8500) - { - $hash_buf = racf_hash (uc $salt_buf, $word_buf); - - $tmp_hash = sprintf ('$racf$*%s*%s', uc $salt_buf, uc $hash_buf); - } - elsif ($mode == 8600) - { - my @saved_key = map { ord $_; } split "", $word_buf; - - my $len = scalar @saved_key; - - my @state = domino_big_md (\@saved_key, $len); - - $tmp_hash = sprintf ('%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x', - $state[ 0], - $state[ 1], - $state[ 2], - $state[ 3], - $state[ 4], - $state[ 5], - $state[ 6], - $state[ 7], - $state[ 8], - $state[ 9], - $state[10], - $state[11], - $state[12], - $state[13], - $state[14], - $state[15], - ); - } - elsif ($mode == 8700) - { - my $domino_char = undef; - - if (defined ($additional_param)) - { - $domino_char = $additional_param; - } - - my @saved_key = map { ord $_; } split "", $word_buf; - - my $len = scalar @saved_key; - - my @state = domino_big_md (\@saved_key, $len); - - my $str = "(" . unpack ("H*", join ("", (map { chr $_; } @state))) . ")"; - - @saved_key = map { ord $_; } split "", $salt_buf . uc $str; - - @state = domino_big_md (\@saved_key, 34); - - $hash_buf = join ("", (map { chr $_; } @state)); - - $tmp_hash = sprintf ('(G%s)', domino_encode ($salt_buf . $hash_buf, $domino_char)); - } - elsif ($mode == 8900) - { - my $N = 1024; - my $r = 1; - my $p = 1; - - if (defined ($additional_param)) - { - $N = $additional_param; - $r = $additional_param2; - $p = $additional_param3; - } - - $hash_buf = scrypt_hash ($word_buf, $salt_buf, $N, $r, $p, 32); - - $tmp_hash = sprintf ('%s', $hash_buf); - } - elsif ($mode == 9100) - { - my $iterations = 5000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $domino_char = undef; - - # domino 5 hash - SEC_pwddigest_V1 - -m 8600 - - my @saved_key = map { ord $_; } split "", $word_buf; - - my $len = scalar @saved_key; - - my @state = domino_big_md (\@saved_key, $len); - - - # domino 6 hash - SEC_pwddigest_V2 - -m 8700 - - my $salt_part = substr ($salt_buf, 0, 5); - - my $str = "(" . unpack ("H*", join ("", (map { chr $_; } @state))) . ")"; - - @saved_key = map { ord $_; } split "", $salt_part . uc $str; - - @state = domino_big_md (\@saved_key, 34); - - $hash_buf = join ("", (map { chr $_; } @state)); - - $tmp_hash = sprintf ('(G%s)', domino_encode ($salt_part . $hash_buf, $domino_char)); - - - # domino 8(.5.x) hash - SEC_pwddigest_V3 - -m 9100 - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 8, - salt_len => 16, - ); - - my $chars = "02"; - - if (defined ($additional_param)) - { - $chars = $additional_param; - } - - my $digest_new = $pbkdf2->PBKDF2 ($salt_buf, $tmp_hash); - - for (my $i = length ($iterations); $i < 10; $i++) - { - $iterations = "0" . $iterations; - } - - $tmp_hash = sprintf ('(H%s)', domino_85x_encode ($salt_buf . $iterations . $chars . $digest_new, $domino_char)); - } - elsif ($mode == 9200) - { - my $iterations = 20000; - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations - ); - - $hash_buf = encode_base64 ($pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - $tmp_hash = ""; - - for (my $i = 0; $i < 43; $i++) - { - $tmp_hash .= $CISCO_BASE64_MAPPING->{substr ($hash_buf, $i, 1)}; - } - - $tmp_hash = sprintf ("\$8\$%s\$%s", $salt_buf, $tmp_hash); - } - elsif ($mode == 9300) - { - my $N = 16384; - my $r = 1; - my $p = 1; - - $hash_buf = scrypt_b64 ($word_buf, $salt_buf, $N, $r, $p, 32); - - $tmp_hash = ""; - - for (my $i = 0; $i < 43; $i++) - { - $tmp_hash .= $CISCO_BASE64_MAPPING->{substr ($hash_buf, $i, 1)}; - } - - $tmp_hash = sprintf ('$9$%s$%s', $salt_buf, $tmp_hash); - } - elsif ($mode == 9400) - { - my $iterations = 50000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $aes_key_size = 128; # or 256 - - if (defined ($additional_param2)) - { - $aes_key_size = $additional_param2; - } - - $salt_buf = pack ("H*", $salt_buf); - - my $tmp = sha1 ($salt_buf . encode ("UTF-16LE", $word_buf)); - - for (my $i = 0; $i < $iterations; $i++) - { - my $num32 = pack ("L", $i); - - $tmp = sha1 ($num32 . $tmp); - } - - my $zero32 = pack ("L", 0x00); - - my $derivation_array1 = pack ("C", 0x36) x 64; - my $derivation_array2 = pack ("C", 0x5C) x 64; - - $tmp = sha1 ($tmp . $zero32); - - my $tmp2 = sha1 ($derivation_array1 ^ $tmp); - my $tmp3 = sha1 ($derivation_array2 ^ $tmp); - - my $key = substr ($tmp2 . $tmp3, 0, $aes_key_size / 8); - - my $m = Crypt::Mode::ECB->new ('AES', 0); - - my $encdata; - - if (defined $additional_param) - { - $encdata = $m->decrypt (pack ("H*", $additional_param), $key); - } - else - { - $encdata = "A" x 16; ## can be anything - } - - my $data1_buf = $encdata; - my $data2_buf = sha1 (substr ($data1_buf, 0, 16)); - - $data1_buf = substr ($data1_buf . ("\x00" x 16), 0, 16); - $data2_buf = substr ($data2_buf . ("\x00" x 16), 0, 32); - - my $encrypted1 = unpack ("H*", $m->encrypt ($data1_buf, $key)); - my $encrypted2 = unpack ("H*", $m->encrypt ($data2_buf, $key)); - - $encrypted1 = substr ($encrypted1, 0, 32); - $encrypted2 = substr ($encrypted2, 0, 40); - - $tmp_hash = sprintf ("\$office\$*%d*%d*%d*%d*%s*%s*%s", 2007, 20, $aes_key_size, 16, unpack ("H*", $salt_buf), $encrypted1, $encrypted2); - } - elsif ($mode == 9500) - { - my $iterations = 100000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - $salt_buf = pack ("H*", $salt_buf); - - my $tmp = sha1 ($salt_buf . encode ("UTF-16LE", $word_buf)); - - for (my $i = 0; $i < $iterations; $i++) - { - my $num32 = pack ("L", $i); - - $tmp = sha1 ($num32 . $tmp); - } - - my $encryptedVerifierHashInputBlockKey = "\xfe\xa7\xd2\x76\x3b\x4b\x9e\x79"; - my $encryptedVerifierHashValueBlockKey = "\xd7\xaa\x0f\x6d\x30\x61\x34\x4e"; - - my $final1 = sha1 ($tmp . $encryptedVerifierHashInputBlockKey); - my $final2 = sha1 ($tmp . $encryptedVerifierHashValueBlockKey); - - my $key1 = substr ($final1, 0, 16); - my $key2 = substr ($final2, 0, 16); - - my $cipher1 = Crypt::CBC->new ({ - key => $key1, - cipher => "Crypt::Rijndael", - iv => $salt_buf, - literal_key => 1, - header => "none", - keysize => 16, - padding => "null", - }); - - my $cipher2 = Crypt::CBC->new ({ - key => $key2, - cipher => "Crypt::Rijndael", - iv => $salt_buf, - literal_key => 1, - header => "none", - keysize => 16, - padding => "null", - }); - - my $encdata; - - if (defined $additional_param) - { - $encdata = $cipher1->decrypt (pack ("H*", $additional_param)); - } - else - { - $encdata = "A" x 16; ## can be anything - } - - my $data1_buf = $encdata; - my $data2_buf = sha1 (substr ($data1_buf, 0, 16)); - - my $encrypted1 = unpack ("H*", $cipher1->encrypt ($data1_buf)); - my $encrypted2 = unpack ("H*", $cipher2->encrypt ($data2_buf)); - - $encrypted2 = substr ($encrypted2, 0, 64); - - $tmp_hash = sprintf ("\$office\$*%d*%d*%d*%d*%s*%s*%s", 2010, 100000, 128, 16, unpack ("H*", $salt_buf), $encrypted1, $encrypted2); - } - elsif ($mode == 9600) - { - my $iterations = 100000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - $salt_buf = pack ("H*", $salt_buf); - - my $tmp = sha512 ($salt_buf . encode ("UTF-16LE", $word_buf)); - - for (my $i = 0; $i < $iterations; $i++) - { - my $num32 = pack ("L", $i); - - $tmp = sha512 ($num32 . $tmp); - } - - my $encryptedVerifierHashInputBlockKey = "\xfe\xa7\xd2\x76\x3b\x4b\x9e\x79"; - my $encryptedVerifierHashValueBlockKey = "\xd7\xaa\x0f\x6d\x30\x61\x34\x4e"; - - my $final1 = sha512 ($tmp . $encryptedVerifierHashInputBlockKey); - my $final2 = sha512 ($tmp . $encryptedVerifierHashValueBlockKey); - - my $key1 = substr ($final1, 0, 32); - my $key2 = substr ($final2, 0, 32); - - my $cipher1 = Crypt::CBC->new ({ - key => $key1, - cipher => "Crypt::Rijndael", - iv => $salt_buf, - literal_key => 1, - header => "none", - keysize => 32, - padding => "null", - }); - - my $cipher2 = Crypt::CBC->new ({ - key => $key2, - cipher => "Crypt::Rijndael", - iv => $salt_buf, - literal_key => 1, - header => "none", - keysize => 32, - padding => "null", - }); - - my $encdata; - - if (defined $additional_param) - { - $encdata = $cipher1->decrypt (pack ("H*", $additional_param)); - } - else - { - $encdata = "A" x 16; ## can be anything - } - - my $data1_buf = $encdata; - my $data2_buf = sha512 (substr ($data1_buf, 0, 16)); - - my $encrypted1 = unpack ("H*", $cipher1->encrypt ($data1_buf)); - my $encrypted2 = unpack ("H*", $cipher2->encrypt ($data2_buf)); - - $encrypted2 = substr ($encrypted2, 0, 64); - - $tmp_hash = sprintf ("\$office\$*%d*%d*%d*%d*%s*%s*%s", 2013, 100000, 256, 16, unpack ("H*", $salt_buf), $encrypted1, $encrypted2); - } - elsif ($mode == 9700) - { - $salt_buf = pack ("H*", $salt_buf); - - my $tmp = md5 (encode ("UTF-16LE", $word_buf)); - - $tmp = substr ($tmp, 0, 5); - - my $data; - - for (my $i = 0; $i < 16; $i++) - { - $data .= $tmp; - $data .= $salt_buf; - } - - $tmp = md5 ($data); - - $tmp = substr ($tmp, 0, 5); - - my $version; - - if (defined $additional_param2) - { - $version = $additional_param2; - } - else - { - $version = (unpack ("L", $tmp) & 1) ? 0 : 1; - } - - my $rc4_key = md5 ($tmp . "\x00\x00\x00\x00"); - - my $m = Crypt::RC4->new (substr ($rc4_key, 0, 16)); - - my $encdata; - - if (defined $additional_param) - { - $encdata = $m->RC4 (pack ("H*", $additional_param)); - } - else - { - $encdata = "A" x 16; ## can be anything - } - - my $data1_buf = $encdata; - my $data2_buf = md5 (substr ($data1_buf, 0, 16)); - - $m = Crypt::RC4->new (substr ($rc4_key, 0, 16)); - - my $encrypted1 = $m->RC4 ($data1_buf); - my $encrypted2 = $m->RC4 ($data2_buf); - - $tmp_hash = sprintf ("\$oldoffice\$%d*%s*%s*%s", $version, unpack ("H*", $salt_buf), unpack ("H*", $encrypted1), unpack ("H*", $encrypted2)); - } - elsif ($mode == 9800) - { - $salt_buf = pack ("H*", $salt_buf); - - my $tmp = sha1 ($salt_buf. encode ("UTF-16LE", $word_buf)); - - my $version; - - if (defined $additional_param2) - { - $version = $additional_param2; - } - else - { - $version = (unpack ("L", $tmp) & 1) ? 3 : 4; - } - - my $rc4_key = sha1 ($tmp . "\x00\x00\x00\x00"); - - if ($version == 3) - { - $rc4_key = substr ($rc4_key, 0, 5) . "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; - } - - my $m = Crypt::RC4->new (substr ($rc4_key, 0, 16)); - - my $encdata; - - if (defined $additional_param) - { - $encdata = $m->RC4 (pack ("H*", $additional_param)); - } - else - { - $encdata = "A" x 16; ## can be anything - } - - my $data1_buf = $encdata; - my $data2_buf = sha1 (substr ($data1_buf, 0, 16)); - - $m = Crypt::RC4->new (substr ($rc4_key, 0, 16)); - - my $encrypted1 = $m->RC4 ($data1_buf); - my $encrypted2 = $m->RC4 ($data2_buf); - - $tmp_hash = sprintf ("\$oldoffice\$%d*%s*%s*%s", $version, unpack ("H*", $salt_buf), unpack ("H*", $encrypted1), unpack ("H*", $encrypted2)); - } - elsif ($mode == 9900) - { - $tmp_hash = sprintf ("%s", md5_hex ($word_buf . "\0" x (100 - length ($word_buf)))); - } - elsif ($mode == 10000) - { - my $iterations = 10000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations - ); - - $hash_buf = encode_base64 ($pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - $tmp_hash = sprintf ("pbkdf2_sha256\$%i\$%s\$%s", $iterations, $salt_buf, $hash_buf); - } - elsif ($mode == 10100) - { - my $seed = pack ("H*", $salt_buf); - - my ($hi, $lo) = siphash ($word_buf, $seed); - - my $hi_s = sprintf ("%08x", $hi); - my $lo_s = sprintf ("%08x", $lo); - - $hi_s =~ s/^(..)(..)(..)(..)$/$4$3$2$1/; - $lo_s =~ s/^(..)(..)(..)(..)$/$4$3$2$1/; - - $tmp_hash = sprintf ("%s%s:2:4:%s", $hi_s, $lo_s, $salt_buf); - } - elsif ($mode == 10200) - { - my $challengeb64 = encode_base64 ($salt_buf, ""); - - my $username; - - if (defined $additional_param) - { - $username = $additional_param; - } - else - { - $username = "user"; - } - - $hash_buf = hmac_hex ($salt_buf, $word_buf, \&md5); - - my $responseb64 = encode_base64 ($username . " " . $hash_buf, ""); - - $tmp_hash = sprintf ('$cram_md5$%s$%s', $challengeb64, $responseb64); - } - elsif ($mode == 10300) - { - my $iterations = 1024; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $hash_buf = $salt_buf; - - for (my $pos = 0; $pos < $iterations; $pos++) - { - $hash_buf = sha1 ($word_buf . $hash_buf); - } - - $hash_buf = encode_base64 ($hash_buf . $salt_buf, ""); - - $tmp_hash = sprintf ("{x-issha, %i}%s", $iterations, $hash_buf); - } - elsif ($mode == 10400) - { - my $id = $salt_buf; - my $u = $additional_param; - my $o = $additional_param2; - my $P = $additional_param3; - - if (defined $u == 0) - { - $u = "0" x 64; - } - - if (defined $o == 0) - { - $o = "0" x 64; - } - - if (defined $P == 0) - { - $P = -1; - } - - my $padding; - - for (my $i = 0; $i < 32; $i++) - { - $padding .= pack ("C", $PDF_PADDING->[$i]); - } - - my $res = pdf_compute_encryption_key ($word_buf, $padding, $id, $u, $o, $P, 1, 2, 0); - - my $m = Crypt::RC4->new (substr ($res, 0, 5)); - - $u = $m->RC4 ($padding); - - $tmp_hash = sprintf ('$pdf$%d*%d*40*%d*%d*16*%s*32*%s*32*%s', 1, 2, $P, 0, $id, unpack ("H*", $u), $o); - } - elsif ($mode == 10500) - { - my $id = $salt_buf; - my $u = $additional_param; - my $o = $additional_param2; - my $P = $additional_param3; - my $V = $additional_param4; - my $R = $additional_param5; - my $enc = $additional_param6; - - if (defined $u == 0) - { - $u = "0" x 64; - } - - my $u_save = $u; - - if (defined $o == 0) - { - $o = "0" x 64; - } - - if (defined $R == 0) - { - $R = get_random_num (3, 5); - } - - if (defined $V == 0) - { - $V = ($R == 3) ? 2 : 4; - } - - if (defined $P == 0) - { - $P = ($R == 3) ? -4 : -1028; - } - - if (defined $enc == 0) - { - $enc = ($R == 3) ? 1 : get_random_num (0, 2); - } - - my $padding; - - for (my $i = 0; $i < 32; $i++) - { - $padding .= pack ("C", $PDF_PADDING->[$i]); - } - - my $res = pdf_compute_encryption_key ($word_buf, $padding, $id, $u, $o, $P, $V, $R, $enc); - - my $digest = md5 ($padding . pack ("H*", $id)); - - my $m = Crypt::RC4->new ($res); - - $u = $m->RC4 ($digest); - - my @ress = split "", $res; - - for (my $x = 1; $x <= 19; $x++) - { - my @xor; - - for (my $i = 0; $i < 16; $i++) - { - $xor[$i] = chr (ord ($ress[$i]) ^ $x); - } - - my $s = join ("", @xor); - - my $m2 = Crypt::RC4->new ($s); - - $u = $m2->RC4 ($u); - } - - $u .= substr (pack ("H*", $u_save), 16, 16); - - $tmp_hash = sprintf ('$pdf$%d*%d*128*%d*%d*16*%s*32*%s*32*%s', $V, $R, $P, $enc, $id, unpack ("H*", $u), $o); - } - elsif ($mode == 10600) - { - my $id = $salt_buf; - my $rest = $additional_param; - - if (defined $id == 0) - { - $id = "0" x 32; - } - - if (defined $rest == 0) - { - $rest = "127*"; - $rest .= "0" x 64; - $rest .= $id; - $rest .= "0" x 158; - $rest .= "*127*00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000"; - } - - my @data = split /\*/, $rest; - - my $u = pack ("H*", $data[1]); - - my $h = sha256 ($word_buf . substr ($u, 32, 8)); - - $data[1] = unpack ("H*", $h . substr ($u, 32)); - - $rest = join ("*", @data); - - $tmp_hash = sprintf ('$pdf$5*5*256*-1028*1*16*%s*%s', $id, $rest); - } - elsif ($mode == 10700) - { - my $id = $salt_buf; - my $rest = $additional_param; - - if (defined $id == 0) - { - $id = "0" x 32; - } - - if (defined $rest == 0) - { - $rest = "127*"; - $rest .= "0" x 64; - $rest .= $id; - $rest .= "0" x 158; - $rest .= "*127*00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000*32*0000000000000000000000000000000000000000000000000000000000000000"; - } - - my @datax = split /\*/, $rest; - - my $u = pack ("H*", $datax[1]); - - my $block = sha256 ($word_buf . substr ($u, 32, 8)); - - my $block_size = 32; - - my $data = 0x00 x 64; - - my $data_len = 1; - - my $data63 = 0; - - for (my $i = 0; $i < 64 || $i < $data63 + 32; $i++) - { - $data = $word_buf . $block; - - $data_len = length ($data); - - for (my $k = 1; $k < 64; $k++) - { - $data .= $word_buf . $block; - } - - my $aes = Crypt::CBC->new ({ - key => substr ($block, 0, 16), - cipher => "Crypt::Rijndael", - iv => substr ($block, 16, 16), - literal_key => 1, - header => "none", - keysize => 16, - padding => "null", - }); - - my $data = $aes->encrypt ($data); - - my $sum = 0; - - for (my $j = 0; $j < 16; $j++) - { - $sum += ord (substr ($data, $j, 1)); - } - - $block_size = 32 + ($sum % 3) * 16; - - if ($block_size == 32) - { - $block = sha256 (substr ($data, 0, $data_len * 64)); - } - elsif ($block_size == 48) - { - $block = sha384 (substr ($data, 0, $data_len * 64)); - } - elsif ($block_size == 64) - { - $block = sha512 (substr ($data, 0, $data_len * 64)); - } - - $data63 = ord (substr ($data, $data_len * 64 - 1, 1)); - } - - $datax[1] = unpack ("H*", substr ($block, 0, 32) . substr ($u, 32)); - - $rest = join ("*", @datax); - - $tmp_hash = sprintf ('$pdf$5*6*256*-1028*1*16*%s*%s', $id, $rest); - } - elsif ($mode == 10800) - { - $hash_buf = sha384_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 10900) - { - my $iterations = 1000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $out_len = 24; - - if (defined $additional_param) - { - $out_len = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => $out_len - ); - - $hash_buf = encode_base64 ($pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - - $tmp_hash = sprintf ("sha256:%i:%s:%s", $iterations, $base64_salt_buf, $hash_buf); - } - elsif ($mode == 16900) - { - my $iterations = 10000; - - my $salt_hex = substr ($salt_buf, 0, 64); - my $salt = pack ("H*", $salt_hex); - - my $ciphertext = randbytes(32); - - if (defined $additional_param) - { - my $ciphertext_hex = $additional_param; - $ciphertext = pack ("H*", $ciphertext_hex); - } - - # actually 80 but the last 16 bytes are the IV which we don't need - my $out_len = 64; - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => $out_len - ); - - my $derived_key = $pbkdf2->PBKDF2 ($salt, $word_buf); - - $hash_buf = hmac_hex ($ciphertext, substr ($derived_key, 32, 32), \&sha256); - - $tmp_hash = sprintf ('$ansible$0*0*%s*%s*%s', unpack ("H*", $salt), unpack ("H*", $ciphertext), $hash_buf); - } - elsif ($mode == 11000) - { - $hash_buf = md5_hex ($salt_buf . $word_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11100) - { - my $user = "postgres"; - - if (defined $additional_param) - { - $user = $additional_param; - } - - $hash_buf = md5_hex (md5_hex ($word_buf . $user) . pack ("H*", $salt_buf)); - - $tmp_hash = sprintf ("\$postgres\$%s*%s*%s", $user, $salt_buf, $hash_buf); - } - elsif ($mode == 11200) - { - my $sha1_pass = sha1 ($word_buf); - my $double_sha1 = sha1 ($sha1_pass); - - my $xor_part1 = $sha1_pass; - my $xor_part2 = sha1 (pack ("H*", $salt_buf) . $double_sha1); - - my $hash_buf = ""; - - for (my $i = 0; $i < 20; $i++) - { - my $first_byte = substr ($xor_part1, $i, 1); - my $second_byte = substr ($xor_part2, $i, 1); - - my $xor_result = $first_byte ^ $second_byte; - - $hash_buf .= unpack ("H*", $xor_result); - } - - $tmp_hash = sprintf ("\$mysqlna\$%s*%s", $salt_buf, $hash_buf); - } - elsif ($mode == 11300) - { - my $ckey_buf = get_random_string (96); - - if (length ($additional_param)) - { - $ckey_buf = $additional_param; - } - - my $public_key_buf = get_random_string (66); - - if (length ($additional_param2)) - { - $public_key_buf = $additional_param2; - } - - my $salt_iter = get_random_num (150000, 250000); - - if (length ($iter)) - { - $salt_iter = int ($iter); - } - - my $hash_buf = sha512 ($word_buf . pack ("H*", $salt_buf)); - - for (my $i = 1; $i < $salt_iter; $i++) - { - $hash_buf = sha512 ($hash_buf); - } - - my $data = get_random_string (32); - - my $aes = Crypt::CBC->new ({ - key => substr ($hash_buf, 0, 32), - cipher => "Crypt::Rijndael", - iv => substr ($hash_buf, 32, 16), - literal_key => 1, - header => "none", - keysize => 32, - padding => "standard", - }); - - my $cry_master_buf = (unpack ("H*", $aes->encrypt ($data))); - - $tmp_hash = sprintf ('$bitcoin$%d$%s$%d$%s$%d$%d$%s$%d$%s', - length ($cry_master_buf), - $cry_master_buf, - length ($salt_buf), - $salt_buf, - $salt_iter, - length ($ckey_buf), - $ckey_buf, - length ($public_key_buf), - $public_key_buf); - } - elsif ($mode == 11400) - { - my ($directive, $URI_server, $URI_client, $user, $realm, $nonce, $nonce_count, $nonce_client, $qop, $method, $URI, $URI_prefix, $URI_resource, $URI_suffix); - - $directive = "MD5"; # only directive currently supported - - if (defined ($additional_param)) - { - $user = $additional_param; - $realm = $additional_param2; - $nonce = $salt_buf; - $nonce_count = $additional_param3; - $nonce_client = $additional_param4; - $qop = $additional_param5; - $method = $additional_param6; - - $URI_prefix = $additional_param7; - $URI_resource = $additional_param8; - $URI_suffix = $additional_param9; - - # not needed information - - $URI_server = $additional_param10; - $URI_client = $additional_param11; - } - else - { - $user = get_random_string (get_random_num (0, 12 + 1)); - - # special limit: (user_len + 1 + realm_len + 1 + word_buf_len) < 56 - my $realm_max_len = 55 - length ($user) - 1 - length ($word_buf) - 1; - - if ($realm_max_len < 1) # should never happen - { - $realm_max_len = 1; - } - - $realm_max_len = min (20, $realm_max_len); - - $realm = get_random_string (get_random_num (0, $realm_max_len + 1)); - - $nonce = $salt_buf; - - if (get_random_num (0, 1 + 1) == 1) - { - $qop = "auth"; - - $nonce_count = get_random_string (get_random_num (0, 10 + 1)); - $nonce_client = get_random_string (get_random_num (0, 12 + 1)); - } - else - { - $qop = ""; - - $nonce_count = ""; - $nonce_client = ""; - } - - $method = get_random_string (get_random_num (0, 24 + 1)); - - $URI_prefix = get_random_string (get_random_num (0, 10 + 1)); - $URI_resource = get_random_string (get_random_num (1, 32 + 1)); - $URI_suffix = get_random_string (get_random_num (0, 32 + 1)); - - # not needed information - - $URI_server = get_random_string (get_random_num (0, 32 + 1)); - $URI_client = $URI_resource; # simplification - } - - # start - - $URI = ""; - - if (length ($URI_prefix) > 0) - { - $URI = $URI_prefix . ":"; - } - - $URI .= $URI_resource; - - if (length ($URI_suffix) > 0) - { - $URI .= ":" . $URI_suffix; - } - - my $HA2 = md5_hex ($method . ":" . $URI); - - my $HA1 = md5_hex ($user . ":" . $realm . ":" . $word_buf); - - my $tmp_buf; - - if (($qop eq "auth") || ($qop eq "auth-int")) - { - $tmp_buf = $nonce . ":" . $nonce_count . ":" . $nonce_client . ":" . $qop; - } - else - { - $tmp_buf = $nonce; - } - - my $hash_buf = md5_hex ($HA1 . ":" . $tmp_buf . ":" . $HA2); - - $tmp_hash = sprintf ("\$sip\$*%s*%s*%s*%s*%s*%s*%s*%s*%s*%s*%s*%s*%s*%s", $URI_server, $URI_resource, $user, $realm, $method, $URI_prefix, $URI_resource, $URI_suffix, $nonce, $nonce_client, $nonce_count, $qop, $directive, $hash_buf); - } - elsif ($mode == 11500) - { - $hash_buf = crc32 ($word_buf); - - $tmp_hash = sprintf ("%08x:00000000", $hash_buf); - } - elsif ($mode == 11600) - { - my ($p, $num_cycle_power, $seven_zip_salt_len, $seven_zip_salt_buf, $salt_len, $data_len, $unpack_size, $data_buf); - - $p = 0; # is fixed - - my $validation_only = 0; - - $validation_only = 1 if (defined ($additional_param)); - - if ($validation_only == 1) - { - $num_cycle_power = int ($iter); - $seven_zip_salt_len = $additional_param; - $seven_zip_salt_buf = $additional_param2; - $salt_len = $additional_param3; - # $salt_buf set in parser - # $hash_buf (resulting crc) - $data_len = $additional_param4; - $unpack_size = $additional_param5; - $data_buf = $additional_param6; - } - else - { - $num_cycle_power = 14; # by default it is 19 - $seven_zip_salt_len = 0; - $seven_zip_salt_buf = ""; - $salt_len = length ($salt_buf); - # $salt_buf set automatically - # $hash_buf (resulting crc) - # $data_len will be set when encrypting - $unpack_size = get_random_num (1, 32 + 1); - $data_buf = get_random_string ($unpack_size); - } - - # - # 2 ^ NumCyclesPower "iterations" of SHA256 (only one final SHA256) - # - - $word_buf = encode ("UTF-16LE", $word_buf); - - my $rounds = 1 << $num_cycle_power; - - my $pass_buf = ""; - - for (my $i = 0; $i < $rounds; $i++) - { - my $num_buf = ""; - - $num_buf .= pack ("V", $i); - $num_buf .= "\x00" x 4; - - # this would be better but only works on 64-bit systems: - # $num_buf = pack ("q", $i); - - $pass_buf .= sprintf ("%s%s", $word_buf, $num_buf); - } - - my $key = sha256 ($pass_buf); - - # the salt_buf is our IV for AES CBC - # pad the salt_buf - - my $salt_buf_len = length ($salt_buf); - my $salt_padding_len = 0; - - if ($salt_buf_len < 16) - { - $salt_padding_len = 16 - $salt_buf_len; - } - - $salt_buf .= "\x00" x $salt_padding_len; - - my $aes = Crypt::CBC->new ({ - cipher => "Crypt::Rijndael", - key => $key, - keysize => 32, - literal_key => 1, - iv => $salt_buf, - header => "none", - }); - - if ($validation_only == 1) - { - # decrypt - - my $decrypted_data = $aes->decrypt ($data_buf); - - $decrypted_data = substr ($decrypted_data, 0, $unpack_size); - - $hash_buf = crc32 ($decrypted_data); - } - else - { - # encrypt - - $hash_buf = crc32 ($data_buf); - - $data_buf = $aes->encrypt ($data_buf); - - $data_len = length ($data_buf); - } - - $tmp_hash = sprintf ("\$7z\$%i\$%i\$%i\$%s\$%i\$%08s\$%u\$%u\$%u\$%s", $p, $num_cycle_power, $seven_zip_salt_len, $seven_zip_salt_buf, $salt_len, unpack ("H*", $salt_buf), $hash_buf, $data_len, $unpack_size, unpack ("H*", $data_buf)); - } - elsif ($mode == 11700) - { - # PyGOST outputs digests in little-endian order, while the kernels - # expect them in big-endian; hence the digest[::-1] mirroring. - # Using sys.stdout.write instead of print to disable \n character. - my $python_code = <<"END_CODE"; - -import binascii -import sys -from pygost import gost34112012256 -digest = gost34112012256.new(b"$word_buf").digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $tmp_hash = `python2 -c '$python_code'`; - } - elsif ($mode == 11750) - { - my $python_code = <<"END_CODE"; - -import binascii -import hmac -import sys -from pygost import gost34112012256 -key = b"$word_buf" -msg = b"$salt_buf" -digest = hmac.new(key, msg, gost34112012256).digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $hash_buf = `python2 -c '$python_code'`; - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11760) - { - my $python_code = <<"END_CODE"; - -import binascii -import hmac -import sys -from pygost import gost34112012256 -key = b"$salt_buf" -msg = b"$word_buf" -digest = hmac.new(key, msg, gost34112012256).digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $hash_buf = `python2 -c '$python_code'`; - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11800) - { - my $python_code = <<"END_CODE"; - -import binascii -import sys -from pygost import gost34112012512 -digest = gost34112012512.new(b"$word_buf").digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $tmp_hash = `python2 -c '$python_code'`; - } - elsif ($mode == 11850) - { - my $python_code = <<"END_CODE"; - -import binascii -import hmac -import sys -from pygost import gost34112012512 -key = b"$word_buf" -msg = b"$salt_buf" -digest = hmac.new(key, msg, gost34112012512).digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $hash_buf = `python2 -c '$python_code'`; - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11860) - { - my $python_code = <<"END_CODE"; - -import binascii -import hmac -import sys -from pygost import gost34112012512 -key = b"$salt_buf" -msg = b"$word_buf" -digest = hmac.new(key, msg, gost34112012512).digest() -sys.stdout.write(binascii.hexlify(digest[::-1])) - -END_CODE - - $hash_buf = `python2 -c '$python_code'`; - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 11900) - { - my $iterations = 1000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $out_len = 32; - - if (defined $additional_param) - { - $out_len = $additional_param; - } - - # - # call PHP here - WTF - # - - # sanitize $word_buf and $salt_buf: - - my $word_buf_base64 = encode_base64 ($word_buf, ""); - my $salt_buf_base64 = encode_base64 ($salt_buf, ""); - - # sanitize lenghs - - $out_len = int ($out_len); - - # output is in hex encoding, otherwise it could be screwed (but shouldn't) - - my $php_code = <<'END_CODE'; - - function pbkdf2 ($algorithm, $password, $salt, $count, $key_length, $raw_output = false) - { - $algorithm = strtolower ($algorithm); - - if (! in_array ($algorithm, hash_algos (), true)) - { - trigger_error ("PBKDF2 ERROR: Invalid hash algorithm.", E_USER_ERROR); - } - - if ($count <= 0 || $key_length <= 0) - { - trigger_error ("PBKDF2 ERROR: Invalid parameters.", E_USER_ERROR); - } - - if (function_exists ("hash_pbkdf2")) - { - if (!$raw_output) - { - $key_length = $key_length * 2; - } - - return hash_pbkdf2 ($algorithm, $password, $salt, $count, $key_length, $raw_output); - } - - $hash_length = strlen (hash ($algorithm, "", true)); - $block_count = ceil ($key_length / $hash_length); - - $output = ""; - - for ($i = 1; $i <= $block_count; $i++) - { - $last = $salt . pack ("N", $i); - - $last = $xorsum = hash_hmac ($algorithm, $last, $password, true); - - for ($j = 1; $j < $count; $j++) - { - $xorsum ^= ($last = hash_hmac ($algorithm, $last, $password, true)); - } - - $output .= $xorsum; - } - - if ($raw_output) - { - return substr ($output, 0, $key_length); - } - else - { - return bin2hex (substr ($output, 0, $key_length)); - } - } - - print pbkdf2 ("md5", base64_decode ("$word_buf_base64"), base64_decode ("$salt_buf_base64"), $iterations, $out_len, False); - -END_CODE - - # replace with these command line arguments - - $php_code =~ s/\$word_buf_base64/$word_buf_base64/; - $php_code =~ s/\$salt_buf_base64/$salt_buf_base64/; - $php_code =~ s/\$iterations/$iterations/; - $php_code =~ s/\$out_len/$out_len/; - - my $php_output = `php -r '$php_code'`; - - $hash_buf = pack ("H*", $php_output); - - $hash_buf = encode_base64 ($hash_buf, ""); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - - $tmp_hash = sprintf ("md5:%i:%s:%s", $iterations, $base64_salt_buf, $hash_buf); - } - elsif ($mode == 12000) - { - my $iterations = 1000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $out_len = 16; - - if (defined $additional_param) - { - $out_len = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'), - iterations => $iterations, - output_len => $out_len - ); - - $hash_buf = encode_base64 ($pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - - $tmp_hash = sprintf ("sha1:%i:%s:%s", $iterations, $base64_salt_buf, $hash_buf); - } - elsif ($mode == 12001) - { - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'), - iterations => 10000, - output_len => 32 - ); - - my $base64_buf = encode_base64 ($salt_buf . $pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - $tmp_hash = sprintf ("{PKCS5S2}%s", $base64_buf); - } - elsif ($mode == 12100) - { - my $iterations = 1000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $out_len = 16; - - if (defined $additional_param) - { - $out_len = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512), - iterations => $iterations, - output_len => $out_len - ); - - $hash_buf = encode_base64 ($pbkdf2->PBKDF2 ($salt_buf, $word_buf), ""); - - my $base64_salt_buf = encode_base64 ($salt_buf, ""); - - $tmp_hash = sprintf ("sha512:%i:%s:%s", $iterations, $base64_salt_buf, $hash_buf); - } - elsif ($mode == 12200) - { - my $iterations = 65536; - - my $default_salt = 0; - - if (defined $additional_param) - { - $default_salt = int ($additional_param); - } - - if ($default_salt == 1) - { - $salt_buf = "0011223344556677"; - } - - $hash_buf = sha512 (pack ("H*", $salt_buf) . $word_buf); - - for (my $i = 0; $i < $iterations; $i++) - { - $hash_buf = sha512 ($hash_buf); - } - - $hash_buf = unpack ("H*", $hash_buf); - $hash_buf = substr ($hash_buf, 0, 16); - - if ($default_salt == 0) - { - $tmp_hash = sprintf ("\$ecryptfs\$0\$1\$%s\$%s", $salt_buf, $hash_buf); - } - else - { - $tmp_hash = sprintf ("\$ecryptfs\$0\$%s", $hash_buf); - } - } - elsif ($mode == 12300) - { - my $iterations = 4096; - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 64 - ); - - my $salt_bin = pack ("H*", $salt_buf); - - my $key = $pbkdf2->PBKDF2 ($salt_bin. "AUTH_PBKDF2_SPEEDY_KEY", $word_buf); - - $hash_buf = sha512_hex ($key . $salt_bin); - - $tmp_hash = sprintf ("%s%s", uc ($hash_buf), uc ($salt_buf)); - } - elsif ($mode == 12400) - { - my $iterations; - - if (length ($iter)) - { - $iterations = int ($iter); - } - else - { - $iterations = get_random_num (1, 5001 + 1); - } - - my $key_value = fold_password ($word_buf); - - my $data = "\x00\x00\x00\x00\x00\x00\x00\x00"; - my $salt_value = base64_to_int24 ($salt_buf); - - $hash_buf = crypt_rounds ($key_value, $iterations, $salt_value, $data); - - $tmp_hash = sprintf ("_%s%s%s", int24_to_base64 ($iterations), $salt_buf, block_to_base64 ($hash_buf)); - } - elsif ($mode == 12600) - { - $hash_buf = sha1_hex ($word_buf); - - $hash_buf = sha256_hex ($salt_buf . uc $hash_buf); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 12700) - { - my $iterations = 10; - - my $data = qq|{ - "guid" : "00000000-0000-0000-0000-000000000000", - "sharedKey" : "00000000-0000-0000-0000-000000000000", - "options" : {"pbkdf2_iterations":10,"fee_policy":0,"html5_notifications":false,"logout_time":600000,"tx_display":0,"always_keep_local_backup":false}|; - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 32 - ); - - my $key = $pbkdf2->PBKDF2 ($salt_buf_bin, $word_buf); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $salt_buf_bin, - literal_key => 1, - header => "none", - keysize => 32 - }); - - my $encrypted = unpack ("H*", $cipher->encrypt ($data)); - - $tmp_hash = sprintf ("\$blockchain\$%s\$%s", length ($salt_buf . $encrypted) / 2, $salt_buf . $encrypted); - } - elsif ($mode == 12800) - { - my $iterations = 100; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $nt = md4_hex (encode ("UTF-16LE", $word_buf)); - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => 32 - ); - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hash = $pbkdf2->PBKDF2 ($salt_buf_bin, uc (encode ("UTF-16LE", $nt))); - - $tmp_hash = sprintf ("v1;PPH1_MD4,%s,%d,%s", $salt_buf, $iterations, unpack ("H*", $hash)); - } - elsif ($mode == 12900) - { - my $iterations = 4096; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $salt2 = $salt_buf . $salt_buf; - - if (defined $additional_param) - { - $salt2 = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => 32 - ); - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hash = $pbkdf2->PBKDF2 ($salt_buf_bin, $word_buf); - - my $salt2_bin = pack ("H*", $salt2); - - my $hash_hmac = hmac_hex ($salt2_bin, $hash, \&sha256, 64); - - $tmp_hash = sprintf ("%s%s%s", $salt2, $hash_hmac, $salt_buf); - } - elsif ($mode == 13000) - { - my $iterations = 15; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $iv = "0" x 32; - - if (defined $additional_param) - { - $iv = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => (1 << $iterations) + 32, - output_len => 32 - ); - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hash = $pbkdf2->PBKDF2 ($salt_buf_bin, $word_buf); - - my $hash_final = substr ($hash, 0, 8) - ^ substr ($hash, 8, 8) - ^ substr ($hash, 16, 8) - ^ substr ($hash, 24, 8); - - $tmp_hash = sprintf ('$rar5$16$%s$%d$%s$8$%s', $salt_buf, $iterations, $iv, unpack ("H*", $hash_final)); - } - elsif ($mode == 13100) - { - my @salt_arr = split ('\$', $salt_buf); - - my $user = $salt_arr[0]; - - my $realm = $salt_arr[1]; - - my $spn = $salt_arr[2]; - - my $k = md4 (encode ("UTF-16LE", $word_buf)); - - my $k1 = hmac_md5 ("\x02\x00\x00\x00", $k); - - my $cleartext_ticket = '6381b03081ada00703050050a00000a11b3019a003020117a1'. - '12041058e0d77776e8b8e03991f2966939222aa2171b154d594b5242544553542e434f4e5'. - '44f534f2e434f4da3133011a003020102a10a30081b067472616e6365a40b3009a0030201'. - '01a1020400a511180f32303136303231353134343735305aa611180f32303136303231353'. - '134343735305aa711180f32303136303231363030343735305aa811180f32303136303232'. - '323134343735305a'; - - my $checksum = ""; - - if (defined $additional_param) - { - $checksum = pack ("H*", $additional_param); - } - else - { - my $nonce = $salt_arr[3]; - - $cleartext_ticket = $nonce . $cleartext_ticket; - - $checksum = hmac_md5 (pack ("H*", $cleartext_ticket), $k1); - } - - my $k3 = hmac_md5 ($checksum, $k1); - - my $edata2 = ""; - - if (defined $additional_param2) - { - $edata2 = $additional_param2; - - my $cipher_decrypt = Crypt::RC4->new ($k3); - - my $ticket_decrypt = unpack ("H*", $cipher_decrypt->RC4 (pack ("H*", $edata2))); - - my $check_correct = ((substr ($ticket_decrypt, 16, 4) eq "6381" && substr ($ticket_decrypt, 22, 2) eq "30") || - (substr ($ticket_decrypt, 16, 4) eq "6382")) && - ((substr ($ticket_decrypt, 32, 6) eq "030500") || - (substr ($ticket_decrypt, 32, 8) eq "050307A0")); - - if ($check_correct == 1) - { - $cleartext_ticket = $ticket_decrypt; - } - else # validation failed - { - # fake/wrong ticket (otherwise if we just decrypt/encrypt we end up with false positives all the time) - $cleartext_ticket = "0" x (length ($cleartext_ticket) + 16); - } - } - - my $cipher = Crypt::RC4->new ($k3); - - $edata2 = $cipher->RC4 (pack ("H*", $cleartext_ticket)); - - $tmp_hash = sprintf ('$krb5tgs$23$*%s$%s$%s*$%s$%s', $user, $realm, $spn, unpack ("H*", $checksum), unpack ("H*", $edata2)); - } - elsif ($mode == 13200) - { - my @salt_arr = split ('\*', $salt_buf); - - my $iteration = $salt_arr[0]; - - my $mysalt = $salt_arr[1]; - - $mysalt = pack ("H*", $mysalt); - - my $iv = "a6a6a6a6a6a6a6a6"; - - my $KEK = sha1 ($word_buf); - - $KEK = substr ($KEK ^ $mysalt, 0, 16); - - my $aes = Crypt::Mode::ECB->new ('AES'); - - my $B; - - my $A; - - my @R = (); - - if (defined $additional_param) - { - $additional_param = pack ("H*", $additional_param); - - $A = substr ($additional_param, 0, 8); - $B = 0x00 x 8; - - $R[1] = substr ($additional_param, 8, 8); - $R[2] = substr ($additional_param, 16, 8); - - for (my $j = $iteration - 1; $j >= 0; $j--) - { - $A = substr ($A, 0, 8) ^ pack ("l", (2 * $j + 2)); - - $B = $R[2]; - - $A = $aes->decrypt ($A . $B . "\x00" x 16, $KEK); - - $R[2] = substr ($A, 8, 16); - - $A = substr ($A, 0, 8) ^ pack ("l", (2 * $j + 1)); - - $B = $R[1]; - - $A = $aes->decrypt ($A . $B . "\x00" x 16, $KEK); - - $R[1] = substr ($A, 8, 16); - } - - # check if valid - if (index ($A, "\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6") != 0) - { - # fake wrong @R and $A values - - @R = ('', "\x00" x 8, "\x00" x 8); - - $A = "\x00" x 16; - } - } - else - { - my $DEK = randbytes (16); - - @R = ('', substr (pack ("H*", $DEK), 0, 8), substr (pack ("H*", $DEK), 8, 16)); - - $A = pack ("H*", $iv); - } - - for (my $j = 0; $j < $iteration; $j++) - { - $B = $aes->encrypt ($A . $R[1], $KEK); - - $A = substr ($B, 0, 8) ^ pack ("q", (2 * $j + 1)); - - $R[1] = substr ($B, 8, 16); - - $B = $aes->encrypt ($A . $R[2], $KEK); - - $A = substr ($B, 0, 8) ^ pack ("q", (2 * $j + 2)); - - $R[2] = substr ($B, 8, 16); - } - - my $wrapped_key = unpack ("H*", $A . substr ($R[1], 0 ,8) . substr ($R[2], 0 ,8)); - - $mysalt = unpack ("H*", $mysalt); - - $tmp_hash = sprintf ('$axcrypt$*1*%s*%s*%s', $iteration, $mysalt, $wrapped_key); - } - elsif ($mode == 13300) - { - my $length = 32; - - if ($additional_param) - { - $length = $additional_param; - } - - $hash_buf = sha1_hex ($word_buf); - - $tmp_hash = sprintf ('$axcrypt_sha1$%s', substr ($hash_buf, 0, $length)); - } - elsif ($mode == 13400) - { - my @salt_arr = split ('\*', $salt_buf); - - my $version = $salt_arr[0]; - - my $iteration = $salt_arr[1]; - - my $algorithm = $salt_arr[2]; - - my $final_random_seed = $salt_arr[3]; - - my $transf_random_seed = $salt_arr[4]; - - my $enc_iv = $salt_arr[5]; - - my $contents_hash; - - # specific to version 1 - my $inline_flag; - my $contents_len; - my $contents; - - # specific to version 2 - my $expected_bytes; - - # specific to keyfile handling - my $inline_keyfile_flag; - my $keyfile_len; - my $keyfile_content; - my $keyfile_attributes = ""; - - $final_random_seed = pack ("H*", $final_random_seed); - - $transf_random_seed = pack ("H*", $transf_random_seed); - - $enc_iv = pack ("H*", $enc_iv); - - my $intermediate_hash = sha256 ($word_buf); - - if ($version == 1) - { - $contents_hash = $salt_arr[6]; - - $contents_hash = pack ("H*", $contents_hash); - - $inline_flag = $salt_arr[7]; - - - $contents_len = $salt_arr[8]; - - - $contents = $salt_arr[9]; - - $contents = pack ("H*", $contents); - - # keyfile handling - if (scalar @salt_arr == 13) - { - $inline_keyfile_flag = $salt_arr[10]; - - $keyfile_len = $salt_arr[11]; - - $keyfile_content = $salt_arr[12]; - - $keyfile_attributes = $keyfile_attributes - . "*" . $inline_keyfile_flag - . "*" . $keyfile_len - . "*" . $keyfile_content; - - $intermediate_hash = $intermediate_hash . pack ("H*", $keyfile_content); - - $intermediate_hash = sha256 ($intermediate_hash); - } - } - elsif ($version == 2) - { - # keyfile handling - if (scalar @salt_arr == 11) - { - $inline_keyfile_flag = $salt_arr[8]; - - $keyfile_len = $salt_arr[9]; - - $keyfile_content = $salt_arr[10]; - - $intermediate_hash = $intermediate_hash . pack ("H*", $keyfile_content); - - $keyfile_attributes = $keyfile_attributes - . "*" . $inline_keyfile_flag - . "*" . $keyfile_len - . "*" . $keyfile_content; - - } - - $intermediate_hash = sha256 ($intermediate_hash); - } - - my $aes = Crypt::Mode::ECB->new ('AES', 1); - - for (my $j = 0; $j < $iteration; $j++) - { - $intermediate_hash = $aes->encrypt ($intermediate_hash, $transf_random_seed); - - $intermediate_hash = substr ($intermediate_hash, 0, 32); - } - - $intermediate_hash = sha256 ($intermediate_hash); - - my $final_key = sha256 ($final_random_seed . $intermediate_hash); - - my $final_algorithm; - - if ($version == 1 && $algorithm == 1) - { - $final_algorithm = "Crypt::Twofish"; - } - else - { - $final_algorithm = "Crypt::Rijndael"; - } - - my $cipher = Crypt::CBC->new ({ - key => $final_key, - cipher => $final_algorithm, - iv => $enc_iv, - literal_key => 1, - header => "none", - keysize => 32 - }); - - if ($version == 1) - { - if (defined $additional_param) - { - # if we try to verify the crack, we need to decrypt the contents instead of only encrypting it: - - $contents = $cipher->decrypt ($contents); - - # and check the output - - my $contents_hash_old = $contents_hash; - - $contents_hash = sha256 ($contents); - - if ($contents_hash_old ne $contents_hash) - { - # fake content - $contents = "\x00" x length ($contents); - } - } - else - { - $contents_hash = sha256 ($contents); - } - - $contents = $cipher->encrypt ($contents); - - $tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%d*%d*%s%s', - $version, - $iteration, - $algorithm, - unpack ("H*", $final_random_seed), - unpack ("H*", $transf_random_seed), - unpack ("H*", $enc_iv), - unpack ("H*", $contents_hash), - $inline_flag, - $contents_len, - unpack ("H*", $contents), - $keyfile_attributes); - } - if ($version == 2) - { - $expected_bytes = $salt_arr[6]; - - $contents_hash = $salt_arr[7]; - $contents_hash = pack ("H*", $contents_hash); - - $expected_bytes = $cipher->decrypt ($contents_hash); - - $tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%s%s', - $version, - $iteration, - $algorithm, - unpack ("H*", $final_random_seed), - unpack ("H*", $transf_random_seed), - unpack ("H*", $enc_iv), - unpack ("H*", $expected_bytes), - unpack ("H*", $contents_hash), - $keyfile_attributes); - } - } - elsif ($mode == 13500) - { - $hash_buf = sha1_hex (pack ("H*", $salt_buf) . encode ("UTF-16LE", $word_buf)); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 13600) - { - my $iterations = 1000; - - my $type = 0; - - if (defined $additional_param) - { - $type = $additional_param; - } - - my $mode = 1 + int rand (3); - - if (defined $additional_param2) - { - $mode = $additional_param2; - } - - my $magic = 0; - - if (defined $additional_param3) - { - $magic = $additional_param3; - } - - if (defined $additional_param4) - { - $salt_buf = $additional_param4; - } - - $salt_buf = substr ($salt_buf, 0, 8 + ($mode * 8)); - - my $compress_length = 0; - - if (defined $additional_param5) - { - $compress_length = $additional_param5; - } - - my $data = ""; - - if (defined $additional_param6) - { - $data = $additional_param6; - } - - my $key_len = (8 * ($mode & 3) + 8) * 2; - - my $out_len = $key_len + 2; - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'); - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => $hasher, - iterations => $iterations, - output_len => $out_len - ); - - my $key = $pbkdf2->PBKDF2_hex ($salt_buf_bin, $word_buf); - - my $verify_bytes = substr ($key, -4); $verify_bytes =~ s/^0+//; #lol - - $key = substr ($key, $key_len, $key_len); - - my $key_bin = pack ("H*", $key); - - my $auth = hmac_hex ($data, $key_bin, \&sha1, 64); - - $tmp_hash = sprintf ('$zip2$*%u*%u*%u*%s*%s*%u*%s*%s*$/zip2$', $type, $mode, $magic, $salt_buf, $verify_bytes, $compress_length, $data, substr ($auth, 0, 20)); - } - elsif ($mode == 13800) - { - my $word_buf_utf16le = encode ("UTF-16LE", $word_buf); - - my $salt_buf_bin = pack ("H*", $salt_buf); - - $hash_buf = sha256_hex ($word_buf_utf16le . $salt_buf_bin); - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 14000) - { - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $cipher = new Crypt::DES $word_buf; - - my $hash_buf = $cipher->encrypt ($salt_buf_bin); - - $tmp_hash = sprintf ("%s:%s", unpack ("H*", $hash_buf), $salt_buf); - } - elsif ($mode == 14100) - { - my $word_buf1 = substr ($word_buf, 0, 8); - my $word_buf2 = substr ($word_buf, 8, 8); - my $word_buf3 = substr ($word_buf, 16, 8); - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $cipher1 = new Crypt::DES $word_buf1; - - my $hash_buf1 = $cipher1->encrypt ($salt_buf_bin); - - my $cipher2 = new Crypt::DES $word_buf2; - - my $hash_buf2 = $cipher2->decrypt ($hash_buf1); - - my $cipher3 = new Crypt::DES $word_buf3; - - my $hash_buf3 = $cipher3->encrypt ($hash_buf2); - - $tmp_hash = sprintf ("%s:%s", unpack ("H*", $hash_buf3), $salt_buf); - } - elsif ($mode == 14400) - { - my $begin = "--" . $salt_buf . "--"; - my $end = "--" . $word_buf . "----"; - - my $hash_buf = sha1_hex ($begin . $end); - - for (my $round = 1; $round < 10; $round++) - { - $hash_buf = sha1_hex ($begin . $hash_buf . $end); - } - - $tmp_hash = sprintf ("%s:%s", $hash_buf, $salt_buf); - } - elsif ($mode == 14700) - { - my $iterations = 10000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'), - iterations => $iterations, - output_len => 32 - ); - - $salt_buf = pack ("H*", $salt_buf); - - my $key = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $ITUNES_BACKUP_KEY = 12008468691120727718; - - my $WPKY = "\x00" x 40; - - if (defined $additional_param) - { - my ($A, $R) = itunes_aes_unwrap ($key, $additional_param); - - if ($A == $ITUNES_BACKUP_KEY) - { - $WPKY = itunes_aes_wrap ($key, $A, $R); - } - } - else - { - my $max_number = 18446744073709551615; # 0xffffffffffffffff - - my @R; - - for (my $i = 0; $i < 4; $i++) - { - $R[$i] = get_random_num (0, $max_number); - } - - $WPKY = itunes_aes_wrap ($key, $ITUNES_BACKUP_KEY, \@R); - } - - $tmp_hash = sprintf ("\$itunes_backup\$*9*%s*%i*%s**", unpack ("H*", $WPKY), $iterations, unpack ("H*", $salt_buf)); - } - elsif ($mode == 14800) - { - my $iterations = 10000; - - if (length ($iter)) - { - $iterations = int ($iter); - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'), - iterations => $iterations, - output_len => 32 - ); - - $salt_buf = pack ("H*", $salt_buf); - - my $ITUNES_BACKUP_KEY = 12008468691120727718; - - my $DPIC; - my $DPSL; - - if (defined $additional_param) - { - $DPIC = $additional_param2; - $DPSL = $additional_param3; - } - else - { - #$DPIC = 10000000; it's too much for the tests - $DPIC = 1000; - $DPSL = randbytes (20); - } - - my $WPKY = "\x00" x 40; - - my $pbkdf2x = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2'), - iterations => $DPIC, - output_len => 32 - ); - - my $key_dpsl = $pbkdf2x->PBKDF2 ($DPSL, $word_buf); - - my $key = $pbkdf2->PBKDF2 ($salt_buf, $key_dpsl); - - if (defined $additional_param) - { - my ($A, $R) = itunes_aes_unwrap ($key, $additional_param); - - if ($A == $ITUNES_BACKUP_KEY) - { - $WPKY = itunes_aes_wrap ($key, $A, $R); - } - } - else - { - my $max_number = 18446744073709551615; # 0xffffffffffffffff - - my @R; - - for (my $i = 0; $i < 4; $i++) - { - $R[$i] = get_random_num (0, $max_number); - } - - $WPKY = itunes_aes_wrap ($key, $ITUNES_BACKUP_KEY, \@R); - } - - $tmp_hash = sprintf ("\$itunes_backup\$*10*%s*%i*%s*%i*%s", unpack ("H*", $WPKY), $iterations, unpack ("H*", $salt_buf), $DPIC, unpack ("H*", $DPSL)); - } - elsif ($mode == 14900) - { - my $salt_bin = pack ("H*", $salt_buf); - - my $skip32 = Crypt::Skip32->new ($word_buf); - - my $hash = $skip32->encrypt ($salt_bin); - - $tmp_hash = sprintf ("%08x:%s", unpack ("N*", $hash), $salt_buf); - } - elsif ($mode == 15100) - { - my $iterations = 20000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $pbkdf1_salt_buf = sprintf ('%s$sha1$%u', $salt_buf, $iterations); - - my $tmp = hmac ($pbkdf1_salt_buf, $word_buf, \&sha1, 64); - - for (my $r = 1; $r < $iterations; $r++) - { - $tmp = hmac ($tmp, $word_buf, \&sha1, 64); - } - - my $hash_buf = ""; - - $hash_buf .= to64 ((int (ord (substr ($tmp, 0, 1))) << 16) | (int (ord (substr ($tmp, 1, 1))) << 8) | (int (ord (substr ($tmp, 2, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 3, 1))) << 16) | (int (ord (substr ($tmp, 4, 1))) << 8) | (int (ord (substr ($tmp, 5, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 6, 1))) << 16) | (int (ord (substr ($tmp, 7, 1))) << 8) | (int (ord (substr ($tmp, 8, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 9, 1))) << 16) | (int (ord (substr ($tmp, 10, 1))) << 8) | (int (ord (substr ($tmp, 11, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 12, 1))) << 16) | (int (ord (substr ($tmp, 13, 1))) << 8) | (int (ord (substr ($tmp, 14, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 15, 1))) << 16) | (int (ord (substr ($tmp, 16, 1))) << 8) | (int (ord (substr ($tmp, 17, 1)))), 4); - $hash_buf .= to64 ((int (ord (substr ($tmp, 18, 1))) << 16) | (int (ord (substr ($tmp, 19, 1))) << 8) | 0 , 4); - - ## super hackish, but we have no other choice, as this byte is kind of a random byte added to the digest when the hash was created - - if (defined $additional_param) - { - $hash_buf = substr ($hash_buf, 0, 24) . substr ($additional_param, 24, 4); - } - - $tmp_hash = sprintf ("\$sha1\$%d\$%s\$%s", $iterations, $salt_buf, $hash_buf); - } - elsif ($mode == 15200) - { - my $iterations = 5000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $data = qq|{ - "guid" : "00000000-0000-0000-0000-000000000000", - "sharedKey" : "00000000-0000-0000-0000-000000000000", - "options" : {"pbkdf2_iterations":$iterations,"fee_policy":0,"html5_notifications":false,"logout_time":600000,"tx_display":0,"always_keep_local_backup":false}|; - - my $salt_buf_bin = pack ("H*", $salt_buf); - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 32 - ); - - my $key = $pbkdf2->PBKDF2 ($salt_buf_bin, $word_buf); - - my $cipher = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $salt_buf_bin, - literal_key => 1, - header => "none", - keysize => 32 - }); - - my $encrypted = unpack ("H*", $cipher->encrypt ($data)); - - $tmp_hash = sprintf ("\$blockchain\$v2\$%d\$%s\$%s", $iterations, length ($salt_buf . $encrypted) / 2, $salt_buf . $encrypted); - } - elsif ($mode == 15300 || $mode == 15900) - { - my @salt_arr = split ('\*', $salt_buf); - - my $version = $salt_arr[0]; - - my $context = $salt_arr[1]; - - my $SID = $salt_arr[2]; - - my $cipher_algorithm = $salt_arr[3]; - - my $hash_algorithm = $salt_arr[4]; - - my $iterations = $salt_arr[5]; - - my $salt = pack ("H*", $salt_arr[6]); - - my $cipher_len = $salt_arr[7]; - - my $cipher; - - # intermediate values - - my $user_hash; - my $user_derivationKey; - my $encKey; - my $expected_hmac; - my $cleartext; - - if ($context == 1) - { - $user_hash = sha1 (encode ("UTF-16LE", $word_buf)); - } - elsif ($context == 2) - { - $user_hash = md4 (encode ("UTF-16LE", $word_buf)); - } - - $user_derivationKey = hmac_sha1 (encode ("UTF-16LE", $SID . "\x00"), $user_hash); - - my $hmacSalt = randbytes (16); - my $last_key = randbytes (64); - - if ($version == 1) - { - $encKey = hmac_sha1 ($hmacSalt, $user_derivationKey); - $expected_hmac = hmac_sha1 ($last_key, $encKey); - - # need padding because keyLen is 24 and hashLen 20 - $expected_hmac = $expected_hmac . randbytes (4); - } - elsif ($version == 2) - { - $encKey = hmac_sha512 ($hmacSalt, $user_derivationKey); - $expected_hmac = hmac_sha512 ($last_key, $encKey); - } - - $cleartext = $hmacSalt . $expected_hmac . $last_key; - - my $derived_key; - my $key; - my $iv; - - my $pbkdf2; - - if ($version == 1) - { - $derived_key = dpapi_pbkdf2 ($user_derivationKey, $salt, $iterations, 32, \&hmac_sha1); - } - elsif ($version == 2) - { - $derived_key = dpapi_pbkdf2 ($user_derivationKey, $salt, $iterations, 48, \&hmac_sha512); - } - - if (defined $additional_param) - { - $cipher = pack ("H*", $additional_param); - my $computed_hmac = ""; - - if ($version == 1) - { - $key = substr ($derived_key, 0, 24); - $iv = substr ($derived_key, 24, 8); - - my $p1 = Crypt::ECB->new ({ - key => substr ($key, 0, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - my $p2 = Crypt::ECB->new ({ - key => substr ($key, 8, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - my $p3 = Crypt::ECB->new ({ - key => substr ($key, 16, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - # let's compute a 3DES-EDE-CBC decryption - - my $out1; - my $out2; - my $out3; - my $expected_cleartext = ""; - - # size of cipherlen is 104 bytes - for (my $k = 0; $k < 13; $k++) - { - $out1 = $p3->decrypt (substr ($cipher, $k * 8, 8)); - $out2 = $p2->encrypt ($out1); - $out3 = $p1->decrypt ($out2); - - $expected_cleartext .= substr ($out3, 0, 8) ^ $iv; - - $iv = substr ($cipher, $k * 8, 8); - } - - $last_key = substr ($expected_cleartext, length ($expected_cleartext) - 64, 64); - $hmacSalt = substr ($expected_cleartext, 0, 16); - $expected_hmac = substr ($expected_cleartext, 16, 20); - - $encKey = hmac_sha1 ($hmacSalt, $user_derivationKey); - $computed_hmac = hmac_sha1 ($last_key, $encKey); - - $cleartext = $expected_cleartext; - - if (unpack ("H*", $expected_hmac) ne unpack ("H*", $computed_hmac)) - { - $cleartext = "0" x 104; - } - } - elsif ($version == 2) - { - $key = substr ($derived_key, 0, 32); - $iv = substr ($derived_key, 32, 16); - - my $aes = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 32, - padding => "null", - }); - - my $expected_cleartext = $aes->decrypt ($cipher); - - $last_key = substr ($expected_cleartext, length ($expected_cleartext) - 64, 64); - $hmacSalt = substr ($expected_cleartext, 0, 16); - $expected_hmac = substr ($expected_cleartext, 16, 64); - - $encKey = hmac_sha512 ($hmacSalt, $user_derivationKey); - $computed_hmac = hmac_sha512 ($last_key, $encKey); - - $cleartext = $expected_cleartext; - - if (unpack ("H*", $expected_hmac) ne unpack ("H*", $computed_hmac)) - { - $cleartext = "0" x 144; - } - } - } - - if ($version == 1) - { - $key = substr ($derived_key, 0, 24); - $iv = substr ($derived_key, 24, 8); - - my $p1 = Crypt::ECB->new ({ - key => substr ($key, 0, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - my $p2 = Crypt::ECB->new ({ - key => substr ($key, 8, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - my $p3 = Crypt::ECB->new ({ - key => substr ($key, 16, 8), - cipher => "DES", - literal_key => 1, - header => "none", - keysize => 8, - padding => "null", - }); - - # let's compute a 3DES-EDE-CBC encryption - - # compute first block - my $out1 = $p1->encrypt (substr ($cleartext, 0, 8) ^ $iv); - my $out2 = $p2->decrypt ($out1); - my $out3 = $p3->encrypt ($out2); - - $cipher = substr ($out3, 0, 8); - - # size of cipherlen is 104 bytes - for (my $k = 1; $k < 13; $k++) - { - $iv = $out3; - - $out1 = $p1->encrypt (substr ($cleartext, $k * 8, 8) ^ $iv); - $out2 = $p2->decrypt ($out1); - $out3 = $p3->encrypt ($out2); - - $cipher .= substr ($out3, 0, 8); - } - } - else - { - $key = substr ($derived_key, 0, 32); - $iv = substr ($derived_key, 32, 16); - - my $aes = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 32, - padding => "null", - }); - - $cipher = $aes->encrypt ($cleartext); - } - - $tmp_hash = sprintf ('$DPAPImk$%d*%d*%s*%s*%s*%d*%s*%d*%s', - $version, - $context, - $SID, - $cipher_algorithm, - $hash_algorithm, - $iterations, - unpack ("H*", $salt), - $cipher_len, - unpack ("H*", $cipher)); - } - elsif ($mode == 15400) - { - my $counter; - my $offset; - my $iv; - - if (defined $additional_param) - { - $counter = $additional_param; - $offset = $additional_param2; - $iv = $additional_param3; - } - else - { - $counter = "0400000000000003"; - $offset = int (rand (63)); - $iv = "0200000000000001"; - } - - my $plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz0a2b4c6d8e"; - my $eight_byte_iv = pack ("H*", $iv); - my $eight_byte_counter = pack ("H*", $counter); - my $pad_len = 32 - length ($word_buf); - my $key = $word_buf . "\0" x $pad_len; - - my $cipher = Crypt::OpenSSH::ChachaPoly->new ($key); - - $cipher->ivsetup ($eight_byte_iv, $eight_byte_counter); - - my $enc = $cipher->encrypt ($plaintext); - - my $enc_offset = substr ($enc, $offset, 8); - - $hash_buf = $enc_offset; - - $tmp_hash = sprintf ("\$chacha20\$\*%s\*%d\*%s\*%s\*%s", $counter, $offset, $iv, unpack ("H*", substr ($plaintext, $offset, 8)), unpack ("H*", $enc_offset)); - } - elsif ($mode == 15500) - { - my $iv = pack ("H*", $salt_buf); - - if (length $additional_param) - { - $iv = pack ("H*", $additional_param); - } - - my $enc_key = randbytes (get_random_num (1, 1500)); - - if (length $additional_param2) - { - $enc_key = pack ("H*", $additional_param2); - } - - my $alias = "test"; - - if (length $additional_param3) - { - $alias = $additional_param3; - } - - my $word_buf_utf16be = encode ("UTF-16BE", $word_buf); - - my $hash_buf = sha1 ($word_buf_utf16be . $iv); - - my $DER1 = substr ($hash_buf, 0, 1); - my $DER2 = substr ($hash_buf, 6, 14); - - my @enc_key_data = split "", $enc_key; - - my $enc_key_data_length = scalar @enc_key_data; - - my @key_data = (); - - for (my $i = 0; $i < scalar $enc_key_data_length; $i += 20) - { - my @hash_buf_data = split "", $hash_buf; - - for (my $j = 0; $j < 20; $j++) - { - last if (($i + $j) >= $enc_key_data_length); - - $key_data[$i + $j] = $enc_key_data[$i + $j] ^ $hash_buf_data[$j]; - } - - $hash_buf = sha1 ($word_buf_utf16be . $hash_buf); - } - - my $key = join "", @key_data; - - $hash_buf = sha1 ($word_buf_utf16be . $key); - - $tmp_hash = sprintf ("\$jksprivk\$*%s*%s*%s*%s*%s*%s", uc unpack ("H*", $hash_buf), uc unpack ("H*", $iv), uc unpack ("H*", $enc_key), uc unpack ("H*", $DER1), uc unpack ("H*", $DER2), $alias); - } - elsif ($mode == 15600) - { - my $iterations; - my $ciphertext; - - if (defined $additional_param) - { - $iterations = $iter; - $ciphertext = $additional_param; - } - else - { - $iterations = 1024; # 262144 originally - $ciphertext = randbytes (32); - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - out_len => 32 - ); - - my $derived_key = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $derived_key_cropped = substr ($derived_key, 16, 16); - - $hash_buf = keccak_256_hex ($derived_key_cropped . $ciphertext); - - $tmp_hash = sprintf ("\$ethereum\$p*%i*%s*%s*%s", $iterations, unpack ("H*", $salt_buf), unpack ("H*", $ciphertext), $hash_buf); - } - elsif ($mode == 15700) - { - my $scrypt_N; - my $scrypt_r; - my $scrypt_p; - - my $ciphertext; - - if (defined $additional_param) - { - $scrypt_N = $additional_param; - $scrypt_r = $additional_param2; - $scrypt_p = $additional_param3; - $ciphertext = $additional_param4; - } - else - { - $scrypt_N = 1024; # 262144 originally - $scrypt_r = 1; # 8 originally - $scrypt_p = 1; - $ciphertext = randbytes (32); - } - - my $derived_key = scrypt_raw ($word_buf, $salt_buf, $scrypt_N, $scrypt_r, $scrypt_p, 32); - - my $derived_key_cropped = substr ($derived_key, 16, 16); - - $hash_buf = keccak_256_hex ($derived_key_cropped . $ciphertext); - - $tmp_hash = sprintf ("\$ethereum\$s*%i*%i*%i*%s*%s*%s", $scrypt_N, $scrypt_r, $scrypt_p, unpack ("H*", $salt_buf), unpack ("H*", $ciphertext), $hash_buf); - } - elsif ($mode == 16000) - { - my $converter = Text::Iconv->new ("utf-8", "shift-jis"); - - $word_buf = $converter->convert ($word_buf); - - $salt_buf = substr ($word_buf . '..', 1, 2); - - $salt_buf =~ s/[^\.-z]/\./go; - - $salt_buf =~ tr/:;<=>?@[\\]^_`/A-Ga-f/; - - $hash_buf = crypt ($word_buf, $salt_buf); - - $hash_buf = substr ($hash_buf, -10); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 16100) - { - my $session_id; - my $encrypted_data; - my $sequence; - - if (defined $additional_param) - { - $session_id = pack ("H*", $additional_param); - } - else - { - $session_id = pack ("H*", randbytes (8)); - } - - if (defined $additional_param2) - { - $encrypted_data = pack ("H*", $additional_param2); - } - - if (defined $additional_param3) - { - $sequence = pack ("H*", $additional_param3); - } - else - { - $sequence = pack ("H*", "c006"); - } - - my $key = md5 ($session_id . $word_buf . $sequence); - - if (defined $encrypted_data) - { - ## verify case - - my $encrypted_data_len = length $encrypted_data; - - my $plain_data = substr ($encrypted_data, 0, 6) ^ substr ($key, 0, 6); - - my ($status, $flags, $server_msg_len, $data_len) = unpack ("CCnn", $plain_data); - - if ((($status >= 0x01 && $status <= 0x07) || $status == 0x21) - && ($flags == 0x01 || $flags == 0x00) - && (6 + $server_msg_len + $data_len == $encrypted_data_len)) - { - ## ok - } - else - { - $encrypted_data = ""; # some invalid data - } - } - else - { - my $plain_data = "\x01\x00\x00\x00\x00\x00"; - - my $plain_data_len = length $plain_data; - - my $shortest = ($plain_data_len > 16) ? 16 : $plain_data_len; - - $encrypted_data = substr ($plain_data, 0, $shortest) ^ substr ($key, 0, $shortest); - } - - $tmp_hash = sprintf ('$tacacs-plus$0$%s$%s$%s', unpack ("H*", $session_id), unpack ("H*", $encrypted_data), unpack ("H*", $sequence)); - } - elsif ($mode == 16200) - { - my $salt_bin = pack ("H*", $salt_buf); - - my $iterations = 20000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $Z_PK = 1; - - if (defined $additional_param) - { - $Z_PK = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => 16, - ); - - my $KEK = $pbkdf2->PBKDF2 ($salt_bin, $word_buf); - - my $aes = Crypt::Mode::ECB->new ('AES', 0); - - my $blob_bin; - - my $A; - my $B; - my $P1; - my $P2; - - if (defined $additional_param2) - { - $blob_bin = pack ("H*", $additional_param2); - - $A = substr ($blob_bin, 0, 8); - $P1 = substr ($blob_bin, 8, 8); - $P2 = substr ($blob_bin, 16, 8); - - for (my $j = 5; $j >= 0; $j--) - { - # N = 2 - - $B = $A; - $B ^= pack ("Q>", (2 * $j + 2)); - $B .= $P2; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P2 = substr ($B, 8, 8); - - # N = 1 - - $B = $A; - $B ^= pack ("Q>", (2 * $j + 1)); - $B .= $P1; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P1 = substr ($B, 8, 8); - } - - if ($A eq "\xa6" x 8) - { - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 2)); - $P2 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2; - } - else - { - $blob_bin = "\xff" x 24; - } - } - else - { - $A = "\xa6" x 8; - $P1 = "\xff" x 8; - $P2 = "\xff" x 8; - - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 2)); - $P2 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2; - } - - $tmp_hash = sprintf ('$ASN$*%d*%d*%s*%s', $Z_PK, $iterations, unpack ("H*", $salt_bin), unpack ("H*", $blob_bin)); - } - elsif ($mode == 16300) - { - my $ethaddr = $salt_buf; - - my $iv = ""; - my $seed = ""; - my $encseed = ""; - - # setup pbkdf2 params: - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => 2000, - output_len => 16 - ); - - my $key = $pbkdf2->PBKDF2 ($word_buf, $word_buf); - - if (defined $additional_param) - { - $iv = substr ($additional_param, 0, 16); - $encseed = substr ($additional_param, 16); - - # AES-128-CBC decrypt: - - my $aes_cbc = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 16 - }); - - $seed = $aes_cbc->decrypt ($encseed); - } - else - { - $iv = randbytes (16); - $seed = randbytes (592); - - # AES-128-CBC encrypt: - - my $aes_cbc = Crypt::CBC->new ({ - key => $key, - cipher => "Crypt::Rijndael", - iv => $iv, - literal_key => 1, - header => "none", - keysize => 16 - }); - - $encseed = $aes_cbc->encrypt ($seed); - } - - $hash_buf = keccak_256_hex ($seed . "\x02"); - - $tmp_hash = sprintf ("\$ethereum\$w*%s*%s*%s", unpack ("H*", $iv . $encseed), $ethaddr, substr ($hash_buf, 0, 32)); - } - elsif ($mode == 16400) - { - my $md5 = Digest::Perl::MD5->new; - my $length = length($word_buf); - - $md5->{_data} = $word_buf ^ ("\x5c" x $length); - $md5->{_data} .= "\x5c" x (64 - $length); - $md5->add(); - - $hash_buf = unpack("H*", pack('V4', @{$md5->{_state}})); - $tmp_hash = sprintf ("{CRAM-MD5}%s00000000000000000000000000000000", $hash_buf); - } - elsif ($mode == 16500) - { - my ($header_base64) = split (/\./, $salt_buf); - - my $header_jwt = decode_base64url ($header_base64); - - my $header = decode_json ($header_jwt); - - my $alg = $header->{"alg"}; - - if ($alg eq "HS256") - { - $hash_buf = hmac ($salt_buf, $word_buf, \&sha256, 64); - } - elsif ($alg eq "HS384") - { - $hash_buf = hmac ($salt_buf, $word_buf, \&sha384, 128); - } - elsif ($alg eq "HS512") - { - $hash_buf = hmac ($salt_buf, $word_buf, \&sha512, 128); - } - else - { - die "not supported hash\n"; - } - - $tmp_hash = sprintf ("%s.%s", $salt_buf, encode_base64url ($hash_buf, "")); - } - elsif ($mode == 16600) - { - my $key_bin = sha256 (sha256 ($word_buf)); - - my $salt_type; - - if (defined $additional_param) - { - $salt_type = $additional_param; - - if ($salt_type ne "1") { die "currently only salt_type 1 supported\n"; } - } - else - { - $salt_type = 1; - } - - my $iv; - - if (defined $additional_param2) - { - $iv = $additional_param2; - } - else - { - $iv = substr ($salt_buf, 0, 32); - } - - my $iv_bin = pack ("H*", $iv); - - my $cipher = Crypt::CBC->new ({ - key => $key_bin, - cipher => "Crypt::Rijndael", - iv => $iv_bin, - literal_key => 1, - header => "none", - keysize => 32, - padding => "null", - }); - - my $plain_bin; - - if (defined $additional_param3) - { - my $encrypted_bin = pack ("H*", $additional_param3); - - my $test = $cipher->decrypt ($encrypted_bin); - - if ($test =~ /^[0-9a-f]+$/) - { - $plain_bin = $test; - } - else - { - $plain_bin = "\xff" x 16; - } - } - else - { - my $plain = "30313233343536373839616263646566"; - - $plain_bin = pack ("H*", $plain); - } - - my $encrypted_bin = $cipher->encrypt ($plain_bin); - - my $encrypted = unpack ("H*", $encrypted_bin); - - $tmp_hash = sprintf ("\$electrum\$%d*%s*%s", $salt_type, $iv, $encrypted); - } - elsif ($mode == 16700) - { - my $salt_bin = pack ("H*", $salt_buf); - - my $iterations = 20000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $Z_PK = 1; - - if (defined $additional_param) - { - $Z_PK = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => 16, - ); - - my $KEK = $pbkdf2->PBKDF2 ($salt_bin, $word_buf); - - my $aes = Crypt::Mode::ECB->new ('AES', 0); - - my $blob_bin; - - my $A; - my $B; - my $P1; - my $P2; - - if (defined $additional_param2) - { - $blob_bin = pack ("H*", $additional_param2); - - $A = substr ($blob_bin, 0, 8); - $P1 = substr ($blob_bin, 8, 8); - $P2 = substr ($blob_bin, 16, 8); - - for (my $j = 5; $j >= 0; $j--) - { - # N = 2 - - $B = $A; - $B ^= pack ("Q>", (2 * $j + 2)); - $B .= $P2; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P2 = substr ($B, 8, 8); - - # N = 1 - - $B = $A; - $B ^= pack ("Q>", (2 * $j + 1)); - $B .= $P1; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P1 = substr ($B, 8, 8); - } - - if ($A eq "\xa6" x 8) - { - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 2)); - $P2 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2; - } - else - { - $blob_bin = "\xff" x 24; - } - } - else - { - $A = "\xa6" x 8; - $P1 = "\xff" x 8; - $P2 = "\xff" x 8; - - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (2 * $j + 2)); - $P2 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2; - } - - $tmp_hash = sprintf ('$fvde$%d$%d$%s$%d$%s', $Z_PK, length ($salt_bin), unpack ("H*", $salt_bin), $iterations, unpack ("H*", $blob_bin)); - } - elsif ($mode == 16800) - { - my $macap; - my $macsta; - my $essid; - - if (!defined ($additional_param)) - { - $macap = unpack ("H*", randbytes (6)); - } - else - { - $macap = $additional_param; - } - - if (!defined ($additional_param2)) - { - $macsta = unpack ("H*", randbytes (6)); - } - else - { - $macsta = $additional_param2; - } - - if (!defined ($additional_param3)) - { - $essid = unpack ("H*", randbytes (get_random_num (8, 32) & 0x1e)); - } - else - { - $essid = $additional_param3; - } - - # generate the Pairwise Master Key (PMK) - - my $iterations = 4096; - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 32, - ); - - my $essid_bin = pack ("H*", $essid); - - my $pmk = $pbkdf2->PBKDF2 ($essid_bin, $word_buf); - - my $macap_bin = pack ("H*", $macap); - my $macsta_bin = pack ("H*", $macsta); - - my $data = "PMK Name" . $macap_bin . $macsta_bin; - - my $pmkid = hmac_hex ($data, $pmk, \&sha1); - - $tmp_hash = sprintf ("%s*%s*%s*%s", substr ($pmkid, 0, 32), $macap, $macsta, $essid); - } - elsif ($mode == 17300) - { - $hash_buf = sha3_224_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17400) - { - $hash_buf = sha3_256_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17500) - { - $hash_buf = sha3_384_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17600) - { - $hash_buf = sha3_512_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17700) - { - $hash_buf = keccak_224_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17800) - { - $hash_buf = keccak_256_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 17900) - { - $hash_buf = keccak_384_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 18000) - { - $hash_buf = keccak_512_hex ($word_buf); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 18100) - { - my $paddedTime = sprintf ("%016x", int (int ($salt_buf) / 30)); - my $data = pack ('H*', $paddedTime); - my $key = $word_buf; - - $hash_buf = hmac_hex ($data, $key, \&sha1, 64); - - my $offset = hex (substr ($hash_buf, -8)) & 0xf; - $offset *= 2; - my $token = hex (substr ($hash_buf, $offset, 8)); - $token &= 0x7fffffff; - $token %= 1000000; - - ## token must be leading zero padded, and salt leading zero stripped - $tmp_hash = sprintf ("%06d:%d", $token, int ($salt_buf)); - } - elsif ($mode == 18200) - { - my @salt_arr = split (':', $salt_buf); - - my $user_principal_name = $salt_arr[0]; - - my $k = md4 (encode ("UTF-16LE", $word_buf)); - - my $k1 = hmac_md5 ("\x08\x00\x00\x00", $k); - - my $cleartext_ticket = '7981df3081dca01b3019a003020117a112041071e026814da2' . - '3f129f0e67a01b73f79aa11c301a3018a003020100a111180f32303138313033303039353' . - '831365aa206020460fdc6caa311180f32303337303931343032343830355aa40703050050' . - 'c10000a511180f32303138313033303039353831365aa611180f323031383130333030393' . - '53831365aa711180f32303138313033303139353831365aa811180f323031383130333131' . - '30303433385aa90d1b0b545952454c4c2e434f5250aa20301ea003020101a11730151b066' . - 'b72627467741b0b545952454c4c2e434f5250'; - my $checksum = ""; - - if (defined $additional_param) - { - $checksum = pack ("H*", $additional_param); - } - else - { - my $nonce = $salt_arr[1]; - - $cleartext_ticket = $nonce . $cleartext_ticket; - - $checksum = hmac_md5 (pack ("H*", $cleartext_ticket), $k1); - } - - my $k3 = hmac_md5 ($checksum, $k1); - - my $edata2 = ""; - - if (defined $additional_param2) - { - $edata2 = $additional_param2; - - my $cipher_decrypt = Crypt::RC4->new ($k3); - - my $ticket_decrypt = unpack ("H*", $cipher_decrypt->RC4 (pack ("H*", $edata2))); - - my $check_correct = ((substr ($ticket_decrypt, 16, 4) eq "7981" && substr ($ticket_decrypt, 22, 2) eq "30")) || - ((substr ($ticket_decrypt, 16, 2) eq "79") && (substr ($ticket_decrypt, 20, 2) eq "30")) || - ((substr ($ticket_decrypt, 16, 4) eq "7982") && (substr ($ticket_decrypt, 24, 2) eq "30")); - - if ($check_correct == 1) - { - $cleartext_ticket = $ticket_decrypt; - } - else # validation failed - { - # fake/wrong ticket (otherwise if we just decrypt/encrypt we end up with false positives all the time) - $cleartext_ticket = "0" x (length ($cleartext_ticket) + 16); - } - } - - my $cipher = Crypt::RC4->new ($k3); - - $edata2 = $cipher->RC4 (pack ("H*", $cleartext_ticket)); - - $tmp_hash = sprintf ('$krb5asrep$23$%s:%s$%s', $user_principal_name, unpack ("H*", $checksum), unpack ("H*", $edata2)); - } - elsif ($mode == 18300) - { - my $salt_bin = pack ("H*", $salt_buf); - - my $iterations = 20000; - - if (defined ($iter)) - { - $iterations = $iter; - } - - my $Z_PK = 2; - - if (defined $additional_param) - { - $Z_PK = $additional_param; - } - - my $pbkdf2 = Crypt::PBKDF2->new - ( - hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256), - iterations => $iterations, - output_len => 32, - ); - - my $KEK = $pbkdf2->PBKDF2 ($salt_bin, $word_buf); - - my $aes = Crypt::Mode::ECB->new ('AES', 0); - - my $blob_bin; - - my $A; - my $B; - my $P1; - my $P2; - my $P3; - my $P4; - - if (defined $additional_param2) - { - $blob_bin = pack ("H*", $additional_param2); - - $A = substr ($blob_bin, 0, 8); - $P1 = substr ($blob_bin, 8, 8); - $P2 = substr ($blob_bin, 16, 8); - $P3 = substr ($blob_bin, 24, 8); - $P4 = substr ($blob_bin, 32, 8); - - for (my $j = 5; $j >= 0; $j--) - { - # N = 4 - - $B = $A; - $B ^= pack ("Q>", (4 * $j + 4)); - $B .= $P4; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P4 = substr ($B, 8, 8); - - # N = 3 - - $B = $A; - $B ^= pack ("Q>", (4 * $j + 3)); - $B .= $P3; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P3 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B ^= pack ("Q>", (4 * $j + 2)); - $B .= $P2; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P2 = substr ($B, 8, 8); - - # N = 1 - - $B = $A; - $B ^= pack ("Q>", (4 * $j + 1)); - $B .= $P1; - $B = $aes->decrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $P1 = substr ($B, 8, 8); - } - - if ($A eq "\xa6" x 8) - { - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 2)); - $P2 = substr ($B, 8, 8); - - # N = 3 - - $B = $A; - $B .= $P3; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 3)); - $P3 = substr ($B, 8, 8); - - # N = 4 - - $B = $A; - $B .= $P4; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 4)); - $P4 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2 . $P3 . $P4; - } - else - { - $blob_bin = "\xff" x 40; - } - } - else - { - $A = "\xa6" x 8; - $P1 = "\xff" x 8; - $P2 = "\xff" x 8; - $P3 = "\xff" x 8; - $P4 = "\xff" x 8; - - for (my $j = 0; $j <= 5; $j++) - { - # N = 1 - - $B = $A; - $B .= $P1; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 1)); - $P1 = substr ($B, 8, 8); - - # N = 2 - - $B = $A; - $B .= $P2; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 2)); - $P2 = substr ($B, 8, 8); - - # N = 3 - - $B = $A; - $B .= $P3; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 3)); - $P3 = substr ($B, 8, 8); - - # N = 4 - - $B = $A; - $B .= $P4; - $B = $aes->encrypt ($B, $KEK); - $A = substr ($B, 0, 8); - $A ^= pack ("Q>", (4 * $j + 4)); - $P4 = substr ($B, 8, 8); - } - - $blob_bin = $A . $P1 . $P2 . $P3 . $P4; - } - - $tmp_hash = sprintf ('$fvde$%d$%d$%s$%d$%s', $Z_PK, length ($salt_bin), unpack ("H*", $salt_bin), $iterations, unpack ("H*", $blob_bin)); - } - elsif ($mode == 18400) - { - # defaults for single mode - my $iterations = 100000; - my $iv = "aa" x 16; - my $plaintext = "bb" x 1024; - - # parameters for verify mode - if (defined $iter) - { - $iterations = $iter; - } - - if (defined $additional_param) - { - $iv = $additional_param; - } - - if (defined $additional_param2) - { - $plaintext = $additional_param2; - } - - # binary buffers - my $b_iv = pack ("H*", $iv); - my $b_salt = pack ("H*", $salt_buf); - my $b_plaintext = pack ("H*", $plaintext); - - my $kdf = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 32 - ); - - my $checksum = sha256_hex ($b_plaintext); - - my $pass_hash = sha256 ($word_buf); - my $derived_key = $kdf->PBKDF2 ($b_salt, $pass_hash); - my $cbc = Crypt::Mode::CBC->new ('AES', 0); - my $b_ciphertext = $cbc->encrypt ($b_plaintext, $derived_key, $b_iv); - - my $ciphertext = unpack ("H*", $b_ciphertext); - - $tmp_hash = '$odf$'."*1*1*$iterations*32*$checksum*16*$iv*16*$salt_buf*0*$ciphertext"; - } - elsif ($mode == 18500) - { - $hash_buf = sha1_hex (md5_hex (md5_hex ($word_buf))); - - $tmp_hash = sprintf ("%s", $hash_buf); - } - elsif ($mode == 18600) - { - # defaults for single mode - my $iterations = 1024; - my $iv = "aa" x 8; - my $plaintext = "bb" x 1024; - - # parameters for verify mode - if (defined $iter) - { - $iterations = $iter; - } - - if (defined $additional_param) - { - $iv = $additional_param; - } - - if (defined $additional_param2) - { - $plaintext = $additional_param2; - } - - # binary buffers - my $b_iv = pack ("H*", $iv); - my $b_salt = pack ("H*", $salt_buf); - my $b_plaintext = pack ("H*", $plaintext); - - my $kdf = Crypt::PBKDF2->new - ( - hash_class => 'HMACSHA1', - iterations => $iterations, - output_len => 16 - ); - - my $checksum = sha1_hex ($b_plaintext); - my $pass_hash = sha1 ($word_buf); - my $derived_key = $kdf->PBKDF2 ($b_salt, $pass_hash); - - my $cfb = Crypt::GCrypt->new( - type => 'cipher', - algorithm => 'blowfish', - mode => 'cfb', - ); - - $cfb->start ('encrypting'); - $cfb->setkey ($derived_key); - $cfb->setiv ($b_iv); - - my $b_ciphertext = $cfb->encrypt ($b_plaintext); - - $cfb->finish (); - - my $ciphertext = unpack ("H*", $b_ciphertext); - - $tmp_hash = '$odf$'."*0*0*$iterations*16*$checksum*8*$iv*16*$salt_buf*0*$ciphertext"; - } - elsif ($mode == 99999) - { - $tmp_hash = sprintf ("%s", $word_buf); - } - - return ($tmp_hash); -} - -#Thanks to Jochen Hoenicke -# (one of the authors of Palm Keyring) -# for these next two subs. -sub dpapi_pbkdf2 -{ - my ($password, $salt, $iter, $keylen, $prf) = @_; - my ($k, $t, $u, $ui, $i); - $t = ""; - for ($k = 1; length ($t) < $keylen; $k++) - { - $u = $ui = &$prf ($salt.pack ('N', $k), $password); - for ($i = 1; $i < $iter; $i++) - { - # modification to fit Microsoft - # weird pbkdf2 implementation... - $ui = &$prf ($u, $password); - $u ^= $ui; - } - $t .= $u; - } - return substr ($t, 0, $keylen); -} - -## STEP 4: Add custom traits here (optional). -sub rnd -{ - my $mode = shift; - - my $word_len = shift; - - my $salt_len = shift; - - my $max = $MAX_LEN; - - if ($mode == 2410) - { - $salt_len = min ($salt_len, 4); - } - - if (is_in_array ($mode, $IS_UTF16LE)) - { - if (is_in_array ($mode, $ALLOW_LONG_SALT)) - { - $word_len = min ($word_len, int ($max / 2)); - } - else - { - $word_len = min ($word_len, int ($max / 2) - $salt_len); - } - } - elsif (is_in_array ($mode, $LESS_FIFTEEN)) - { - $word_len = min ($word_len, 15); - } - else - { - if (! is_in_array ($mode, $ALLOW_LONG_SALT)) - { - $word_len = min ($word_len, $max - $salt_len); - } - } - - if ($word_len < 1) - { - $word_len = 1; - } - - ## - ## gen salt - ## - - my $salt_buf; - - if ($mode == 4800) - { - my @salt_arr; - - for (my $i = 0; $i < $salt_len; $i++) - { - my $c = get_random_chr (0x30, 0x39); - - push (@salt_arr, $c); - } - - $salt_buf = join ("", @salt_arr); - - $salt_buf = get_random_md5chap_salt ($salt_buf); - } - elsif ($mode == 5300 || $mode == 5400) - { - $salt_buf = get_random_ike_salt (); - } - elsif ($mode == 5500) - { - $salt_buf = get_random_netntlmv1_salt ($salt_len, $salt_len); - } - elsif ($mode == 5600) - { - $salt_buf = get_random_netntlmv2_salt ($salt_len, $salt_len); - } - elsif ($mode == 6600) - { - $salt_buf = get_random_agilekeychain_salt (); - } - elsif ($mode == 8200) - { - $salt_buf = get_random_cloudkeychain_salt (); - } - elsif ($mode == 8300) - { - $salt_buf = get_random_dnssec_salt (); - } - elsif ($mode == 13100) - { - $salt_buf = get_random_kerberos5_tgs_salt (); - } - elsif ($mode == 13200) - { - $salt_buf = get_random_axcrypt_salt (); - } - elsif ($mode == 13400) - { - $salt_buf = get_random_keepass_salt (); - } - elsif ($mode == 13500) - { - $salt_buf = get_pstoken_salt (); - } - elsif ($mode == 15300 || $mode == 15900) - { - my $version = 2; - - if ($mode == 15300) - { - $version = 1; - } - - $salt_buf = get_random_dpapimk_salt ($version); - } - elsif ($mode == 16500) - { - $salt_buf = get_random_jwt_salt (); - } - elsif ($mode == 18200) - { - $salt_buf = get_random_kerberos5_as_rep_salt (); - } - else - { - my @salt_arr; - - for (my $i = 0; $i < $salt_len; $i++) - { - my $c = get_random_chr (0x30, 0x39); - - push (@salt_arr, $c); - } - - $salt_buf = join ("", @salt_arr); - - if ($mode == 7500) - { - $salt_buf = get_random_kerberos5_salt ($salt_buf); - } - } - - ## - ## gen plain - ## - - my @word_arr; - - for (my $i = 0; $i < $word_len; $i++) - { - my $c = get_random_chr (0x30, 0x39); - - if (($mode == 14000) || ($mode == 14100)) - { - $c &= 0xfe; - } - - push (@word_arr, $c); - } - - my $word_buf = join ("", @word_arr); - - ## - ## gen hash - ## - - my $tmp_hash = gen_hash ($mode, $word_buf, $salt_buf); - - ## - ## run - ## - - my @cmd = - ( - $hashcat, - "-a 0 -m", $mode, - $tmp_hash - ); - - print sprintf ("echo -n %-20s | %s \${OPTS} %s %4d '%s'\n", $word_buf, @cmd); -} - -## -## subs -## - -sub min -{ - $_[$_[0] > $_[1]]; -} - -sub get_random_string -{ - my $len = shift; - - my @arr; - - for (my $i = 0; $i < $len; $i++) - { - my $c = get_random_chr (0x30, 0x39); - - push (@arr, $c); - } - - my $buf = join ("", @arr); - - return $buf; -} - -sub get_random_num -{ - my $min = shift; - my $max = shift; - - return int ((rand ($max - $min)) + $min); -} - -sub get_random_chr -{ - return chr get_random_num (@_); -} - -sub domino_decode -{ - my $str = shift; - - my $decoded = ""; - - for (my $i = 0; $i < length ($str); $i += 4) - { - my $num = domino_base64_decode (substr ($str, $i, 4), 4); - - $decoded .= chr (($num >> 16) & 0xff) . chr (($num >> 8) & 0xff) . chr ($num & 0xff); - } - - my $salt; - my $digest; - my $char; - - $salt = substr ($decoded, 0, 5); - - my $byte10 = (ord (substr ($salt, 3, 1)) - 4); - - if ($byte10 < 0) - { - $byte10 = 256 + $byte10; - } - - substr ($salt, 3, 1) = chr ($byte10); - - $digest = substr ($decoded, 5, 9); - $char = substr ($str, 18, 1); - - return ($digest, $salt, $char); -} - -sub domino_85x_decode -{ - my $str = shift; - - my $decoded = ""; - - for (my $i = 0; $i < length ($str); $i += 4) - { - my $num = domino_base64_decode (substr ($str, $i, 4), 4); - - $decoded .= chr (($num >> 16) & 0xff) . chr (($num >> 8) & 0xff) . chr ($num & 0xff); - } - - my $digest; - my $salt; - my $iterations = -1; - my $chars; - - $salt = substr ($decoded, 0, 16); # longer than -m 8700 (5 vs 16 <- new) - - my $byte10 = (ord (substr ($salt, 3, 1)) - 4); - - if ($byte10 < 0) - { - $byte10 = 256 + $byte10; - } - - substr ($salt, 3, 1) = chr ($byte10); - - $iterations = substr ($decoded, 16, 10); - - if ($iterations =~ /^?d*$/) - { - # continue - - $iterations = $iterations + 0; # hack: make sure it is an int now (atoi ()) - $chars = substr ($decoded, 26, 2); # in my example it is "02" - $digest = substr ($decoded, 28, 8); # only of length of 8 vs 20 SHA1 bytes - } - - return ($digest, $salt, $iterations, $chars); -} - -sub domino_base64_decode -{ - my $v = shift; - my $n = shift; - - my $itoa64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - - my $ret = 0; - - my $i = 1; - - while ($i <= $n) - { - my $idx = (index ($itoa64, substr ($v, $n - $i, 1))) & 0x3f; - - $ret += ($idx << (6 * ($i - 1))); - - $i = $i + 1; - } - - return $ret -} - -sub domino_encode -{ - my $final = shift; - my $char = shift; - - my $byte10 = (ord (substr ($final, 3, 1)) + 4); - - if ($byte10 > 255) - { - $byte10 = $byte10 - 256; - } - - substr ($final, 3, 1) = chr ($byte10); - - my $passwd = ""; - - $passwd .= domino_base64_encode ((int (ord (substr ($final, 0, 1))) << 16) | (int (ord (substr ($final, 1, 1))) << 8) | (int (ord (substr ($final, 2, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 3, 1))) << 16) | (int (ord (substr ($final, 4, 1))) << 8) | (int (ord (substr ($final, 5, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 6, 1))) << 16) | (int (ord (substr ($final, 7, 1))) << 8) | (int (ord (substr ($final, 8, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 9, 1))) << 16) | (int (ord (substr ($final, 10, 1))) << 8) | (int (ord (substr ($final, 11, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 12, 1))) << 16) | (int (ord (substr ($final, 13, 1))) << 8) | (int (ord (substr ($final, 14, 1)))), 4); - - if (defined ($char)) - { - substr ($passwd, 18, 1) = $char; - } - substr ($passwd, 19, 1) = ""; - - return $passwd; -} - -sub domino_85x_encode -{ - my $final = shift; - my $char = shift; - - my $byte10 = (ord (substr ($final, 3, 1)) + 4); - - if ($byte10 > 255) - { - $byte10 = $byte10 - 256; - } - - substr ($final, 3, 1) = chr ($byte10); - - my $passwd = ""; - - $passwd .= domino_base64_encode ((int (ord (substr ($final, 0, 1))) << 16) | (int (ord (substr ($final, 1, 1))) << 8) | (int (ord (substr ($final, 2, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 3, 1))) << 16) | (int (ord (substr ($final, 4, 1))) << 8) | (int (ord (substr ($final, 5, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 6, 1))) << 16) | (int (ord (substr ($final, 7, 1))) << 8) | (int (ord (substr ($final, 8, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 9, 1))) << 16) | (int (ord (substr ($final, 10, 1))) << 8) | (int (ord (substr ($final, 11, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 12, 1))) << 16) | (int (ord (substr ($final, 13, 1))) << 8) | (int (ord (substr ($final, 14, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 15, 1))) << 16) | (int (ord (substr ($final, 16, 1))) << 8) | (int (ord (substr ($final, 17, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 18, 1))) << 16) | (int (ord (substr ($final, 19, 1))) << 8) | (int (ord (substr ($final, 20, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 21, 1))) << 16) | (int (ord (substr ($final, 22, 1))) << 8) | (int (ord (substr ($final, 23, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 24, 1))) << 16) | (int (ord (substr ($final, 25, 1))) << 8) | (int (ord (substr ($final, 26, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 27, 1))) << 16) | (int (ord (substr ($final, 28, 1))) << 8) | (int (ord (substr ($final, 29, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 30, 1))) << 16) | (int (ord (substr ($final, 31, 1))) << 8) | (int (ord (substr ($final, 32, 1)))), 4); - $passwd .= domino_base64_encode ((int (ord (substr ($final, 33, 1))) << 16) | (int (ord (substr ($final, 34, 1))) << 8) | (int (ord (substr ($final, 35, 1)))), 4); - - if (defined ($char)) - { - substr ($passwd, 18, 1) = $char; - } - - return $passwd; -} - -sub domino_base64_encode -{ - my $v = shift; - my $n = shift; - - my $itoa64 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - - my $ret = ""; - - while (($n - 1) >= 0) - { - $n = $n - 1; - - $ret = substr ($itoa64, $v & 0x3f, 1) . $ret; - - $v = $v >> 6; - } - - return $ret -} - -sub pseudo_base64 -{ - my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - my $md5 = shift; - my $s64 = ""; - for my $i (0..3) { - my $v = unpack "V", substr ($md5, $i*4, 4); - for (1..4) { - $s64 .= substr ($itoa64, $v & 0x3f, 1); - $v >>= 6; - } - } - return $s64; -} - -sub racf_hash -{ - my ($username, $password) = @_; - - $username = substr ($username . " " x 8, 0, 8); - $password = substr ($password . " " x 8, 0, 8); - - my $username_ebc = ascii2ebcdic ($username); - my $password_ebc = ascii2ebcdic ($password); - - my @pw = split ("", $password_ebc); - - for (my $i = 0; $i < 8; $i++) - { - $pw[$i] = unpack ("C", $pw[$i]); - $pw[$i] ^= 0x55; - $pw[$i] <<= 1; - $pw[$i] = pack ("C", $pw[$i] & 0xff); - } - - my $key = join ("", @pw); - - my $cipher = new Crypt::DES $key; - - my $ciphertext = $cipher->encrypt ($username_ebc); - - my $ct = unpack ("H16", $ciphertext); - - return $ct; -} - -sub oracle_hash -{ - my ($username, $password) = @_; - - my $userpass = pack ('n*', unpack ('C*', uc ($username.$password))); - $userpass .= pack ('C', 0) while (length ($userpass) % 8); - - my $key = pack ('H*', "0123456789ABCDEF"); - my $iv = pack ('H*', "0000000000000000"); - - my $c = new Crypt::CBC ( - -literal_key => 1, - -cipher => "DES", - -key => $key, - -iv => $iv, - -header => "none" - ); - my $key2 = substr ($c->encrypt ($userpass), length ($userpass)-8, 8); - - my $c2 = new Crypt::CBC ( - -literal_key => 1, - -cipher => "DES", - -key => $key2, - -iv => $iv, - -header => "none" - ); - my $hash = substr ($c2->encrypt ($userpass), length ($userpass)-8, 8); - - return uc (unpack ('H*', $hash)); -} - -sub androidpin_hash -{ - my $word_buf = shift; - - my $salt_buf = shift; - - my $w = sprintf ("%d%s%s", 0, $word_buf, $salt_buf); - - my $digest = sha1 ($w); - - for (my $i = 1; $i < 1024; $i++) - { - $w = $digest . sprintf ("%d%s%s", $i, $word_buf, $salt_buf); - - $digest = sha1 ($w); - } - - my ($A, $B, $C, $D, $E) = unpack ("N5", $digest); - - return sprintf ("%08x%08x%08x%08x%08x", $A, $B, $C, $D, $E); -} - -sub to64 -{ - my $v = shift; - my $n = shift; - - my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - my $ret = ""; - - while (($n - 1) >= 0) - { - $n = $n - 1; - - $ret .= substr ($itoa64, $v & 0x3f, 1); - - $v = $v >> 6; - } - - return $ret -} - -sub md5_crypt -{ - my $magic = shift; - - my $iter = shift; - my $pass = shift; - my $salt = shift; - - my $hash = ""; # hash to be returned by this function - - my $final = md5 ($pass . $salt . $pass); - - $salt = substr ($salt, 0, 8); - - my $tmp = $pass . $magic . $salt; - - my $pass_len = length ($pass); - - my $i; - - for ($i = $pass_len; $i > 0; $i -= 16) - { - my $len = 16; - - if ($i < $len) - { - $len = $i; - } - - $tmp .= substr ($final, 0, $len); - } - - $i = $pass_len; - - while ($i > 0) - { - if ($i & 1) - { - $tmp .= chr (0); - } - else - { - $tmp .= substr ($pass, 0, 1); - } - - $i >>= 1; - } - - $final = md5 ($tmp); - - for ($i = 0; $i < $iter; $i++) - { - $tmp = ""; - - if ($i & 1) - { - $tmp .= $pass; - } - else - { - $tmp .= $final; - } - - if ($i % 3) - { - $tmp .= $salt; - } - - if ($i % 7) - { - $tmp .= $pass; - } - - if ($i & 1) - { - $tmp .= $final; - } - else - { - $tmp .= $pass; - } - - $final = md5 ($tmp); - } - - # done - # now format the output sting ("hash") - - my $hash_buf; - - $hash = to64 ((ord (substr ($final, 0, 1)) << 16) | (ord (substr ($final, 6, 1)) << 8) | (ord (substr ($final, 12, 1))), 4); - $hash .= to64 ((ord (substr ($final, 1, 1)) << 16) | (ord (substr ($final, 7, 1)) << 8) | (ord (substr ($final, 13, 1))), 4); - $hash .= to64 ((ord (substr ($final, 2, 1)) << 16) | (ord (substr ($final, 8, 1)) << 8) | (ord (substr ($final, 14, 1))), 4); - $hash .= to64 ((ord (substr ($final, 3, 1)) << 16) | (ord (substr ($final, 9, 1)) << 8) | (ord (substr ($final, 15, 1))), 4); - $hash .= to64 ((ord (substr ($final, 4, 1)) << 16) | (ord (substr ($final, 10, 1)) << 8) | (ord (substr ($final, 5, 1))), 4); - $hash .= to64 (ord (substr ($final, 11, 1)), 2); - - if ($iter == 1000) # default - { - $hash_buf = sprintf ("%s%s\$%s", $magic , $salt , $hash); - } - else - { - $hash_buf = sprintf ("%srounds=%i\$%s\$%s", $magic, $iter, $salt , $hash); - } - - return $hash_buf; -} - -sub sha512_crypt -{ - my $iter = shift; - my $pass = shift; - my $salt = shift; - - my $hash = ""; # hash to be returned by this function - - my $final = sha512 ($pass . $salt . $pass); - - $salt = substr ($salt, 0, 16); - - my $tmp = $pass . $salt; - - my $pass_len = length ($pass); - my $salt_len = length ($salt); - - my $i; - - for ($i = $pass_len; $i > 0; $i -= 16) - { - my $len = 16; - - if ($i < $len) - { - $len = $i; - } - - $tmp .= substr ($final, 0, $len); - } - - $i = $pass_len; - - while ($i > 0) - { - if ($i & 1) - { - $tmp .= $final; - } - else - { - $tmp .= $pass; - } - - $i >>= 1; - } - - $final = sha512 ($tmp); - - # p_bytes - - my $p_bytes = ""; - - for ($i = 0; $i < $pass_len; $i++) - { - $p_bytes .= $pass; - } - - $p_bytes = sha512 ($p_bytes); - $p_bytes = substr ($p_bytes, 0, $pass_len); - - # s_bytes - - my $final_first_byte = ord (substr ($final, 0, 1)); - - my $s_bytes = ""; - - for ($i = 0; $i < (16 + $final_first_byte); $i++) - { - $s_bytes .= $salt; - } - - $s_bytes = sha512 ($s_bytes); - $s_bytes = substr ($s_bytes, 0, $salt_len); - - for ($i = 0; $i < $iter; $i++) - { - $tmp = ""; - - if ($i & 1) - { - $tmp .= $p_bytes; - } - else - { - $tmp .= $final; - } - - if ($i % 3) - { - $tmp .= $s_bytes; - } - - if ($i % 7) - { - $tmp .= $p_bytes; - } - - if ($i & 1) - { - $tmp .= $final; - } - else - { - $tmp .= $p_bytes; - } - - $final = sha512 ($tmp); - } - - # done - # now format the output string ("hash") - - my $hash_buf; - - $hash .= to64 ((ord (substr ($final, 0, 1)) << 16) | (ord (substr ($final, 21, 1)) << 8) | (ord (substr ($final, 42, 1))), 4); - $hash .= to64 ((ord (substr ($final, 22, 1)) << 16) | (ord (substr ($final, 43, 1)) << 8) | (ord (substr ($final, 1, 1))), 4); - $hash .= to64 ((ord (substr ($final, 44, 1)) << 16) | (ord (substr ($final, 2, 1)) << 8) | (ord (substr ($final, 23, 1))), 4); - $hash .= to64 ((ord (substr ($final, 3, 1)) << 16) | (ord (substr ($final, 24, 1)) << 8) | (ord (substr ($final, 45, 1))), 4); - $hash .= to64 ((ord (substr ($final, 25, 1)) << 16) | (ord (substr ($final, 46, 1)) << 8) | (ord (substr ($final, 4, 1))), 4); - $hash .= to64 ((ord (substr ($final, 47, 1)) << 16) | (ord (substr ($final, 5, 1)) << 8) | (ord (substr ($final, 26, 1))), 4); - $hash .= to64 ((ord (substr ($final, 6, 1)) << 16) | (ord (substr ($final, 27, 1)) << 8) | (ord (substr ($final, 48, 1))), 4); - $hash .= to64 ((ord (substr ($final, 28, 1)) << 16) | (ord (substr ($final, 49, 1)) << 8) | (ord (substr ($final, 7, 1))), 4); - $hash .= to64 ((ord (substr ($final, 50, 1)) << 16) | (ord (substr ($final, 8, 1)) << 8) | (ord (substr ($final, 29, 1))), 4); - $hash .= to64 ((ord (substr ($final, 9, 1)) << 16) | (ord (substr ($final, 30, 1)) << 8) | (ord (substr ($final, 51, 1))), 4); - $hash .= to64 ((ord (substr ($final, 31, 1)) << 16) | (ord (substr ($final, 52, 1)) << 8) | (ord (substr ($final, 10, 1))), 4); - $hash .= to64 ((ord (substr ($final, 53, 1)) << 16) | (ord (substr ($final, 11, 1)) << 8) | (ord (substr ($final, 32, 1))), 4); - $hash .= to64 ((ord (substr ($final, 12, 1)) << 16) | (ord (substr ($final, 33, 1)) << 8) | (ord (substr ($final, 54, 1))), 4); - $hash .= to64 ((ord (substr ($final, 34, 1)) << 16) | (ord (substr ($final, 55, 1)) << 8) | (ord (substr ($final, 13, 1))), 4); - $hash .= to64 ((ord (substr ($final, 56, 1)) << 16) | (ord (substr ($final, 14, 1)) << 8) | (ord (substr ($final, 35, 1))), 4); - $hash .= to64 ((ord (substr ($final, 15, 1)) << 16) | (ord (substr ($final, 36, 1)) << 8) | (ord (substr ($final, 57, 1))), 4); - $hash .= to64 ((ord (substr ($final, 37, 1)) << 16) | (ord (substr ($final, 58, 1)) << 8) | (ord (substr ($final, 16, 1))), 4); - $hash .= to64 ((ord (substr ($final, 59, 1)) << 16) | (ord (substr ($final, 17, 1)) << 8) | (ord (substr ($final, 38, 1))), 4); - $hash .= to64 ((ord (substr ($final, 18, 1)) << 16) | (ord (substr ($final, 39, 1)) << 8) | (ord (substr ($final, 60, 1))), 4); - $hash .= to64 ((ord (substr ($final, 40, 1)) << 16) | (ord (substr ($final, 61, 1)) << 8) | (ord (substr ($final, 19, 1))), 4); - $hash .= to64 ((ord (substr ($final, 62, 1)) << 16) | (ord (substr ($final, 20, 1)) << 8) | (ord (substr ($final, 41, 1))), 4); - $hash .= to64 (ord (substr ($final, 63, 1)), 2); - - my $magic = '$6$'; - - if ($iter == 5000) # default - { - $hash_buf = sprintf ("%s%s\$%s", $magic, $salt , $hash); - } - else - { - $hash_buf = sprintf ("%srounds=%i\$%s\$%s", $magic, $iter, $salt , $hash); - } - - return $hash_buf; -} - -sub sha256_crypt -{ - my $iter = shift; - my $pass = shift; - my $salt = shift; - - my $hash = ""; # hash to be returned by this function - - my $final = sha256 ($pass . $salt . $pass); - - $salt = substr ($salt, 0, 16); - - my $tmp = $pass . $salt; - - my $pass_len = length ($pass); - my $salt_len = length ($salt); - - my $i; - - for ($i = $pass_len; $i > 0; $i -= 16) - { - my $len = 16; - - if ($i < $len) - { - $len = $i; - } - - $tmp .= substr ($final, 0, $len); - } - - $i = $pass_len; - - while ($i > 0) - { - if ($i & 1) - { - $tmp .= $final; - } - else - { - $tmp .= $pass; - } - - $i >>= 1; - } - - $final = sha256 ($tmp); - - # p_bytes - - my $p_bytes = ""; - - for ($i = 0; $i < $pass_len; $i++) - { - $p_bytes .= $pass; - } - - $p_bytes = sha256 ($p_bytes); - $p_bytes = substr ($p_bytes, 0, $pass_len); - - # s_bytes - - my $final_first_byte = ord (substr ($final, 0, 1)); - - my $s_bytes = ""; - - for ($i = 0; $i < (16 + $final_first_byte); $i++) - { - $s_bytes .= $salt; - } - - $s_bytes = sha256 ($s_bytes); - $s_bytes = substr ($s_bytes, 0, $salt_len); - - for ($i = 0; $i < $iter; $i++) - { - $tmp = ""; - - if ($i & 1) - { - $tmp .= $p_bytes; - } - else - { - $tmp .= $final; - } - - if ($i % 3) - { - $tmp .= $s_bytes; - } - - if ($i % 7) - { - $tmp .= $p_bytes; - } - - if ($i & 1) - { - $tmp .= $final; - } - else - { - $tmp .= $p_bytes; - } - - $final = sha256 ($tmp); - } - - # done - # now format the output string ("hash") - - my $hash_buf; - - $hash .= to64 ((ord (substr ($final, 0, 1)) << 16) | (ord (substr ($final, 10, 1)) << 8) | (ord (substr ($final, 20, 1))), 4); - $hash .= to64 ((ord (substr ($final, 21, 1)) << 16) | (ord (substr ($final, 1, 1)) << 8) | (ord (substr ($final, 11, 1))), 4); - $hash .= to64 ((ord (substr ($final, 12, 1)) << 16) | (ord (substr ($final, 22, 1)) << 8) | (ord (substr ($final, 2, 1))), 4); - $hash .= to64 ((ord (substr ($final, 3, 1)) << 16) | (ord (substr ($final, 13, 1)) << 8) | (ord (substr ($final, 23, 1))), 4); - $hash .= to64 ((ord (substr ($final, 24, 1)) << 16) | (ord (substr ($final, 4, 1)) << 8) | (ord (substr ($final, 14, 1))), 4); - $hash .= to64 ((ord (substr ($final, 15, 1)) << 16) | (ord (substr ($final, 25, 1)) << 8) | (ord (substr ($final, 5, 1))), 4); - $hash .= to64 ((ord (substr ($final, 6, 1)) << 16) | (ord (substr ($final, 16, 1)) << 8) | (ord (substr ($final, 26, 1))), 4); - $hash .= to64 ((ord (substr ($final, 27, 1)) << 16) | (ord (substr ($final, 7, 1)) << 8) | (ord (substr ($final, 17, 1))), 4); - $hash .= to64 ((ord (substr ($final, 18, 1)) << 16) | (ord (substr ($final, 28, 1)) << 8) | (ord (substr ($final, 8, 1))), 4); - $hash .= to64 ((ord (substr ($final, 9, 1)) << 16) | (ord (substr ($final, 19, 1)) << 8) | (ord (substr ($final, 29, 1))), 4); - $hash .= to64 ((ord (substr ($final, 31, 1)) << 8) | (ord (substr ($final, 30, 1))), 3); - - my $magic = '$5$'; - - if ($iter == 5000) # default - { - $hash_buf = sprintf ("%s%s\$%s", $magic, $salt , $hash); - } - else - { - $hash_buf = sprintf ("%srounds=%i\$%s\$%s", $magic, $iter, $salt , $hash); - } - - return $hash_buf; -} - -sub aix_ssha256_pbkdf2 -{ - my $word_buf = shift; - my $salt_buf = shift; - my $iterations = shift; - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - output_len => 32 - ); - - my $hash_buf = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $tmp_hash = ""; - - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 0, 1))) << 16) | (int (ord (substr ($hash_buf, 1, 1))) << 8) | (int (ord (substr ($hash_buf, 2, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 3, 1))) << 16) | (int (ord (substr ($hash_buf, 4, 1))) << 8) | (int (ord (substr ($hash_buf, 5, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 6, 1))) << 16) | (int (ord (substr ($hash_buf, 7, 1))) << 8) | (int (ord (substr ($hash_buf, 8, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 9, 1))) << 16) | (int (ord (substr ($hash_buf, 10, 1))) << 8) | (int (ord (substr ($hash_buf, 11, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 12, 1))) << 16) | (int (ord (substr ($hash_buf, 13, 1))) << 8) | (int (ord (substr ($hash_buf, 14, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 15, 1))) << 16) | (int (ord (substr ($hash_buf, 16, 1))) << 8) | (int (ord (substr ($hash_buf, 17, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 18, 1))) << 16) | (int (ord (substr ($hash_buf, 19, 1))) << 8) | (int (ord (substr ($hash_buf, 20, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 21, 1))) << 16) | (int (ord (substr ($hash_buf, 22, 1))) << 8) | (int (ord (substr ($hash_buf, 23, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 24, 1))) << 16) | (int (ord (substr ($hash_buf, 25, 1))) << 8) | (int (ord (substr ($hash_buf, 26, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 27, 1))) << 16) | (int (ord (substr ($hash_buf, 28, 1))) << 8) | (int (ord (substr ($hash_buf, 29, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 30, 1))) << 16) | (int (ord (substr ($hash_buf, 31, 1))) << 8) , 3); - - return $tmp_hash; -} - -sub aix_ssha512_pbkdf2 -{ - my $word_buf = shift; - my $salt_buf = shift; - my $iterations = shift; - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - ); - - my $hash_buf = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $tmp_hash = ""; - - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 0, 1))) << 16) | (int (ord (substr ($hash_buf, 1, 1))) << 8) | (int (ord (substr ($hash_buf, 2, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 3, 1))) << 16) | (int (ord (substr ($hash_buf, 4, 1))) << 8) | (int (ord (substr ($hash_buf, 5, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 6, 1))) << 16) | (int (ord (substr ($hash_buf, 7, 1))) << 8) | (int (ord (substr ($hash_buf, 8, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 9, 1))) << 16) | (int (ord (substr ($hash_buf, 10, 1))) << 8) | (int (ord (substr ($hash_buf, 11, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 12, 1))) << 16) | (int (ord (substr ($hash_buf, 13, 1))) << 8) | (int (ord (substr ($hash_buf, 14, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 15, 1))) << 16) | (int (ord (substr ($hash_buf, 16, 1))) << 8) | (int (ord (substr ($hash_buf, 17, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 18, 1))) << 16) | (int (ord (substr ($hash_buf, 19, 1))) << 8) | (int (ord (substr ($hash_buf, 20, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 21, 1))) << 16) | (int (ord (substr ($hash_buf, 22, 1))) << 8) | (int (ord (substr ($hash_buf, 23, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 24, 1))) << 16) | (int (ord (substr ($hash_buf, 25, 1))) << 8) | (int (ord (substr ($hash_buf, 26, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 27, 1))) << 16) | (int (ord (substr ($hash_buf, 28, 1))) << 8) | (int (ord (substr ($hash_buf, 29, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 30, 1))) << 16) | (int (ord (substr ($hash_buf, 31, 1))) << 8) | (int (ord (substr ($hash_buf, 32, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 33, 1))) << 16) | (int (ord (substr ($hash_buf, 34, 1))) << 8) | (int (ord (substr ($hash_buf, 35, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 36, 1))) << 16) | (int (ord (substr ($hash_buf, 37, 1))) << 8) | (int (ord (substr ($hash_buf, 38, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 39, 1))) << 16) | (int (ord (substr ($hash_buf, 40, 1))) << 8) | (int (ord (substr ($hash_buf, 41, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 42, 1))) << 16) | (int (ord (substr ($hash_buf, 43, 1))) << 8) | (int (ord (substr ($hash_buf, 44, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 45, 1))) << 16) | (int (ord (substr ($hash_buf, 46, 1))) << 8) | (int (ord (substr ($hash_buf, 47, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 48, 1))) << 16) | (int (ord (substr ($hash_buf, 49, 1))) << 8) | (int (ord (substr ($hash_buf, 50, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 51, 1))) << 16) | (int (ord (substr ($hash_buf, 52, 1))) << 8) | (int (ord (substr ($hash_buf, 53, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 54, 1))) << 16) | (int (ord (substr ($hash_buf, 55, 1))) << 8) | (int (ord (substr ($hash_buf, 56, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 57, 1))) << 16) | (int (ord (substr ($hash_buf, 58, 1))) << 8) | (int (ord (substr ($hash_buf, 59, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 60, 1))) << 16) | (int (ord (substr ($hash_buf, 61, 1))) << 8) | (int (ord (substr ($hash_buf, 62, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 63, 1))) << 16) , 2); - - return $tmp_hash; -} - -sub aix_ssha1_pbkdf2 -{ - my $word_buf = shift; - my $salt_buf = shift; - my $iterations = shift; - - my $hasher = Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA1'); - - my $pbkdf2 = Crypt::PBKDF2->new ( - hasher => $hasher, - iterations => $iterations, - ); - - my $hash_buf = $pbkdf2->PBKDF2 ($salt_buf, $word_buf); - - my $tmp_hash = ""; - - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 0, 1))) << 16) | (int (ord (substr ($hash_buf, 1, 1))) << 8) | (int (ord (substr ($hash_buf, 2, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 3, 1))) << 16) | (int (ord (substr ($hash_buf, 4, 1))) << 8) | (int (ord (substr ($hash_buf, 5, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 6, 1))) << 16) | (int (ord (substr ($hash_buf, 7, 1))) << 8) | (int (ord (substr ($hash_buf, 8, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 9, 1))) << 16) | (int (ord (substr ($hash_buf, 10, 1))) << 8) | (int (ord (substr ($hash_buf, 11, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 12, 1))) << 16) | (int (ord (substr ($hash_buf, 13, 1))) << 8) | (int (ord (substr ($hash_buf, 14, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 15, 1))) << 16) | (int (ord (substr ($hash_buf, 16, 1))) << 8) | (int (ord (substr ($hash_buf, 17, 1)))), 4); - $tmp_hash .= to64 ((int (ord (substr ($hash_buf, 18, 1))) << 16) | (int (ord (substr ($hash_buf, 19, 1))) << 8) , 3); - - return $tmp_hash; -} - -sub sapb_transcode -{ - my $data_s = shift; - - my @data = split "", $data_s; - - my $transTable_s = - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\x3f\x40\x41\x50\x43\x44\x45\x4b\x47\x48\x4d\x4e\x54\x51\x53\x46" . - "\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x56\x55\x5c\x49\x5d\x4a" . - "\x42\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" . - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x58\x5b\x59\xff\x52" . - "\x4c\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" . - "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x57\x5e\x5a\x4f\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" . - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; - - my @transTable = unpack ("C256", $transTable_s); - - my @out; - - for (my $i = 0; $i < scalar @data; $i++) - { - $out[$i] = $transTable[int (ord ($data[$i]))]; - } - - return pack ("C*", @out); -} - -sub sapb_waldorf -{ - my $digest_s = shift; - - my $w_s = shift; - my $s_s = shift; - - my @w = unpack "C*", $w_s; - my @s = unpack "C*", $s_s; - - my $bcodeTable_s = - "\x14\x77\xf3\xd4\xbb\x71\x23\xd0\x03\xff\x47\x93\x55\xaa\x66\x91" . - "\xf2\x88\x6b\x99\xbf\xcb\x32\x1a\x19\xd9\xa7\x82\x22\x49\xa2\x51" . - "\xe2\xb7\x33\x71\x8b\x9f\x5d\x01\x44\x70\xae\x11\xef\x28\xf0\x0d"; - - my @bcodeTable = unpack ("C48", $bcodeTable_s); - - my @abcd = unpack ("C16", $digest_s); - - my $sum20 = ($abcd[0] & 3) - + ($abcd[1] & 3) - + ($abcd[2] & 3) - + ($abcd[3] & 3) - + ($abcd[5] & 3); - - $sum20 |= 0x20; - - my @out; - - for (my $i2 = 0; $i2 < $sum20; $i2++) - { - $out[$i2] = 0; - } - - for (my $i1 = 0, my $i2 = 0, my $i3 = 0; $i2 < $sum20; $i2++, $i2++) - { - if ($i1 < length $w_s) - { - if ($abcd[15 - $i1] & 1) - { - $out[$i2] = $bcodeTable[48 - 1 - $i1]; - - $i2++; - } - - $out[$i2] = $w[$i1]; - - $i1++; - $i2++; - } - - if ($i3 < length $s_s) - { - $out[$i2] = $s[$i3]; - - $i2++; - $i3++; - } - - $out[$i2] = $bcodeTable[$i2 - $i1 - $i3]; - } - - return substr (pack ("C*", @out), 0, $sum20); -} - -sub setup_des_key -{ - my @key_56 = split (//, shift); - - my $key = ""; - - $key = $key_56[0]; - - $key .= chr (((ord ($key_56[0]) << 7) | (ord ($key_56[1]) >> 1)) & 255); - $key .= chr (((ord ($key_56[1]) << 6) | (ord ($key_56[2]) >> 2)) & 255); - $key .= chr (((ord ($key_56[2]) << 5) | (ord ($key_56[3]) >> 3)) & 255); - $key .= chr (((ord ($key_56[3]) << 4) | (ord ($key_56[4]) >> 4)) & 255); - $key .= chr (((ord ($key_56[4]) << 3) | (ord ($key_56[5]) >> 5)) & 255); - $key .= chr (((ord ($key_56[5]) << 2) | (ord ($key_56[6]) >> 6)) & 255); - $key .= chr (( ord ($key_56[6]) << 1) & 255); - - return $key; -} - -sub randbytes -{ - my $len = shift; - - my @arr; - - for (my $i = 0; $i < $len; $i++) - { - my $c = get_random_chr (0, 255); - - push (@arr, $c); - } - - return join ("", @arr); -} - -sub get_random_netntlmv1_salt -{ - my $len_user = shift; - my $len_domain = shift; - - my $char; - my $type; - my $user = ""; - - for (my $i = 0; $i < $len_user; $i++) - { - $type = get_random_num (1, 3); - - if ($type == 1) - { - $char = get_random_chr (0x30, 0x39); - } - elsif ($type == 2) - { - $char = get_random_chr (0x41, 0x5A); - } - else - { - $char = get_random_chr (0x61, 0x7A); - } - - $user .= $char; - } - - my $domain = ""; - - for (my $i = 0; $i < $len_domain; $i++) - { - $type = get_random_num (1, 3); - - if ($type == 1) - { - $char = get_random_chr (0x30, 0x39); - } - elsif ($type == 2) - { - $char = get_random_chr (0x41, 0x5A); - } - else - { - $char = get_random_chr (0x61, 0x7A); - } - - $domain .= $char; - } - - my $c_challenge = randbytes (8); - my $s_challenge = randbytes (8); - - my $salt_buf = $user . "::" . $domain . ":" . unpack ("H*", $c_challenge) . unpack ("H*", $s_challenge); - - return $salt_buf; -} - -sub get_random_netntlmv2_salt -{ - my $len_user = shift; - my $len_domain = shift; - - my $char; - my $type; - my $user = ""; - - if ($len_user + $len_domain > 27) - { - if ($len_user > $len_domain) - { - $len_user = 27 - $len_domain; - } - else - { - $len_domain = 27 - $len_user; - } - } - - for (my $i = 0; $i < $len_user; $i++) - { - $type = get_random_num (1, 3); - - if ($type == 1) - { - $char = get_random_chr (0x30, 0x39); - } - elsif ($type == 2) - { - $char = get_random_chr (0x41, 0x5A); - } - else - { - $char = get_random_chr (0x61, 0x7A); - } - - $user .= $char; - } - - my $domain = ""; - - for (my $i = 0; $i < $len_domain; $i++) - { - $type = get_random_num (1, 3); - - if ($type == 1) - { - $char = get_random_chr (0x30, 0x39); - } - elsif ($type == 2) - { - $char = get_random_chr (0x41, 0x5A); - } - else - { - $char = get_random_chr (0x61, 0x7A); - } - - $domain .= $char; - } - - my $c_challenge = randbytes (8); - my $s_challenge = randbytes (8); - - my $temp = "\x01\x01" . - "\x00" x 6 . - randbytes (8) . - $c_challenge . - "\x00" x 4 . - randbytes (20 * rand () + 1) . - "\x00"; - - my $salt_buf = $user . "::" . $domain . ":" . unpack ("H*", $s_challenge) . unpack ("H*", $temp); - - return $salt_buf; -} - -sub get_random_ike_salt -{ - my $nr_buf = ""; - - for (my $i = 0; $i < 40; $i++) - { - $nr_buf .= get_random_chr (0, 0xff); - } - - my $msg_buf = ""; - - for (my $i = 0; $i < 440; $i++) - { - $msg_buf .= get_random_chr (0, 0xff); - } - - my $nr_buf_hex = unpack ("H*", $nr_buf); - my $msg_buf_hex = unpack ("H*", $msg_buf); - - my $salt_buf = sprintf ("%s:%s:%s:%s:%s:%s:%s:%s", substr ($msg_buf_hex, 0, 256), substr ($msg_buf_hex, 256, 256), substr ($msg_buf_hex, 512, 16), substr ($msg_buf_hex, 528, 16), substr ($msg_buf_hex, 544, 320), substr ($msg_buf_hex, 864, 16), substr ($nr_buf_hex, 0, 40), substr ($nr_buf_hex, 40, 40)); - - return $salt_buf; -} - -sub get_random_agilekeychain_salt -{ - my $salt_buf = ""; - - for (my $i = 0; $i < 8; $i++) - { - $salt_buf .= get_random_chr (0x0, 0xff); - } - - my $iv = ""; - - for (my $i = 0; $i < 16; $i++) - { - $iv .= get_random_chr (0x0, 0xff); - } - - my $prefix = "\x00" x 1008; - - my $ret = unpack ("H*", $salt_buf . $prefix . $iv); - - return $ret; -} - -sub get_random_cloudkeychain_salt -{ - my $salt_buf = ""; - - for (my $i = 0; $i < 16; $i++) - { - $salt_buf .= get_random_chr (0x0, 0xff); - } - - for (my $i = 0; $i < 304; $i++) - { - $salt_buf .= get_random_chr (0x0, 0xff); - } - - my $ret = unpack ("H*", $salt_buf); - - return $ret; -} - -sub get_random_kerberos5_salt -{ - my $custom_salt = shift; - - my $clear_data = randbytes (14) . - strftime ("%Y%m%d%H%M%S", localtime) . - randbytes (8); - - my $user = "user"; - my $realm = "realm"; - my $salt = "salt"; - - my $salt_buf = $user . "\$" . $realm . "\$" . $salt . "\$" . unpack ("H*", $custom_salt) . "\$" . unpack ("H*", $clear_data) . "\$"; - - return $salt_buf; -} - -sub get_random_kerberos5_tgs_salt -{ - my $nonce = randbytes (8); - - my $user = "user"; - my $realm = "realm"; - my $spn = "test/spn"; - - my $salt_buf = $user . "\$" . $realm . "\$" . $spn . "\$" . unpack ("H*", $nonce); - - return $salt_buf; -} - -sub get_random_kerberos5_as_rep_salt -{ - my $nonce = randbytes (8); - - my $user_principal_name = "user\@domain.com"; - my $salt_buf = $user_principal_name . ":" . unpack ("H*", $nonce); - - return $salt_buf; -} - -sub get_random_axcrypt_salt -{ - my $mysalt = randbytes (16); - - $mysalt = unpack ("H*", $mysalt); - - my $iteration = get_random_num (6, 100000); - - my $salt_buf = $iteration . '*' . $mysalt; - - return $salt_buf; -} - -sub get_random_keepass_salt -{ - my $version = get_random_num (1, 3); - - my $algorithm; - - my $iteration; - - my $final_random_seed; - - if ($version == 1) - { - $algorithm = get_random_num (0, 2); - - $iteration = get_random_num (50000, 100000); - - $final_random_seed = randbytes (16); - $final_random_seed = unpack ("H*", $final_random_seed); - } - elsif ($version == 2) - { - $algorithm = 0; - - $iteration = get_random_num (6000, 100000); - - $final_random_seed = randbytes (32); - $final_random_seed = unpack ("H*", $final_random_seed); - } - - my $transf_random_seed = randbytes (32); - $transf_random_seed = unpack ("H*", $transf_random_seed); - - my $enc_iv = randbytes (16); - $enc_iv = unpack ("H*", $enc_iv); - - my $contents_hash = randbytes (32); - $contents_hash = unpack ("H*", $contents_hash); - - my $inline_flag = 1; - - my $contents_len = get_random_num (128, 500); - - my $contents = randbytes ($contents_len); - - $contents_len += 16 - $contents_len % 16; - - $contents = unpack ("H*", $contents); - - my $salt_buf; - - my $is_keyfile = get_random_num (0, 2); - - my $keyfile_attributes = ""; - - if ($is_keyfile == 1) - { - $keyfile_attributes = $keyfile_attributes - . "1*64*" - . unpack ("H*", randbytes (32)); - } - - if ($version == 1) - { - $salt_buf = $version . '*' . - $iteration . '*' . - $algorithm . '*' . - $final_random_seed . '*' . - $transf_random_seed . '*' . - $enc_iv . '*' . - $contents_hash . '*' . - $inline_flag . '*' . - $contents_len . '*' . - $contents . '*' . - $keyfile_attributes; - } - elsif ($version == 2) - { - $contents = randbytes (32); - $contents = unpack ("H*", $contents); - - $salt_buf = $version . '*' . - $iteration . '*' . - $algorithm . '*' . - $final_random_seed . '*' . - $transf_random_seed . '*' . - $enc_iv . '*' . - $contents_hash . '*' . - $contents . '*' . - $keyfile_attributes; - } - - return $salt_buf; -} - -sub get_pstoken_salt -{ - my $pstoken_length = get_random_num (16, 256); - - ## not a valid pstoken but a better test - ## because of random length - - my $pstoken_const = randbytes ($pstoken_length); - - return unpack ("H*", $pstoken_const); -} - -sub get_random_md5chap_salt -{ - my $salt_buf = shift; - - my $salt = unpack ("H*", $salt_buf); - - $salt .= ":"; - - $salt .= unpack ("H*", randbytes (1)); - - return $salt; -} - -sub get_random_dnssec_salt -{ - my $salt_buf = ""; - - $salt_buf .= "."; - - for (my $i = 0; $i < 8; $i++) - { - $salt_buf .= get_random_chr (0x61, 0x7a); - } - - $salt_buf .= ".net"; - - $salt_buf .= ":"; - - for (my $i = 0; $i < 8; $i++) - { - $salt_buf .= get_random_chr (0x30, 0x39); - } - - return $salt_buf; -} - -sub get_random_dpapimk_salt -{ - my $salt_buf = ""; - - my $version = shift; - - my $context = get_random_num (1, 3); - - my $cipher_algo = ""; - - my $hash_algo = ""; - - my $iterations; - - my $SID = sprintf ('S-15-21-%d-%d-%d-%d', - get_random_num (400000000,490000000), - get_random_num (400000000,490000000), - get_random_num (400000000,490000000), - get_random_num (1000,1999)); - - my $cipher_len = 0; - - if ($version == 1) - { - $iterations = get_random_num (4000, 24000); - - $cipher_algo = "des3"; - - $hash_algo = "sha1"; - - $cipher_len = 208; - } - elsif ($version == 2) - { - $iterations = get_random_num (8000, 17000); - - $cipher_algo = "aes256"; - - $hash_algo = "sha512"; - - $cipher_len = 288; - } - - my $iv = randbytes (16); - $iv = unpack ("H*", $iv); - - $salt_buf = $version . '*' . - $context . '*' . - $SID . '*' . - $cipher_algo . '*' . - $hash_algo . '*' . - $iterations . '*' . - $iv . '*' . - $cipher_len . '*'; - - return $salt_buf; -} - -sub get_random_jwt_salt -{ - my @hashes = - ( - "HS256", - #"HS384", #this is support in hashcat, but commented out here to prevent mixed hash output files in single mode - #"HS512", #this is support in hashcat, but commented out here to prevent mixed hash output files in single mode - #"RS256", #not supported by hashcat - #"RS384", - #"RS512", - #"PS256", - #"PS384", - #"PS512", - #"ES256", - #"ES384", - #"ES512", - ); - - my $rnd = get_random_num (0, scalar @hashes); - - my $hash = $hashes[$rnd]; - - my $header = - { - "alg" => $hash - }; - - my $random_key = get_random_num (1, 100000000); - my $random_val = get_random_num (1, 100000000); - - my $payload = - { - $random_key => $random_val - }; - - my $header_json = encode_json ($header); - my $payload_json = encode_json ($payload); - - my $header_base64 = encode_base64url ($header_json, ""); - my $payload_base64 = encode_base64url ($payload_json, ""); - - return $header_base64 . "." . $payload_base64; -} - -sub md5bit -{ - my $digest = shift; - my $bit = shift; - - $bit %= 128; - - my $byte_off = int ($bit / 8); - my $bit_off = int ($bit % 8); - - my $char = substr ($digest, $byte_off, 1); - my $num = ord ($char); - - return (($num & (1 << $bit_off)) ? 1 : 0); -} - -sub sun_md5 -{ - my $pw = shift; - my $salt = shift; - my $iter = shift; - - my $constant_phrase = - "To be, or not to be,--that is the question:--\n" . - "Whether 'tis nobler in the mind to suffer\n" . - "The slings and arrows of outrageous fortune\n" . - "Or to take arms against a sea of troubles,\n" . - "And by opposing end them?--To die,--to sleep,--\n" . - "No more; and by a sleep to say we end\n" . - "The heartache, and the thousand natural shocks\n" . - "That flesh is heir to,--'tis a consummation\n" . - "Devoutly to be wish'd. To die,--to sleep;--\n" . - "To sleep! perchance to dream:--ay, there's the rub;\n" . - "For in that sleep of death what dreams may come,\n" . - "When we have shuffled off this mortal coil,\n" . - "Must give us pause: there's the respect\n" . - "That makes calamity of so long life;\n" . - "For who would bear the whips and scorns of time,\n" . - "The oppressor's wrong, the proud man's contumely,\n" . - "The pangs of despis'd love, the law's delay,\n" . - "The insolence of office, and the spurns\n" . - "That patient merit of the unworthy takes,\n" . - "When he himself might his quietus make\n" . - "With a bare bodkin? who would these fardels bear,\n" . - "To grunt and sweat under a weary life,\n" . - "But that the dread of something after death,--\n" . - "The undiscover'd country, from whose bourn\n" . - "No traveller returns,--puzzles the will,\n" . - "And makes us rather bear those ills we have\n" . - "Than fly to others that we know not of?\n" . - "Thus conscience does make cowards of us all;\n" . - "And thus the native hue of resolution\n" . - "Is sicklied o'er with the pale cast of thought;\n" . - "And enterprises of great pith and moment,\n" . - "With this regard, their currents turn awry,\n" . - "And lose the name of action.--Soft you now!\n" . - "The fair Ophelia!--Nymph, in thy orisons\n" . - "Be all my sins remember'd.\n\x00"; - - my $constant_len = length ($constant_phrase); - - my $hash_buf = md5 ($pw . $salt); - - my $W; - - my $to_hash; - - for (my $round = 0; $round < $iter; $round++) - { - my $shift_a = md5bit ($hash_buf, $round + 0); - my $shift_b = md5bit ($hash_buf, $round + 64); - - my @shift_4; - my @shift_7; - - for (my $k = 0; $k < 16; $k++) - { - my $s7shift = ord (substr ($hash_buf, $k, 1)) % 8; - - my $l = ($k + 3) % 16; - - my $num = ord (substr ($hash_buf, $l, 1)); - - $shift_4[$k] = $num % 5; - - $shift_7[$k] = ($num >> $s7shift) & 1; - } - - my @indirect_4; - - for (my $k = 0; $k < 16; $k++) - { - $indirect_4[$k] = (ord (substr ($hash_buf, $k, 1)) >> $shift_4[$k]) & 0xf; - } - - my @indirect_7; - - for (my $k = 0; $k < 16; $k++) - { - $indirect_7[$k] = (ord (substr ($hash_buf, $indirect_4[$k], 1)) >> $shift_7[$k]) & 0x7f; - } - - my $indirect_a = 0; - my $indirect_b = 0; - - for (my $k = 0; $k < 8; $k++) - { - $indirect_a |= md5bit ($hash_buf, $indirect_7[$k + 0]) << $k; - - $indirect_b |= md5bit ($hash_buf, $indirect_7[$k + 8]) << $k; - } - - $indirect_a = ($indirect_a >> $shift_a) & 0x7f; - $indirect_b = ($indirect_b >> $shift_b) & 0x7f; - - my $bit_a = md5bit ($hash_buf, $indirect_a); - my $bit_b = md5bit ($hash_buf, $indirect_b); - - $W = $hash_buf; - - my $pos = 16; - - my $total = $pos; - - $to_hash = ""; - - if ($bit_a ^ $bit_b) - { - substr ($W, 16, 48) = substr ($constant_phrase, 0, 48); - - $total += 48; - - $to_hash .= substr ($W, 0, 64); - - my $constant_off; - - for ($constant_off = 48; $constant_off < $constant_len - 64; $constant_off += 64) - { - substr ($W, 0, 64) = substr ($constant_phrase, $constant_off, 64); - - $total += 64; - - $to_hash .= substr ($W, 0, 64); - } - - $pos = $constant_len - $constant_off; - - $total += $pos; - - substr ($W, 0, $pos) = substr ($constant_phrase, $constant_off, $pos); - } - - my $a_len = 0; - - my @a_buf; - $a_buf[0] = 0; - $a_buf[1] = 0; - $a_buf[2] = 0; - $a_buf[3] = 0; - - my $tmp = $round; - - do - { - my $round_div = int ($tmp / 10); - my $round_mod = int ($tmp % 10); - - $tmp = $round_div; - - $a_buf[int ($a_len / 4)] = (($round_mod + 0x30) | ($a_buf[int ($a_len / 4)] << 8)); - - $a_len++; - - } while ($tmp); - - my $tmp_str = ""; - - my $g; - - for ($g = 0; $g < $a_len; $g++) - { - my $remainder = $a_buf[$g]; - my $factor = 7; - my $started = 1; - - my $sub; - - while ($remainder > 0) - { - $sub = $remainder >> (8 * $factor); - - if ($started != 1 || $sub > 0) - { - $started = 0; - - $tmp_str = chr ($sub) . $tmp_str; - - $remainder -= ($sub << (8 * $factor)); - } - - $factor--; - } - - } - - substr ($W, $pos, $a_len) = $tmp_str; - - $pos += $a_len; - - $total += $a_len; - - $to_hash .= substr ($W, 0, $pos); - - $to_hash = substr ($to_hash, 0, $total); - - $hash_buf = md5 ($to_hash); - } - - my $passwd = ""; - - $passwd .= to64 ((int (ord (substr ($hash_buf, 0, 1))) << 16) | (int (ord (substr ($hash_buf, 6, 1))) << 8) | (int (ord (substr ($hash_buf, 12, 1)))), 4); - $passwd .= to64 ((int (ord (substr ($hash_buf, 1, 1))) << 16) | (int (ord (substr ($hash_buf, 7, 1))) << 8) | (int (ord (substr ($hash_buf, 13, 1)))), 4); - $passwd .= to64 ((int (ord (substr ($hash_buf, 2, 1))) << 16) | (int (ord (substr ($hash_buf, 8, 1))) << 8) | (int (ord (substr ($hash_buf, 14, 1)))), 4); - $passwd .= to64 ((int (ord (substr ($hash_buf, 3, 1))) << 16) | (int (ord (substr ($hash_buf, 9, 1))) << 8) | (int (ord (substr ($hash_buf, 15, 1)))), 4); - $passwd .= to64 ((int (ord (substr ($hash_buf, 4, 1))) << 16) | (int (ord (substr ($hash_buf, 10, 1))) << 8) | (int (ord (substr ($hash_buf, 5, 1)))), 4); - $passwd .= to64 ((int (ord (substr ($hash_buf, 11, 1)))), 2); - - return $passwd; -} - -sub usage_die -{ - die ("usage: $0 single|passthrough| [mode] [len]\n" . - " or\n" . - " $0 verify [mode] [hashfile] [cracks] [outfile]\n"); -} - -sub pad16 -{ - my $block_ref = shift; - - my $offset = shift; - - my $value = 16 - $offset; - - for (my $i = $offset; $i < 16; $i++) - { - push @{$block_ref}, $value; - } -} - -sub lotus_mix -{ - my $in_ref = shift; - - my $p = 0; - - for (my $i = 0; $i < 18; $i++) - { - for (my $j = 0; $j < 48; $j++) - { - $p = ($p + 48 - $j) & 0xff; - - my $c = $LOTUS_MAGIC_TABLE->[$p]; - - $p = $in_ref->[$j] ^ $c; - - $in_ref->[$j] = $p; - } - } -} - -sub lotus_transform_password -{ - my $in_ref = shift; - my $out_ref = shift; - - my $t = $out_ref->[15]; - - for (my $i = 0; $i < 16; $i++) - { - $t ^= $in_ref->[$i]; - - my $c = $LOTUS_MAGIC_TABLE->[$t]; - - $out_ref->[$i] ^= $c; - - $t = $out_ref->[$i]; - } -} - -sub mdtransform_norecalc -{ - my $state_ref = shift; - my $block_ref = shift; - - my @x; - - push (@x, @{$state_ref}); - push (@x, @{$block_ref}); - - for (my $i = 0; $i < 16; $i++) - { - push (@x, $x[0 + $i] ^ $x[16 + $i]); - } - - lotus_mix (\@x); - - for (my $i = 0; $i < 16; $i++) - { - $state_ref->[$i] = $x[$i]; - } -} - -sub mdtransform -{ - my $state_ref = shift; - my $checksum_ref = shift; - my $block_ref = shift; - - mdtransform_norecalc ($state_ref, $block_ref); - - lotus_transform_password ($block_ref, $checksum_ref); -} - -sub domino_big_md -{ - my $saved_key_ref = shift; - - my $size = shift; - - @{$saved_key_ref} = splice (@{$saved_key_ref}, 0, $size); - - my @state = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - my @checksum; - - my $curpos; - - for ($curpos = 0; $curpos + 16 < $size; $curpos += 16) - { - my @block = splice (@{$saved_key_ref}, 0, 16); - - mdtransform (\@state, \@checksum, \@block); - } - - my $left = $size - $curpos; - - my @block = splice (@{$saved_key_ref}, 0, 16); - - pad16 (\@block, $left); - - mdtransform (\@state, \@checksum, \@block); - - mdtransform_norecalc (\@state, \@checksum); - - return @state; -} - -sub pdf_compute_encryption_key -{ - my $word_buf = shift; - my $padding = shift; - my $id = shift; - my $u = shift; - my $o = shift; - my $P = shift; - my $V = shift; - my $R = shift; - my $enc = shift; - - ## start - - my $data; - - $data .= $word_buf; - - $data .= substr ($padding, 0, 32 - length $word_buf); - - $data .= pack ("H*", $o); - - $data .= pack ("I", $P); - - $data .= pack ("H*", $id); - - if ($R >= 4) - { - if (!$enc) - { - $data .= pack ("I", -1); - } - } - - my $res = md5 ($data); - - if ($R >= 3) - { - for (my $i = 0; $i < 50; $i++) - { - $res = md5 ($res); - } - } - - return $res; -} - -sub gen_random_wpa_eapol -{ - my $keyver = shift; - my $snonce = shift; - - my $ret = ""; - - # version - - my $version = 1; # 802.1X-2001 - - $ret .= pack ("C*", $version); - - my $type = 3; # means that this EAPOL frame is used to transfer key information - - $ret .= pack ("C*", $type); - - my $length; # length of remaining data - - if ($keyver == 1) - { - $length = 119; - } - else - { - $length = 117; - } - - $ret .= pack ("n*", $length); - - my $descriptor_type; - - if ($keyver == 1) - { - $descriptor_type = 254; # EAPOL WPA key - } - else - { - $descriptor_type = 1; # EAPOL RSN key - } - - $ret .= pack ("C*", $descriptor_type); - - # key_info is a bit vector: - # generated from these 13 bits: encrypted key data, request, error, secure, key mic, key ack, install, key index (2), key type, key descriptor (3) - - my $key_info = 0; - - $key_info |= 1 << 8; # set key MIC - $key_info |= 1 << 3; # set if it is a pairwise key - - if ($keyver == 1) - { - $key_info |= 1 << 0; # RC4 Cipher, HMAC-MD5 MIC - } - else - { - $key_info |= 1 << 1; # AES Cipher, HMAC-SHA1 MIC - } - - $ret .= pack ("n*", $key_info); - - my $key_length; - - if ($keyver == 1) - { - $key_length = 32; - } - else - { - $key_length = 0; - } - - $ret .= pack ("n*", $key_length); - - my $replay_counter = 1; - - $ret .= pack ("Q>*", $replay_counter); - - $ret .= $snonce; - - my $key_iv = "\x00" x 16; - - $ret .= $key_iv; - - my $key_rsc = "\x00" x 8; - - $ret .= $key_rsc; - - my $key_id = "\x00" x 8; - - $ret .= $key_id; - - my $key_mic = "\x00" x 16; - - $ret .= $key_mic; - - my $key_data_len; - - if ($keyver == 1) - { - $key_data_len = 24; # length of the key_data (== WPA info) - } - else - { - $key_data_len = 22; # length of the key_data (== RSN info) - } - - $ret .= pack ("n*", $key_data_len); - - my $key_data = ""; - - if ($keyver == 1) - { - # wpa info - - my $wpa_info = ""; - - my $vendor_specific_data = ""; - - my $tag_number = 221; # means it is a vendor specific tag - - $vendor_specific_data .= pack ("C*", $tag_number); - - my $tag_len = 22; # length of the remaining "tag data" - - $vendor_specific_data .= pack ("C*", $tag_len); - - my $vendor_specific_oui = pack ("H*", "0050f2"); # microsoft - - $vendor_specific_data .= $vendor_specific_oui; - - my $vendor_specific_oui_type = 1; # WPA Information Element - - $vendor_specific_data .= pack ("C*", $vendor_specific_oui_type); - - my $vendor_specific_wpa_version = 1; - - $vendor_specific_data .= pack ("v*", $vendor_specific_wpa_version); - - # multicast - - my $vendor_specific_multicast_oui = pack ("H*", "0050f2"); - - $vendor_specific_data .= $vendor_specific_multicast_oui; - - my $vendor_specific_multicast_type = 2; # TKIP - - $vendor_specific_data .= pack ("C*", $vendor_specific_multicast_type); - - # unicast - - my $vendor_specific_unicast_count = 1; - - $vendor_specific_data .= pack ("v*", $vendor_specific_unicast_count); - - my $vendor_specific_unicast_oui = pack ("H*", "0050f2"); - - $vendor_specific_data .= $vendor_specific_unicast_oui; - - my $vendor_specific_unicast_type = 2; # TKIP - - $vendor_specific_data .= pack ("C*", $vendor_specific_unicast_type); - - # Auth Key Management (AKM) - - my $auth_key_management_count = 1; - - $vendor_specific_data .= pack ("v*", $auth_key_management_count); - - my $auth_key_management_oui = pack ("H*", "0050f2"); - - $vendor_specific_data .= $auth_key_management_oui; - - my $auth_key_management_type = 2; # Pre-Shared Key (PSK) - - $vendor_specific_data .= pack ("C*", $auth_key_management_type); - - $wpa_info = $vendor_specific_data; - - $key_data = $wpa_info; - } - else - { - # rsn info - - my $rsn_info = ""; - - my $tag_number = 48; # RSN info - - $rsn_info .= pack ("C*", $tag_number); - - my $tag_len = 20; # length of the remaining "tag_data" - - $rsn_info .= pack ("C*", $tag_len); - - my $rsn_version = 1; - - $rsn_info .= pack ("v*", $rsn_version); - - # group cipher suite - - my $group_cipher_suite_oui = pack ("H*", "000fac"); # Ieee8021 - - $rsn_info .= $group_cipher_suite_oui; - - my $group_cipher_suite_type = 4; # AES (CCM) - - $rsn_info .= pack ("C*", $group_cipher_suite_type); - - # pairwise cipher suite - - my $pairwise_cipher_suite_count = 1; - - $rsn_info .= pack ("v*", $pairwise_cipher_suite_count); - - my $pairwise_cipher_suite_oui = pack ("H*", "000fac"); # Ieee8021 - - $rsn_info .= $pairwise_cipher_suite_oui; - - my $pairwise_cipher_suite_type = 4; # AES (CCM) - - $rsn_info .= pack ("C*", $pairwise_cipher_suite_type); - - # Auth Key Management (AKM) - - my $auth_key_management_count = 1; - - $rsn_info .= pack ("v*", $auth_key_management_count); - - my $auth_key_management_oui = pack ("H*", "000fac"); # Ieee8021 - - $rsn_info .= $auth_key_management_oui; - - my $auth_key_management_type = 2; # Pre-Shared Key (PSK) - - $rsn_info .= pack ("C*", $auth_key_management_type); - - # RSN Capabilities - - # bit vector of these 9 bits: peerkey enabled, management frame protection (MFP) capable, MFP required, - # RSN GTKSA Capabilities (2), RSN PTKSA Capabilities (2), no pairwise Capabilities, Pre-Auth Capabilities - - my $rsn_capabilities = pack ("H*", "0000"); - - $rsn_info .= $rsn_capabilities; - - $key_data = $rsn_info; - } - - $ret .= $key_data; - - return $ret; -} - -sub wpa_prf_512 -{ - my $keyver = shift; - my $pmk = shift; - my $stmac = shift; - my $bssid = shift; - my $snonce = shift; - my $anonce = shift; - - my $data = "Pairwise key expansion"; - - if (($keyver == 1) || ($keyver == 2)) - { - $data .= "\x00"; - } - - # - # Min(AA, SPA) || Max(AA, SPA) - # - - # compare if greater: Min()/Max() on the MACs (6 bytes) - - if (memcmp ($stmac, $bssid, 6) < 0) - { - $data .= $stmac; - $data .= $bssid; - } - else - { - $data .= $bssid; - $data .= $stmac; - } - - # - # Min(ANonce,SNonce) || Max(ANonce,SNonce) - # - - # compare if greater: Min()/Max() on the nonces (32 bytes) - - if (memcmp ($snonce, $anonce, 32) < 0) - { - $data .= $snonce; - $data .= $anonce; - } - else - { - $data .= $anonce; - $data .= $snonce; - } - - my $prf_buf; - - if (($keyver == 1) || ($keyver == 2)) - { - $data .= "\x00"; - - $prf_buf = hmac ($data, $pmk, \&sha1); - } - else - { - my $data3 = "\x01\x00" . $data . "\x80\x01"; - - $prf_buf = hmac ($data3, $pmk, \&sha256); - } - - $prf_buf = substr ($prf_buf, 0, 16); - - return $prf_buf; -} - -sub itunes_aes_wrap -{ - my $key = shift; - my $A = shift; - my $R_l = shift; - - my $k = scalar (@$R_l); - my $n = $k + 1; - - my @R; - - for (my $i = 0; $i < $n; $i++) - { - $R[$i] = @$R_l[$i]; - } - - # AES mode ECB - - my $m = Crypt::Mode::ECB->new ('AES', 0); - - # main wrap loop - - my ($i, $j, $a); - - for ($j = 0; $j <= 5; $j++) - { - for ($i = 1, $a = 0; $i <= $k; $i++, $a++) - { - my $input; - - $input = pack ("Q>", $A); - $input .= pack ("Q>", $R[$a]); - - my $t = $m->encrypt ($input, $key); - - $A = unpack ("Q>", substr ($t, 0, 8)); - $A ^= $k * $j + $i; - - $R[$a] = unpack ("Q>", substr ($t, 8, 8)); - } - } - - my $WPKY = pack ("Q>", $A); - - for (my $i = 0; $i < $k; $i++) - { - $WPKY .= pack ("Q>", $R[$i]); - } - - return $WPKY; -} - -sub itunes_aes_unwrap -{ - my $key = shift; - my $WPKY = shift; - - my @B; - - for (my $i = 0; $i < length ($WPKY) / 8; $i++) - { - $B[$i] = unpack ("Q>", substr ($WPKY, $i * 8, 8)); - } - - my $n = scalar (@B); - my $k = $n - 1; - - my @R; - - for (my $i = 0; $i < $k; $i++) - { - $R[$i] = $B[$i + 1]; - } - - # AES mode ECB - - my $m = Crypt::Mode::ECB->new ('AES', 0); - - # main unwrap loop - - my $A = $B[0]; - - my ($i, $j, $a); - - for ($j = 5; $j >= 0; $j--) - { - for ($i = $k, $a = $k - 1; $i > 0; $i--, $a--) - { - my $input; - - $input = pack ("Q>", $A ^ ($k * $j + $i)); - $input .= pack ("Q>", $R[$a]); - - my $t = $m->decrypt ($input, $key); - - $A = unpack ("Q>", substr ($t, 0, 8)); - $R[$a] = unpack ("Q>", substr ($t, 8, 8)); - } - } - - return ($A, \@R); -} - -sub memcmp -{ - my $str1 = shift; - my $str2 = shift; - my $len = shift; - - my $len_str1 = length ($str1); - my $len_str2 = length ($str2); - - if (($len > $len_str1) || ($len > $len_str2)) - { - print "ERROR: memcmp () lengths wrong"; - - exit (1); - } - - for (my $i = 0; $i < $len; $i++) - { - my $c_1 = ord (substr ($str1, $i, 1)); - my $c_2 = ord (substr ($str2, $i, 1)); - - return -1 if ($c_1 < $c_2); - return 1 if ($c_1 > $c_2); - } - - return 0; -}