#!/usr/bin/env perl ## ## Author......: See docs/credits.txt ## License.....: MIT ## ## install help: ## ## cpan install Authen::Passphrase::LANManager Authen::Passphrase::MySQL323 Authen::Passphrase::NTHash Authen::Passphrase::PHPass Crypt::CBC Crypt::DES Crypt::Digest::RIPEMD160 Crypt::Digest::Whirlpool Crypt::ECB Crypt::Eksblowfish::Bcrypt Crypt::Mode::ECB Crypt::MySQL Crypt::OpenSSH::ChachaPoly Crypt::PBKDF2 Crypt::RC4 Crypt::Rijndael Crypt::ScryptKDF Crypt::Skip32 Crypt::Twofish Crypt::UnixCrypt_XS Digest::BLAKE2 Digest::CMAC Digest::CRC Digest::GOST Digest::HMAC Digest::HMAC_MD5 Digest::Keccak Digest::MD4 Digest::MD5 Digest::Perl::MD5 Digest::SHA Digest::SipHash JSON Net::DNS::RR::NSEC3 Net::DNS::SEC Convert::EBCDIC ## use strict; use warnings; 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::HMAC qw (hmac hmac_hex); use Digest::Keccak qw (keccak_256_hex); use Digest::BLAKE2 qw (blake2b_hex); use Crypt::MySQL qw (password41); use Digest::GOST qw (gost gost_hex); use Digest::HMAC_MD5 qw (hmac_md5); use Digest::CRC qw (crc32); use Digest::CMAC; use Crypt::PBKDF2; use Crypt::DES; use Crypt::ECB qw (encrypt); use Crypt::CBC; use Crypt::Eksblowfish::Bcrypt qw (bcrypt en_base64); use Crypt::Digest::RIPEMD160 qw (ripemd160_hex); use Crypt::Digest::Whirlpool qw (whirlpool_hex); use Crypt::RC4; use Crypt::ScryptKDF qw (scrypt_hash scrypt_raw scrypt_b64); use Crypt::Rijndael; use Crypt::Twofish; use Crypt::Mode::ECB; use Crypt::UnixCrypt_XS qw (crypt_rounds fold_password base64_to_int24 block_to_base64 int24_to_base64); use Crypt::Skip32; use Crypt::OpenSSH::ChachaPoly; use JSON; use MIME::Base64 qw (encode_base64 decode_base64 encode_base64url decode_base64url); use Authen::Passphrase::NTHash; use Authen::Passphrase::MySQL323; use Authen::Passphrase::PHPass; use Authen::Passphrase::LANManager; use Encode; use POSIX qw (strftime ceil); use Net::DNS::SEC; use Net::DNS::RR::NSEC3; use Convert::EBCDIC qw (ascii2ebcdic); use Digest::SipHash qw/siphash/; use Text::Iconv; use Digest::Perl::MD5; my $hashcat = "./hashcat"; my $MAX_LEN = 55; 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, 5000, 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, 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, 99999); my %is_utf16le = map { $_ => 1 } qw (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 %less_fifteen = map { $_ => 1 } qw (500 1600 1800 3200 6300 7400 10500 10700); my %allow_long_salt = map { $_ => 1 } qw (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); 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); } 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 ($mode == 0 || $mode == 100 || $mode == 101 || $mode == 133 || $mode == 200 || $mode == 300 || $mode == 600 || $mode == 900 || $mode == 1000 || $mode == 1300 || $mode == 1400 || $mode == 1700 || $mode == 2400 || $mode == 2600 || $mode == 3000 || $mode == 3500 || $mode == 4300 || $mode == 4400 || $mode == 4500 || $mode == 4600 || $mode == 4700 || $mode == 5000 || $mode == 5100 || $mode == 5700 || $mode == 6000 || $mode == 6100 || $mode == 6900 || $mode == 8600 || $mode == 9900 || $mode == 10800 || $mode == 11500 || $mode == 16000 || $mode == 16400 || $mode == 99999) { 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 ($mode == 10 || $mode == 11 || $mode == 12 || $mode == 20 || $mode == 21 || $mode == 22 || $mode == 23 || $mode == 30 || $mode == 40 || $mode == 50 || $mode == 60 || $mode == 110 || $mode == 112 || $mode == 120 || $mode == 121 || $mode == 130 || $mode == 140 || $mode == 150 || $mode == 160 || $mode == 1100 || $mode == 1410 || $mode == 1420 || $mode == 1430 || $mode == 1440 || $mode == 1450 || $mode == 1460 || $mode == 1710 || $mode == 1720 || $mode == 1730 || $mode == 1740 || $mode == 1750 || $mode == 1760 || $mode == 2410 || $mode == 2611 || $mode == 2711 || $mode == 2811 || $mode == 3100 || $mode == 3610 || $mode == 3710 || $mode == 3720 || $mode == 3800 || $mode == 3910 || $mode == 4010 || $mode == 4110 || $mode == 4210 || $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/WPA2 elsif ($mode == 2500) { print "ERROR: verify currently not supported for WPA/WPA2 (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}))); } 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); } 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; if ($mode == 0 || $mode == 100 || $mode == 101 || $mode == 133 || $mode == 200 || $mode == 300 || $mode == 600 || $mode == 900 || $mode == 1000 || $mode == 1300 || $mode == 1400 || $mode == 1700 || $mode == 2400 || $mode == 2600 || $mode == 3500 || $mode == 4300 || $mode == 4400 || $mode == 4500 || $mode == 4600 || $mode == 4700 || $mode == 5000 || $mode == 5100 || $mode == 6000 || $mode == 6100 || $mode == 6900 || $mode == 5700 || $mode == 9900 || $mode == 10800 || $mode == 11500 || $mode == 13300 || $mode == 16400 || $mode == 99999) { $tmp_hash = gen_hash ($mode, $word_buf, ""); } elsif ($mode == 10 || $mode == 20 || $mode == 23 || $mode == 30 || $mode == 40 || $mode == 50 || $mode == 60 || $mode == 110 || $mode == 120 || $mode == 130 || $mode == 140 || $mode == 150 || $mode == 160 || $mode == 1410 || $mode == 1411 || $mode == 1420 || $mode == 1430 || $mode == 1440 || $mode == 1450 || $mode == 1460 || $mode == 1710 || $mode == 1711 || $mode == 1720 || $mode == 1730 || $mode == 1740 || $mode == 1750 || $mode == 1760 || $mode == 3610 || $mode == 3710 || $mode == 3711 || $mode == 3720 || $mode == 3800 || $mode == 3910 || $mode == 4010 || $mode == 4110 || $mode == 4210 || $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)); } 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 ($mode == 0 || $mode == 100 || $mode == 101 || $mode == 133 || $mode == 200 || $mode == 300 || $mode == 600 || $mode == 900 || $mode == 1000 || $mode == 1300 || $mode == 1400 || $mode == 1700 || $mode == 2600 || $mode == 3500 || $mode == 4300 || $mode == 4400 || $mode == 4500 || $mode == 4600 || $mode == 4700 || $mode == 5000 || $mode == 5100 || $mode == 5300 || $mode == 5400 || $mode == 6000 || $mode == 6100 || $mode == 6600 || $mode == 6900 || $mode == 5700 || $mode == 8200 || $mode == 8300 || $mode == 9900 || $mode == 10800 || $mode == 11500 || $mode == 13300 || $mode == 16400 || $mode == 99999) { for (my $i = 1; $i < 32; $i++) { if ($len != 0) { rnd ($mode, $len, 0); } else { rnd ($mode, $i, 0); } } } elsif ($mode == 10 || $mode == 20 || $mode == 23 || $mode == 30 || $mode == 40 || $mode == 50 || $mode == 60 || $mode == 110 || $mode == 120 || $mode == 121 || $mode == 130 || $mode == 140 || $mode == 150 || $mode == 160 || $mode == 1410 || $mode == 1411 || $mode == 1420 || $mode == 1430 || $mode == 1440 || $mode == 1450 || $mode == 1460 || $mode == 1710 || $mode == 1711 || $mode == 1720 || $mode == 1730 || $mode == 1740 || $mode == 1750 || $mode == 1760 || $mode == 3610 || $mode == 3710 || $mode == 3711 || $mode == 3720 || $mode == 3910 || $mode == 4010 || $mode == 4110 || $mode == 4210 || $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); } } } } } exit; 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 == 5000) { $hash_buf = keccak_256_hex ($word_buf); $tmp_hash = sprintf ("%s", $hash_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 == 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 == 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_bin = $cipher->decrypt ($encrypted_bin); my $test = unpack ("H*", $test_bin); if ($test =~ /^[0-9a-f]+$/) { $plain_bin = $test_bin; } 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 == 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); } 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_utf16le{$mode}) { if (! $allow_long_salt{$mode}) { $word_len = min ($word_len, int ($max / 2) - $salt_len); } else { $word_len = min ($word_len, int ($max / 2)); } } elsif ($less_fifteen{$mode}) { $word_len = min ($word_len, 15); } else { if (! $allow_long_salt{$mode}) { $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 (); } 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_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; }