mirror of
https://github.com/hashcat/hashcat.git
synced 2024-11-30 03:48:17 +00:00
Merge pull request #1836 from Naufragous/preprocess-hashlist
Add module_preprocess_hashlist hook for tests
This commit is contained in:
commit
9f3601c3dc
@ -24,7 +24,6 @@ is_in_array ($TYPE, $TYPES) or usage_exit ();
|
|||||||
|
|
||||||
is_whole ($MODE) or die "Mode must be a number\n";
|
is_whole ($MODE) or die "Mode must be a number\n";
|
||||||
|
|
||||||
my $module = sprintf ("m%05d.pm", $MODE);
|
|
||||||
my $MODULE_FILE = sprintf ("m%05d.pm", $MODE);
|
my $MODULE_FILE = sprintf ("m%05d.pm", $MODE);
|
||||||
|
|
||||||
eval { require $MODULE_FILE } or die "Could not load test module: $MODULE_FILE\n$@";
|
eval { require $MODULE_FILE } or die "Could not load test module: $MODULE_FILE\n$@";
|
||||||
@ -98,18 +97,24 @@ sub verify
|
|||||||
|
|
||||||
open (IN, '<', $hashes_file) or die "$hashes_file: $!\n";
|
open (IN, '<', $hashes_file) or die "$hashes_file: $!\n";
|
||||||
|
|
||||||
my $hashlist;
|
my @hashlist;
|
||||||
|
|
||||||
while (my $line = <IN>)
|
while (my $line = <IN>)
|
||||||
{
|
{
|
||||||
$line =~ s/\n$//;
|
$line =~ s/\n$//;
|
||||||
$line =~ s/\r$//;
|
$line =~ s/\r$//;
|
||||||
|
|
||||||
push (@{$hashlist}, $line);
|
push (@hashlist, $line);
|
||||||
}
|
}
|
||||||
|
|
||||||
close (IN);
|
close (IN);
|
||||||
|
|
||||||
|
# resolve hash ambiguity if necessary
|
||||||
|
if (exists &{module_preprocess_hashlist})
|
||||||
|
{
|
||||||
|
module_preprocess_hashlist (\@hashlist);
|
||||||
|
}
|
||||||
|
|
||||||
open (IN, '<', $cracks_file) or die "$cracks_file: $!\n";
|
open (IN, '<', $cracks_file) or die "$cracks_file: $!\n";
|
||||||
open (OUT, '>', $out_file ) or die "$out_file: $!\n";
|
open (OUT, '>', $out_file ) or die "$out_file: $!\n";
|
||||||
|
|
||||||
@ -124,7 +129,7 @@ sub verify
|
|||||||
next unless defined $hash;
|
next unless defined $hash;
|
||||||
|
|
||||||
# possible if the hash is in cracksfile, but not in hashfile
|
# possible if the hash is in cracksfile, but not in hashfile
|
||||||
next unless is_in_array ($hash, $hashlist);
|
next unless is_in_array ($hash, \@hashlist);
|
||||||
|
|
||||||
print OUT "$line\n";
|
print OUT "$line\n";
|
||||||
}
|
}
|
||||||
@ -256,9 +261,11 @@ sub random_numeric_string
|
|||||||
|
|
||||||
return if ! is_count ($count);
|
return if ! is_count ($count);
|
||||||
|
|
||||||
|
my @chars = ('0'..'9');
|
||||||
|
|
||||||
my $string;
|
my $string;
|
||||||
|
|
||||||
$string .= sprintf ("%d", rand 10) for (1 .. $count);
|
$string .= $chars[rand @chars] for (1 .. $count);
|
||||||
|
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,11 @@ During `verify` tests the `module_verify_hash` function must parse the hash:pass
|
|||||||
|
|
||||||
**Important**: You have to call `pack_if_HEX_notation` as soon as you have parsed the password, or your tests will fail on passwords in the `$HEX[...]` format.
|
**Important**: You have to call `pack_if_HEX_notation` as soon as you have parsed the password, or your tests will fail on passwords in the `$HEX[...]` format.
|
||||||
|
|
||||||
|
If the algorithm has ambiguous hashes (e.g. partial case-insensetivity), the test module can provide an optional function `module_preprocess_hashlist`. It recieves a reference to the hashlist array and can unify the hashes in a way that guarantees the match with the output of `module_verify_hash`.
|
||||||
|
|
||||||
#### Examples ####
|
#### Examples ####
|
||||||
|
|
||||||
* For the most basic test modules, see [m00000.pm](m00000.pm) and [m00100.pm](m00100.pm)
|
* For the most basic test modules, see [m00000.pm](m00000.pm) and [m00100.pm](m00100.pm)
|
||||||
* For the basic salted hash tests, see [m00110.pm](m00110.pm) and [m00120.pm](m00120.pm)
|
* For the basic salted hash tests, see [m00110.pm](m00110.pm) and [m00120.pm](m00120.pm)
|
||||||
* For some sligthly more complex modules with PBKDF2 and encryption, see [m18400.pm](m18400.pm) and [m18600.pm](m18600.pm)
|
* For some sligthly more complex modules with PBKDF2 and encryption, see [m18400.pm](m18400.pm) and [m18600.pm](m18600.pm)
|
||||||
* For a test module with a custom salt generation algorithm, see [m05600.pm](m05600.pm)
|
* For a test module with hashlist preprocessing and a custom salt generation algorithm, see [m05600.pm](m05600.pm)
|
||||||
|
@ -17,7 +17,7 @@ sub module_generate_hash
|
|||||||
|
|
||||||
return if length $word > 27;
|
return if length $word > 27;
|
||||||
|
|
||||||
my $hash = md4_hex (encode ("UTF-16LE", $word));
|
my $hash = md4_hex (encode ('UTF-16LE', $word));
|
||||||
|
|
||||||
return $hash;
|
return $hash;
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ sub module_verify_hash
|
|||||||
{
|
{
|
||||||
my $line = shift;
|
my $line = shift;
|
||||||
|
|
||||||
my ($hash, $word) = split ":", $line;
|
my ($hash, $word) = split (':', $line);
|
||||||
|
|
||||||
return unless defined $hash;
|
return unless defined $hash;
|
||||||
return unless defined $word;
|
return unless defined $word;
|
||||||
|
@ -24,7 +24,7 @@ sub module_verify_hash
|
|||||||
{
|
{
|
||||||
my $line = shift;
|
my $line = shift;
|
||||||
|
|
||||||
my ($hash, $word) = split ":", $line;
|
my ($hash, $word) = split (':', $line);
|
||||||
|
|
||||||
return unless defined $hash;
|
return unless defined $hash;
|
||||||
return unless defined $word;
|
return unless defined $word;
|
||||||
|
@ -24,11 +24,11 @@ sub module_generate_hash
|
|||||||
my $srv_ch = shift // random_hex_string (2*8);
|
my $srv_ch = shift // random_hex_string (2*8);
|
||||||
my $cli_ch = shift // random_client_challenge ();
|
my $cli_ch = shift // random_client_challenge ();
|
||||||
|
|
||||||
my $b_srv_ch = pack ("H*", $srv_ch);
|
my $b_srv_ch = pack ('H*', $srv_ch);
|
||||||
my $b_cli_ch = pack ("H*", $cli_ch);
|
my $b_cli_ch = pack ('H*', $cli_ch);
|
||||||
|
|
||||||
my $nthash = Authen::Passphrase::NTHash->new (passphrase => $word)->hash;
|
my $nthash = Authen::Passphrase::NTHash->new (passphrase => $word)->hash;
|
||||||
my $identity = encode ("UTF-16LE", uc ($user) . $domain);
|
my $identity = encode ('UTF-16LE', uc ($user) . $domain);
|
||||||
my $hash_buf = hmac_hex ($b_srv_ch . $b_cli_ch, hmac ($identity, $nthash, \&md5, 64), \&md5, 64);
|
my $hash_buf = hmac_hex ($b_srv_ch . $b_cli_ch, hmac ($identity, $nthash, \&md5, 64), \&md5, 64);
|
||||||
|
|
||||||
my $hash = sprintf ("%s::%s:%s:%s:%s", $user, $domain, $srv_ch, $hash_buf, $cli_ch);
|
my $hash = sprintf ("%s::%s:%s:%s:%s", $user, $domain, $srv_ch, $hash_buf, $cli_ch);
|
||||||
@ -48,9 +48,9 @@ sub module_verify_hash
|
|||||||
|
|
||||||
my $hash;
|
my $hash;
|
||||||
|
|
||||||
my $index1 = index ($line, "::");
|
my $index1 = index ($line, '::');
|
||||||
my $index2 = index ($line, ":", $index1 + 2);
|
my $index2 = index ($line, ':', $index1 + 2);
|
||||||
my $index3 = index ($line, ":", $index2 + 3 + 16 + 32);
|
my $index3 = index ($line, ':', $index2 + 3 + 16 + 32);
|
||||||
|
|
||||||
return if $index1 eq -1;
|
return if $index1 eq -1;
|
||||||
return if $index2 eq -1;
|
return if $index2 eq -1;
|
||||||
@ -68,11 +68,28 @@ sub module_verify_hash
|
|||||||
|
|
||||||
my $new_hash = module_generate_hash ($word, $user, $domain, $srv_ch, $cli_ch);
|
my $new_hash = module_generate_hash ($word, $user, $domain, $srv_ch, $cli_ch);
|
||||||
|
|
||||||
return unless lc $new_hash eq lc $hash;
|
# resolve lowercase/uppercase ambiguity in the username
|
||||||
|
# this will also guarantee a match with the preprocessed hashlist
|
||||||
|
$hash = lc $hash;
|
||||||
|
$new_hash = lc $new_hash;
|
||||||
|
|
||||||
|
return unless $new_hash eq $hash;
|
||||||
|
|
||||||
return $new_hash;
|
return $new_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# algorithm is case-insensitive in regard to usernames
|
||||||
|
# hashcat output always is uppercase, while real world hashes are not
|
||||||
|
sub module_preprocess_hashlist
|
||||||
|
{
|
||||||
|
my $hashlist = shift;
|
||||||
|
|
||||||
|
for my $hash (@{$hashlist})
|
||||||
|
{
|
||||||
|
$hash = lc $hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub random_client_challenge
|
sub random_client_challenge
|
||||||
{
|
{
|
||||||
my $ch;
|
my $ch;
|
||||||
|
@ -20,9 +20,9 @@ sub module_generate_hash
|
|||||||
my $iv = shift // random_hex_string (2*16);
|
my $iv = shift // random_hex_string (2*16);
|
||||||
my $plain = shift // random_hex_string (2*1024);
|
my $plain = shift // random_hex_string (2*1024);
|
||||||
|
|
||||||
my $b_iv = pack ("H*", $iv);
|
my $b_iv = pack ('H*', $iv);
|
||||||
my $b_salt = pack ("H*", $salt);
|
my $b_salt = pack ('H*', $salt);
|
||||||
my $b_plain = pack ("H*", $plain);
|
my $b_plain = pack ('H*', $plain);
|
||||||
|
|
||||||
my $kdf = Crypt::PBKDF2->new
|
my $kdf = Crypt::PBKDF2->new
|
||||||
(
|
(
|
||||||
@ -35,7 +35,7 @@ sub module_generate_hash
|
|||||||
my $key = $kdf->PBKDF2 ($b_salt, $pass_hash);
|
my $key = $kdf->PBKDF2 ($b_salt, $pass_hash);
|
||||||
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
|
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
|
||||||
my $b_cipher = $cbc->encrypt ($b_plain, $key, $b_iv);
|
my $b_cipher = $cbc->encrypt ($b_plain, $key, $b_iv);
|
||||||
my $cipher = unpack ("H*", $b_cipher);
|
my $cipher = unpack ('H*', $b_cipher);
|
||||||
my $checksum = sha256_hex ($b_plain);
|
my $checksum = sha256_hex ($b_plain);
|
||||||
|
|
||||||
my $hash = '$odf$'."*1*1*$iter*32*$checksum*16*$iv*16*$salt*0*$cipher";
|
my $hash = '$odf$'."*1*1*$iter*32*$checksum*16*$iv*16*$salt*0*$cipher";
|
||||||
@ -83,9 +83,9 @@ sub module_verify_hash
|
|||||||
return unless defined $cipher;
|
return unless defined $cipher;
|
||||||
|
|
||||||
# decrypt
|
# decrypt
|
||||||
my $b_iv = pack ("H*", $iv);
|
my $b_iv = pack ('H*', $iv);
|
||||||
my $b_salt = pack ("H*", $salt);
|
my $b_salt = pack ('H*', $salt);
|
||||||
my $b_cipher = pack ("H*", $cipher);
|
my $b_cipher = pack ('H*', $cipher);
|
||||||
|
|
||||||
my $kdf = Crypt::PBKDF2->new
|
my $kdf = Crypt::PBKDF2->new
|
||||||
(
|
(
|
||||||
@ -98,7 +98,7 @@ sub module_verify_hash
|
|||||||
my $key = $kdf->PBKDF2 ($b_salt, $pass_hash);
|
my $key = $kdf->PBKDF2 ($b_salt, $pass_hash);
|
||||||
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
|
my $cbc = Crypt::Mode::CBC->new ('AES', 0);
|
||||||
my $b_plain = $cbc->decrypt ($b_cipher, $key, $b_iv);
|
my $b_plain = $cbc->decrypt ($b_cipher, $key, $b_iv);
|
||||||
my $plain = unpack ("H*", $b_plain);
|
my $plain = unpack ('H*', $b_plain);
|
||||||
|
|
||||||
my $new_hash = module_generate_hash ($word, $salt, $iter, $iv, $plain);
|
my $new_hash = module_generate_hash ($word, $salt, $iter, $iv, $plain);
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ sub module_generate_hash
|
|||||||
my $iv = shift // random_hex_string (2*8);
|
my $iv = shift // random_hex_string (2*8);
|
||||||
my $plain = shift // random_hex_string (2*1024);
|
my $plain = shift // random_hex_string (2*1024);
|
||||||
|
|
||||||
my $b_iv = pack ("H*", $iv);
|
my $b_iv = pack ('H*', $iv);
|
||||||
my $b_salt = pack ("H*", $salt);
|
my $b_salt = pack ('H*', $salt);
|
||||||
my $b_plain = pack ("H*", $plain);
|
my $b_plain = pack ('H*', $plain);
|
||||||
|
|
||||||
my $kdf = Crypt::PBKDF2->new
|
my $kdf = Crypt::PBKDF2->new
|
||||||
(
|
(
|
||||||
@ -48,7 +48,7 @@ sub module_generate_hash
|
|||||||
|
|
||||||
$cfb->finish ();
|
$cfb->finish ();
|
||||||
|
|
||||||
my $cipher = unpack ("H*", $b_cipher);
|
my $cipher = unpack ('H*', $b_cipher);
|
||||||
my $checksum = sha1_hex ($b_plain);
|
my $checksum = sha1_hex ($b_plain);
|
||||||
|
|
||||||
my $hash = '$odf$'."*0*0*$iter*16*$checksum*8*$iv*16*$salt*0*$cipher";
|
my $hash = '$odf$'."*0*0*$iter*16*$checksum*8*$iv*16*$salt*0*$cipher";
|
||||||
@ -96,9 +96,9 @@ sub module_verify_hash
|
|||||||
return unless defined $cipher;
|
return unless defined $cipher;
|
||||||
|
|
||||||
# decrypt
|
# decrypt
|
||||||
my $b_iv = pack ("H*", $iv);
|
my $b_iv = pack ('H*', $iv);
|
||||||
my $b_salt = pack ("H*", $salt);
|
my $b_salt = pack ('H*', $salt);
|
||||||
my $b_cipher = pack ("H*", $cipher);
|
my $b_cipher = pack ('H*', $cipher);
|
||||||
|
|
||||||
my $kdf = Crypt::PBKDF2->new
|
my $kdf = Crypt::PBKDF2->new
|
||||||
(
|
(
|
||||||
@ -124,7 +124,7 @@ sub module_verify_hash
|
|||||||
|
|
||||||
$cfb->finish ();
|
$cfb->finish ();
|
||||||
|
|
||||||
my $plain = unpack ("H*", $b_plain);
|
my $plain = unpack ('H*', $b_plain);
|
||||||
|
|
||||||
my $new_hash = module_generate_hash ($word, $salt, $iter, $iv, $plain);
|
my $new_hash = module_generate_hash ($word, $salt, $iter, $iv, $plain);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user