1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-11-23 00:28:11 +00:00

Added support of keyfiles within Keepass 1.x and Keepass 2.x

This commit is contained in:
Fist0urs 2016-04-06 14:59:00 +02:00
parent 5f05fbf103
commit 34b8d89422
6 changed files with 266 additions and 49 deletions

View File

@ -1168,7 +1168,7 @@ __kernel void m13400_init (__global pw_t *pws, __global kernel_rule_t *rules_buf
sha256_transform (w0, w1, w2, w3, digest); sha256_transform (w0, w1, w2, w3, digest);
if (esalt_bufs[salt_pos].version == 2) if (esalt_bufs[salt_pos].version == 2 && esalt_bufs[salt_pos].keyfile_len == 0)
{ {
w0[0] = digest[0]; w0[0] = digest[0];
w0[1] = digest[1]; w0[1] = digest[1];
@ -1202,6 +1202,62 @@ __kernel void m13400_init (__global pw_t *pws, __global kernel_rule_t *rules_buf
sha256_transform (w0, w1, w2, w3, digest); sha256_transform (w0, w1, w2, w3, digest);
} }
if (esalt_bufs[salt_pos].keyfile_len != 0)
{
w0[0] = digest[0];
w0[1] = digest[1];
w0[2] = digest[2];
w0[3] = digest[3];
w1[0] = digest[4];
w1[1] = digest[5];
w1[2] = digest[6];
w1[3] = digest[7];
w2[0] = esalt_bufs[salt_pos].keyfile[0];
w2[1] = esalt_bufs[salt_pos].keyfile[1];
w2[2] = esalt_bufs[salt_pos].keyfile[2];
w2[3] = esalt_bufs[salt_pos].keyfile[3];
w3[0] = esalt_bufs[salt_pos].keyfile[4];
w3[1] = esalt_bufs[salt_pos].keyfile[5];
w3[3] = esalt_bufs[salt_pos].keyfile[7];
w3[2] = esalt_bufs[salt_pos].keyfile[6];
digest[0] = SHA256M_A;
digest[1] = SHA256M_B;
digest[2] = SHA256M_C;
digest[3] = SHA256M_D;
digest[4] = SHA256M_E;
digest[5] = SHA256M_F;
digest[6] = SHA256M_G;
digest[7] = SHA256M_H;
sha256_transform (w0, w1, w2, w3, digest);
w0[0] = 0x80000000;
w0[1] = 0;
w0[2] = 0;
w0[3] = 0;
w1[0] = 0;
w1[1] = 0;
w1[2] = 0;
w1[3] = 0;
w2[0] = 0;
w2[1] = 0;
w2[2] = 0;
w2[3] = 0;
w3[0] = 0;
w3[1] = 0;
w3[2] = 0;
w3[3] = 64 * 8;
sha256_transform (w0, w1, w2, w3, digest);
}
tmps[gid].tmp_digest[0] = digest[0]; tmps[gid].tmp_digest[0] = digest[0];
tmps[gid].tmp_digest[1] = digest[1]; tmps[gid].tmp_digest[1] = digest[1];
tmps[gid].tmp_digest[2] = digest[2]; tmps[gid].tmp_digest[2] = digest[2];
@ -1420,7 +1476,7 @@ __kernel void m13400_comp (__global pw_t *pws, __global kernel_rule_t *rules_buf
} }
else else
{ {
/* merkle-demgard implementation */ /* merkle-damgard implementation */
u32 final_random_seed[8]; u32 final_random_seed[8];
final_random_seed[0] = esalt_bufs[salt_pos].final_random_seed[0]; final_random_seed[0] = esalt_bufs[salt_pos].final_random_seed[0];

View File

@ -1597,6 +1597,10 @@ typedef struct
u32 version; u32 version;
u32 algorithm; u32 algorithm;
/* key-file handling */
u32 keyfile_len;
u32 keyfile[8];
u32 final_random_seed[8]; u32 final_random_seed[8];
u32 transf_random_seed[8]; u32 transf_random_seed[8];
u32 enc_iv[4]; u32 enc_iv[4];

View File

@ -688,7 +688,7 @@ extern hc_thread_mutex_t mux_display;
#define DISPLAY_LEN_MIN_13300 1 + 12 + 1 + 32 #define DISPLAY_LEN_MIN_13300 1 + 12 + 1 + 32
#define DISPLAY_LEN_MAX_13300 1 + 12 + 1 + 40 #define DISPLAY_LEN_MAX_13300 1 + 12 + 1 + 40
#define DISPLAY_LEN_MIN_13400 1 + 7 + 1 + 1 + 1 + 1 + 1 + 1 + 32 + 1 + 64 + 1 + 32 + 1 + 64 + 1 + 1 + 1 + 1 #define DISPLAY_LEN_MIN_13400 1 + 7 + 1 + 1 + 1 + 1 + 1 + 1 + 32 + 1 + 64 + 1 + 32 + 1 + 64 + 1 + 1 + 1 + 1
#define DISPLAY_LEN_MAX_13400 1 + 7 + 1 + 1 + 10 + 1 + 3 + 1 + 64 + 1 + 64 + 1 + 32 + 1 + 64 + 1 + 4 + 1 + 100000 #define DISPLAY_LEN_MAX_13400 1 + 7 + 1 + 1 + 10 + 1 + 3 + 1 + 64 + 1 + 64 + 1 + 32 + 1 + 64 + 1 + 4 + 1 + 100000 + 1 + 2 + 1 + 64
#define DISPLAY_LEN_MIN_11 32 + 1 + 16 #define DISPLAY_LEN_MIN_11 32 + 1 + 16
#define DISPLAY_LEN_MAX_11 32 + 1 + 32 #define DISPLAY_LEN_MAX_11 32 + 1 + 32

View File

@ -141,6 +141,10 @@ typedef struct
u32 version; u32 version;
u32 algorithm; u32 algorithm;
/* key-file handling */
u32 keyfile_len;
u32 keyfile[8];
u32 final_random_seed[8]; u32 final_random_seed[8];
u32 transf_random_seed[8]; u32 transf_random_seed[8];
u32 enc_iv[4]; u32 enc_iv[4];

View File

@ -6185,7 +6185,7 @@ void ascii_digest (char *out_buf, uint salt_pos, uint digest_pos)
} }
else if (hash_mode == 23) else if (hash_mode == 23)
{ {
// do not show the \nskyper\n part in output // do not show the skyper part in output
char *salt_buf_ptr = (char *) salt.salt_buf; char *salt_buf_ptr = (char *) salt.salt_buf;
@ -8358,11 +8358,13 @@ void ascii_digest (char *out_buf, uint salt_pos, uint digest_pos)
u32 version = (u32) keepass->version; u32 version = (u32) keepass->version;
u32 rounds = salt.salt_iter; u32 rounds = salt.salt_iter;
u32 algorithm = (u32) keepass->algorithm; u32 algorithm = (u32) keepass->algorithm;
u32 keyfile_len = (u32) keepass->keyfile_len;
u32 *ptr_final_random_seed = (u32 *) keepass->final_random_seed ; u32 *ptr_final_random_seed = (u32 *) keepass->final_random_seed ;
u32 *ptr_transf_random_seed = (u32 *) keepass->transf_random_seed ; u32 *ptr_transf_random_seed = (u32 *) keepass->transf_random_seed ;
u32 *ptr_enc_iv = (u32 *) keepass->enc_iv ; u32 *ptr_enc_iv = (u32 *) keepass->enc_iv ;
u32 *ptr_contents_hash = (u32 *) keepass->contents_hash ; u32 *ptr_contents_hash = (u32 *) keepass->contents_hash ;
u32 *ptr_keyfile = (u32 *) keepass->keyfile ;
/* specific to version 1 */ /* specific to version 1 */
u32 contents_len; u32 contents_len;
@ -8462,6 +8464,28 @@ void ascii_digest (char *out_buf, uint salt_pos, uint digest_pos)
for (uint i = 0; i < contents_hash_len; i++, ptr_data += 8) for (uint i = 0; i < contents_hash_len; i++, ptr_data += 8)
sprintf (ptr_data, "%08x", ptr_contents_hash[i]); sprintf (ptr_data, "%08x", ptr_contents_hash[i]);
} }
if (keyfile_len)
{
*ptr_data = '*';
ptr_data++;
/* inline flag */
*ptr_data = '1';
ptr_data++;
*ptr_data = '*';
ptr_data++;
sprintf (ptr_data, "%d", keyfile_len);
ptr_data += 2;
*ptr_data = '*';
ptr_data++;
for (uint i = 0; i < 8; i++, ptr_data += 8)
sprintf (ptr_data, "%08x", ptr_keyfile[i]);
}
} }
else else
{ {
@ -19163,6 +19187,13 @@ int keepass_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
char *enc_iv_pos; char *enc_iv_pos;
u32 enc_iv_len; u32 enc_iv_len;
/* default is no keyfile provided */
char *keyfile_len_pos;
u32 keyfile_len = 0;
u32 is_keyfile_present = 0;
char *keyfile_inline_pos;
char *keyfile_pos;
/* specific to version 1 */ /* specific to version 1 */
char *contents_len_pos; char *contents_len_pos;
u32 contents_len; u32 contents_len;
@ -19307,7 +19338,18 @@ int keepass_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
contents_len = contents_len / 4; contents_len = contents_len / 4;
u32 real_contents_len = input_len - (contents_pos - input_buf); keyfile_inline_pos = strchr (contents_pos, '*');
u32 real_contents_len;
if (keyfile_inline_pos == NULL)
real_contents_len = input_len - (contents_pos - input_buf);
else
{
real_contents_len = keyfile_inline_pos - contents_pos;
keyfile_inline_pos++;
is_keyfile_present = 1;
}
if (real_contents_len != keepass->contents_len * 2) return (PARSER_SALT_LENGTH); if (real_contents_len != keepass->contents_len * 2) return (PARSER_SALT_LENGTH);
@ -19354,11 +19396,51 @@ int keepass_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
keepass->contents_hash[6] = hex_to_u32 ((const u8 *) &contents_hash_pos[48]); keepass->contents_hash[6] = hex_to_u32 ((const u8 *) &contents_hash_pos[48]);
keepass->contents_hash[7] = hex_to_u32 ((const u8 *) &contents_hash_pos[56]); keepass->contents_hash[7] = hex_to_u32 ((const u8 *) &contents_hash_pos[56]);
contents_hash_len = input_len - (int) (contents_hash_pos - input_buf); keyfile_inline_pos = strchr (contents_hash_pos, '*');
if (keyfile_inline_pos == NULL)
contents_hash_len = input_len - (int) (contents_hash_pos - input_buf);
else
{
contents_hash_len = keyfile_inline_pos - contents_hash_pos;
keyfile_inline_pos++;
is_keyfile_present = 1;
}
if (contents_hash_len != 64) return (PARSER_SALT_LENGTH); if (contents_hash_len != 64) return (PARSER_SALT_LENGTH);
} }
if (is_keyfile_present != 0)
{
keyfile_len_pos = strchr (keyfile_inline_pos, '*');
keyfile_len_pos++;
keyfile_len = atoi (keyfile_len_pos);
keepass->keyfile_len = keyfile_len;
if (keyfile_len != 64) return (PARSER_SALT_LENGTH);
keyfile_pos = strchr (keyfile_len_pos, '*');
if (keyfile_pos == NULL) return (PARSER_SALT_LENGTH);
keyfile_pos++;
u32 real_keyfile_len = input_len - (keyfile_pos - input_buf);
if (real_keyfile_len != 64) return (PARSER_SALT_LENGTH);
keepass->keyfile[0] = hex_to_u32 ((const u8 *) &keyfile_pos[ 0]);
keepass->keyfile[1] = hex_to_u32 ((const u8 *) &keyfile_pos[ 8]);
keepass->keyfile[2] = hex_to_u32 ((const u8 *) &keyfile_pos[16]);
keepass->keyfile[3] = hex_to_u32 ((const u8 *) &keyfile_pos[24]);
keepass->keyfile[4] = hex_to_u32 ((const u8 *) &keyfile_pos[32]);
keepass->keyfile[5] = hex_to_u32 ((const u8 *) &keyfile_pos[40]);
keepass->keyfile[6] = hex_to_u32 ((const u8 *) &keyfile_pos[48]);
keepass->keyfile[7] = hex_to_u32 ((const u8 *) &keyfile_pos[56]);
}
digest[0] = keepass->enc_iv[0]; digest[0] = keepass->enc_iv[0];
digest[1] = keepass->enc_iv[1]; digest[1] = keepass->enc_iv[1];
digest[2] = keepass->enc_iv[2]; digest[2] = keepass->enc_iv[2];

