mirror of
https://github.com/hashcat/hashcat.git
synced 2024-11-25 17:38:23 +00:00
Add missing unit-test for -m 29700
This commit is contained in:
parent
289f6b7cbd
commit
9ed69c6248
412
tools/test_modules/m29700.pm
Normal file
412
tools/test_modules/m29700.pm
Normal file
@ -0,0 +1,412 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Crypt::CBC;
|
||||
use Crypt::Mode::ECB;
|
||||
use Digest::SHA qw (sha256);
|
||||
|
||||
sub module_constraints { [[64, 64], [-1, -1], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
sub get_random_keepass_salt
|
||||
{
|
||||
my $version = random_number (1, 2);
|
||||
|
||||
my $algorithm;
|
||||
|
||||
my $iteration;
|
||||
|
||||
my $final_random_seed;
|
||||
|
||||
if ($version == 1)
|
||||
{
|
||||
$algorithm = random_number (0, 1);
|
||||
|
||||
$iteration = random_number (50000, 99999);
|
||||
|
||||
$final_random_seed = random_bytes (16);
|
||||
$final_random_seed = unpack ("H*", $final_random_seed);
|
||||
}
|
||||
elsif ($version == 2)
|
||||
{
|
||||
$algorithm = 0;
|
||||
|
||||
$iteration = random_number (6000, 99999);
|
||||
|
||||
$final_random_seed = random_bytes (32);
|
||||
$final_random_seed = unpack ("H*", $final_random_seed);
|
||||
}
|
||||
|
||||
my $transf_random_seed = random_bytes (32);
|
||||
$transf_random_seed = unpack ("H*", $transf_random_seed);
|
||||
|
||||
my $enc_iv = random_bytes (16);
|
||||
$enc_iv = unpack ("H*", $enc_iv);
|
||||
|
||||
my $contents_hash = random_bytes (32);
|
||||
$contents_hash = unpack ("H*", $contents_hash);
|
||||
|
||||
my $inline_flag = 1;
|
||||
|
||||
my $contents_len = random_number (128, 499);
|
||||
|
||||
my $contents = random_bytes ($contents_len);
|
||||
|
||||
$contents_len += 16 - $contents_len % 16;
|
||||
|
||||
$contents = unpack ("H*", $contents);
|
||||
|
||||
my $salt_buf;
|
||||
|
||||
#my $is_keyfile = random_number (0, 1);
|
||||
my $is_keyfile = 0;
|
||||
|
||||
my $keyfile_attributes = "";
|
||||
|
||||
if ($is_keyfile == 1)
|
||||
{
|
||||
$keyfile_attributes = $keyfile_attributes
|
||||
. "1*64*"
|
||||
. unpack ("H*", random_bytes (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 = random_bytes (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 module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $param = shift;
|
||||
|
||||
if (length $salt == 0)
|
||||
{
|
||||
$salt = get_random_keepass_salt ();
|
||||
}
|
||||
|
||||
my @salt_arr = split ('\*', $salt);
|
||||
|
||||
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 $word_bin = pack ("H*", $word);
|
||||
|
||||
#my $intermediate_hash = sha256 ($word);
|
||||
my $intermediate_hash = sha256 ($word_bin);
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
my $hash;
|
||||
|
||||
if ($version == 1)
|
||||
{
|
||||
if (defined $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);
|
||||
|
||||
$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);
|
||||
|
||||
$expected_bytes = substr ($expected_bytes . "\x00" x 32, 0, 32); # padding
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my ($hash_in, $word) = split ":", $line;
|
||||
|
||||
return unless defined $hash_in;
|
||||
return unless defined $word;
|
||||
|
||||
my @data = split ('\*', $hash_in);
|
||||
|
||||
return unless (scalar @data == 9
|
||||
|| scalar @data == 11
|
||||
|| scalar @data == 12
|
||||
|| scalar @data == 14);
|
||||
|
||||
my $signature = shift @data;
|
||||
return unless ($signature eq '$keepass$');
|
||||
|
||||
my $version = shift @data;
|
||||
return unless ($version == 1 || $version == 2);
|
||||
|
||||
my $iteration = shift @data;
|
||||
|
||||
my $algorithm = shift @data;
|
||||
|
||||
my $final_random_seed = shift @data;
|
||||
|
||||
if ($version == 1)
|
||||
{
|
||||
return unless (length ($final_random_seed) == 32);
|
||||
}
|
||||
elsif ($version == 2)
|
||||
{
|
||||
return unless (length ($final_random_seed) == 64);
|
||||
}
|
||||
|
||||
my $transf_random_seed = shift @data;
|
||||
return unless (length ($transf_random_seed) == 64);
|
||||
|
||||
my $enc_iv = shift @data;
|
||||
return unless (length ($enc_iv) == 32);
|
||||
|
||||
if ($version == 1)
|
||||
{
|
||||
my $contents_hash = shift @data;
|
||||
return unless (length ($contents_hash) == 64);
|
||||
|
||||
my $inline_flags = shift @data;
|
||||
return unless ($inline_flags == 1);
|
||||
|
||||
my $contents_len = shift @data;
|
||||
|
||||
my $contents = shift @data;
|
||||
return unless (length ($contents) == $contents_len * 2);
|
||||
}
|
||||
elsif ($version == 2)
|
||||
{
|
||||
my $expected_bytes = shift @data;
|
||||
return unless (length ($expected_bytes) == 64);
|
||||
|
||||
my $contents_hash = shift @data;
|
||||
return unless (length ($contents_hash) == 64);
|
||||
}
|
||||
|
||||
if (scalar @data == 12 || scalar @data == 14)
|
||||
{
|
||||
my $inline_flags = shift @data;
|
||||
return unless ($inline_flags == 1);
|
||||
|
||||
my $keyfile_len = shift @data;
|
||||
return unless ($keyfile_len == 64);
|
||||
|
||||
my $keyfile = shift @data;
|
||||
return unless (length ($keyfile) == $keyfile_len);
|
||||
}
|
||||
|
||||
my $salt = substr ($hash_in, length ("*keepass*") + 1);
|
||||
my $param = 1; # distinguish between encrypting vs decrypting
|
||||
|
||||
return unless defined $salt;
|
||||
|
||||
$word = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word, $salt, $param);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user