View File

@ -2298,7 +2298,10 @@ sub verify
my @data = split ('\*', $hash_in); my @data = split ('\*', $hash_in);
next unless (scalar @data == 9 || scalar @data == 11); next unless (scalar @data == 9
|| scalar @data == 11
|| scalar @data == 12
|| scalar @data == 14);
my $signature = shift @data; my $signature = shift @data;
next unless ($signature eq '$keepass$'); next unless ($signature eq '$keepass$');
@ -2349,6 +2352,18 @@ sub verify
next unless (length ($contents_hash) == 64); 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, length ($hash_in)); $salt = substr ($hash_in, length ("*keepass*") + 1, length ($hash_in));
next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in}))); next unless (exists ($db->{$hash_in}) and (! defined ($db->{$hash_in})));
@ -6965,6 +6980,12 @@ END_CODE
# specific to version 2 # specific to version 2
my $expected_bytes; 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); $final_random_seed = pack ("H*", $final_random_seed);
$transf_random_seed = pack ("H*", $transf_random_seed); $transf_random_seed = pack ("H*", $transf_random_seed);
@ -6984,9 +7005,44 @@ END_CODE
$contents = $salt_arr[9]; $contents = $salt_arr[9];
$contents = pack ("H*", $contents); $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) 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); $intermediate_hash = sha256 ($intermediate_hash);
} }
@ -7029,7 +7085,7 @@ END_CODE
$contents = $cipher->encrypt($contents); $contents = $cipher->encrypt($contents);
$tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%d*%d*%s', $tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%d*%d*%s%s',
$version, $version,
$iteration, $iteration,
$algorithm, $algorithm,
@ -7039,7 +7095,8 @@ END_CODE
unpack ("H*", $contents_hash), unpack ("H*", $contents_hash),
$inline_flag, $inline_flag,
$contents_len, $contents_len,
unpack ("H*", $contents)); unpack ("H*", $contents),
$keyfile_attributes);
} }
if ($version == 2) if ($version == 2)
{ {
@ -7050,7 +7107,7 @@ END_CODE
$expected_bytes = $cipher->decrypt($contents_hash); $expected_bytes = $cipher->decrypt($contents_hash);
$tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%s', $tmp_hash = sprintf ('$keepass$*%d*%d*%d*%s*%s*%s*%s*%s%s',
$version, $version,
$iteration, $iteration,
$algorithm, $algorithm,
@ -7058,7 +7115,8 @@ END_CODE
unpack ("H*", $transf_random_seed), unpack ("H*", $transf_random_seed),
unpack ("H*", $enc_iv), unpack ("H*", $enc_iv),
unpack ("H*", $expected_bytes), unpack ("H*", $expected_bytes),
unpack ("H*", $contents_hash)); unpack ("H*", $contents_hash),
$keyfile_attributes);
} }
} }
@ -8510,6 +8568,17 @@ sub get_random_keepass_salt
my $salt_buf; 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) if ($version == 1)
{ {
$salt_buf = $version . '*' . $salt_buf = $version . '*' .
@ -8521,7 +8590,8 @@ sub get_random_keepass_salt
$contents_hash . '*' . $contents_hash . '*' .
$inline_flag . '*' . $inline_flag . '*' .
$contents_len . '*' . $contents_len . '*' .
$contents; $contents . '*' .
$keyfile_attributes;
} }
elsif ($version == 2) elsif ($version == 2)
{ {
@ -8535,7 +8605,8 @@ sub get_random_keepass_salt
$transf_random_seed . '*' . $transf_random_seed . '*' .
$enc_iv . '*' . $enc_iv . '*' .
$contents_hash . '*' . $contents_hash . '*' .
$contents; $contents . '*' .
$keyfile_attributes;
} }
return $salt_buf; return $salt_buf;