mirror of
https://github.com/hashcat/hashcat.git
synced 2024-12-22 22:58:30 +00:00
Merge remote-tracking branch 'upstream/master' into fix_MTLCompilerService_InfiniteLoop_bug
This commit is contained in:
commit
92218daf6d
@ -21,11 +21,11 @@
|
||||
|
||||
typedef struct pbkdf2_sha256_tmp
|
||||
{
|
||||
u32 ipad[8];
|
||||
u32 opad[8];
|
||||
u32 ipad[8];
|
||||
u32 opad[8];
|
||||
|
||||
u32 dgst[32];
|
||||
u32 out[32];
|
||||
u32 dgst[32];
|
||||
u32 out[32];
|
||||
|
||||
} pbkdf2_sha256_tmp_t;
|
||||
|
||||
@ -34,7 +34,7 @@ typedef struct pbkdf2_sha256_aes_gcm
|
||||
u32 salt_buf[64];
|
||||
u32 iv_buf[4];
|
||||
u32 iv_len;
|
||||
u32 ct_buf[784]; // TODO this can be smaller and would speedup the attack, only 64 bytes of ciphertext are allowed
|
||||
u32 ct_buf[16];
|
||||
u32 ct_len;
|
||||
|
||||
} pbkdf2_sha256_aes_gcm_t;
|
||||
@ -368,7 +368,6 @@ KERNEL_FQ void m26610_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha256_tmp_t, pbkdf2_sh
|
||||
|
||||
AES_GCM_decrypt (key, J0, ct, 32, pt, s_te0, s_te1, s_te2, s_te3, s_te4);
|
||||
|
||||
|
||||
const int correct = is_valid_printable_32 (pt[0])
|
||||
+ is_valid_printable_32 (pt[1])
|
||||
+ is_valid_printable_32 (pt[2])
|
||||
|
@ -52,6 +52,9 @@
|
||||
- Skip chained generated rules that exceed the maximum number of function calls
|
||||
- Fixed incorrect plaintext check for 25400 and 26610. Increased plaintext check to 32 bytes to prevent false positives.
|
||||
- Fixed bug in --stdout that caused certain rules to malfunction
|
||||
- Fixed bug in 18400 module_hash_encode
|
||||
- Fixed bug in 26900 module_hash_encode
|
||||
- Fixed bug in grep out-of-memory workaround on Unit Test
|
||||
- Fixed bug in input_tokenizer when TOKEN_ATTR_FIXED_LENGTH is used and refactor modules
|
||||
- Fixed build failed for 18400 with Apple Metal
|
||||
- Fixed build failed for 18600 with Apple Metal
|
||||
@ -59,6 +62,7 @@
|
||||
- Fixed incompatible pointer types (salt1 and salt2 buf) in 31700 a3 kernel
|
||||
- Fixed incompatible pointer types (salt1 and salt2 buf) in 3730 a3 kernel
|
||||
- Handle signed/unsigned PDF permission P value for all PDF hash-modes
|
||||
- Fixed minimum password length in module of hash-mode 29800
|
||||
- Fixed buffer overflow on module_26600.c / module_hash_encode()
|
||||
|
||||
##
|
||||
|
@ -248,15 +248,13 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
// ct
|
||||
|
||||
u32 ct_buf[256];
|
||||
u8 ct_buf[(256 * 4 * 2) + 1];
|
||||
|
||||
for (int i = 0; i < 256; i++) ct_buf[i] = byte_swap_32 (odf12->encrypted_data[i]);
|
||||
memset (ct_buf, 0, sizeof (ct_buf));
|
||||
|
||||
u8 ct_buf8[(256 * 4 * 2) + 1];
|
||||
const int ct_len = hex_encode ((const u8 *) odf12->encrypted_data, odf12->encrypted_len, ct_buf);
|
||||
|
||||
const int ct_len = hex_encode ((const u8 *) ct_buf, odf12->encrypted_len, ct_buf8);
|
||||
|
||||
ct_buf8[ct_len] = 0;
|
||||
ct_buf[ct_len] = 0;
|
||||
|
||||
const int out_len = snprintf (line_buf, line_size, "%s*1*1*%u*32*%08x%08x%08x%08x%08x%08x%08x%08x*16*%08x%08x%08x%08x*16*%08x%08x%08x%08x*0*%s",
|
||||
SIGNATURE_ODF,
|
||||
@ -277,7 +275,7 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
byte_swap_32 (salt->salt_buf[1]),
|
||||
byte_swap_32 (salt->salt_buf[2]),
|
||||
byte_swap_32 (salt->salt_buf[3]),
|
||||
(char *) ct_buf8);
|
||||
(char *) ct_buf);
|
||||
|
||||
return out_len;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ static const u32 DGST_POS2 = 2;
|
||||
static const u32 DGST_POS3 = 3;
|
||||
static const u32 DGST_SIZE = DGST_SIZE_4_4;
|
||||
static const u32 HASH_CATEGORY = HASH_CATEGORY_CRYPTOCURRENCY_WALLET;
|
||||
// 22610 generates a decryption key based on a password-guess and uses that to AES-GCM decrypt the data decrypts
|
||||
static const char *HASH_NAME = "MetaMask Wallet (short hash, plaintext check)";
|
||||
static const u64 KERN_TYPE = 26610;
|
||||
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
|
||||
@ -28,7 +27,6 @@ static const u64 OPTS_TYPE = OPTS_TYPE_STOCK_MODULE
|
||||
| OPTS_TYPE_DEEP_COMP_KERNEL;
|
||||
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
|
||||
static const char *ST_PASS = "hashcat1";
|
||||
// hash generated using with python3 tools/metamask2hashcat.py --vault tools/2hashcat_tests/metamask2hashcat.json --shortdata
|
||||
static const char *ST_HASH = "$metamask-short$jfGI3TXguhb8GPnKSXFrMzRk2NCEc131Gt5G3kZr5+s=$h+BoIf2CQ5BEjaIOShFE7g==$R95fzGt4UQ0uwrcrVYnIi4UcSlWn9wlmer+//526ZDwYAp50K82F1u1oacYcdjjhuEvbZnWk/uBG00UkgLLlOw==";
|
||||
|
||||
u32 module_attack_exec (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { return ATTACK_EXEC; }
|
||||
@ -48,11 +46,11 @@ const char *module_st_pass (MAYBE_UNUSED const hashconfig_t *hashconfig,
|
||||
|
||||
typedef struct pbkdf2_sha256_tmp
|
||||
{
|
||||
u32 ipad[8];
|
||||
u32 opad[8];
|
||||
u32 ipad[8];
|
||||
u32 opad[8];
|
||||
|
||||
u32 dgst[32];
|
||||
u32 out[32];
|
||||
u32 dgst[32];
|
||||
u32 out[32];
|
||||
|
||||
} pbkdf2_sha256_tmp_t;
|
||||
|
||||
@ -61,7 +59,7 @@ typedef struct pbkdf2_sha256_aes_gcm
|
||||
u32 salt_buf[64];
|
||||
u32 iv_buf[4];
|
||||
u32 iv_len;
|
||||
u32 ct_buf[784]; // TODO this can be smaller and would speedup the attack, only 64 bytes of ciphertext are allowed
|
||||
u32 ct_buf[16];
|
||||
u32 ct_len;
|
||||
|
||||
} pbkdf2_sha256_aes_gcm_t;
|
||||
@ -135,8 +133,6 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
pbkdf2_sha256_aes_gcm_t *metamask = (pbkdf2_sha256_aes_gcm_t *) esalt_buf;
|
||||
|
||||
#define CT_MAX_LEN_BASE64 (((3136+16) * 8) / 6) + 3 // TODO this can be smaller and would speedup the attack, only 64 bytes of ciphertext are allowed
|
||||
|
||||
hc_token_t token;
|
||||
|
||||
memset (&token, 0, sizeof (hc_token_t));
|
||||
@ -161,8 +157,8 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
| TOKEN_ATTR_VERIFY_BASE64A;
|
||||
|
||||
token.sep[3] = '$';
|
||||
token.len_min[3] = 32;
|
||||
token.len_max[3] = 100; // TODO this can be smaller and would speedup the attack, only 64 bytes of ciphertext are allowed
|
||||
token.len_min[3] = 88;
|
||||
token.len_max[3] = 88;
|
||||
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_BASE64A;
|
||||
|
||||
@ -170,10 +166,6 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
|
||||
|
||||
u8 tmp_buf[CT_MAX_LEN_BASE64] = { 0 };
|
||||
|
||||
size_t tmp_len = 0;
|
||||
|
||||
// iter
|
||||
|
||||
salt->salt_iter = 10000 - 1;
|
||||
@ -183,9 +175,11 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
const u8 *salt_pos = token.buf[1];
|
||||
const int salt_len = token.len[1];
|
||||
|
||||
u8 tmp_buf[88+1];
|
||||
|
||||
memset (tmp_buf, 0, sizeof (tmp_buf));
|
||||
|
||||
tmp_len = base64_decode (base64_to_int, salt_pos, salt_len, tmp_buf);
|
||||
size_t tmp_len = base64_decode (base64_to_int, salt_pos, salt_len, tmp_buf);
|
||||
|
||||
if (tmp_len != 32) return (PARSER_SALT_LENGTH);
|
||||
|
||||
@ -231,20 +225,23 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
tmp_len = base64_decode (base64_to_int, ct_pos, ct_len, tmp_buf);
|
||||
|
||||
if (tmp_len != 64) return (PARSER_CT_LENGTH);
|
||||
|
||||
memcpy ((u8 *) metamask->ct_buf, tmp_buf, tmp_len);
|
||||
|
||||
u32 j = tmp_len / 4;
|
||||
|
||||
if ((tmp_len % 4) > 0) j++;
|
||||
|
||||
for (u32 i = 0; i < j; i++) metamask->ct_buf[i] = byte_swap_32 (metamask->ct_buf[i]);
|
||||
for (u32 i = 0; i < j; i++)
|
||||
{
|
||||
metamask->ct_buf[i] = byte_swap_32 (metamask->ct_buf[i]);
|
||||
}
|
||||
|
||||
metamask->ct_len = tmp_len;
|
||||
|
||||
digest[0] = (metamask->ct_buf[0]);
|
||||
digest[1] = (metamask->ct_buf[1]);
|
||||
digest[2] = (metamask->ct_buf[2]);
|
||||
digest[3] = (metamask->ct_buf[3]);
|
||||
digest[0] = metamask->ct_buf[0];
|
||||
digest[1] = metamask->ct_buf[1];
|
||||
digest[2] = metamask->ct_buf[2];
|
||||
digest[3] = metamask->ct_buf[3];
|
||||
|
||||
return (PARSER_OK);
|
||||
}
|
||||
@ -255,40 +252,42 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
// salt
|
||||
|
||||
#define SALT_LEN_BASE64 ((32 * 8) / 6) + 3
|
||||
#define IV_LEN_BASE64 ((16 * 8) / 6) + 3
|
||||
#define CT_MAX_LEN_BASE64 (((3136+16) * 8) / 6) + 3 // TODO this can be much smaller now, probably 32 ?
|
||||
u8 salt_buf[44+1];
|
||||
|
||||
u8 salt_buf[SALT_LEN_BASE64] = { 0 };
|
||||
memset (salt_buf, 0, sizeof (salt_buf));
|
||||
|
||||
base64_encode (int_to_base64, (const u8 *) salt->salt_buf, (const int) salt->salt_len, salt_buf);
|
||||
|
||||
// iv
|
||||
|
||||
u32 tmp_iv_buf[4] = { 0 };
|
||||
u32 tmp_iv_buf[4];
|
||||
|
||||
tmp_iv_buf[0] = byte_swap_32 (metamask->iv_buf[0]);
|
||||
tmp_iv_buf[1] = byte_swap_32 (metamask->iv_buf[1]);
|
||||
tmp_iv_buf[2] = byte_swap_32 (metamask->iv_buf[2]);
|
||||
tmp_iv_buf[3] = byte_swap_32 (metamask->iv_buf[3]);
|
||||
|
||||
u8 iv_buf[IV_LEN_BASE64+1] = { 0 };
|
||||
u8 iv_buf[24+1];
|
||||
|
||||
memset (iv_buf, 0, sizeof (iv_buf));
|
||||
|
||||
base64_encode (int_to_base64, (const u8 *) tmp_iv_buf, (const int) metamask->iv_len, iv_buf);
|
||||
|
||||
// ct
|
||||
|
||||
u32 tmp_buf[16];
|
||||
|
||||
memset (tmp_buf, 0, sizeof (tmp_buf));
|
||||
|
||||
u32 ct_len = metamask->ct_len;
|
||||
|
||||
u32 j = ct_len / 4;
|
||||
|
||||
if ((ct_len % 4) > 0) j++;
|
||||
|
||||
u32 tmp_buf[784] = { 0 }; // TODO this can be smaller and would speedup the attack, only 64 bytes of ciphertext are allowed
|
||||
|
||||
for (u32 i = 0; i < j; i++) tmp_buf[i] = byte_swap_32 (metamask->ct_buf[i]);
|
||||
|
||||
u8 ct_buf[CT_MAX_LEN_BASE64] = { 0 };
|
||||
u8 ct_buf[88+1];
|
||||
|
||||
memset (ct_buf, 0, sizeof (ct_buf));
|
||||
|
||||
base64_encode (int_to_base64, (const u8 *) tmp_buf, (const int) metamask->ct_len, ct_buf);
|
||||
|
||||
|
@ -284,7 +284,19 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
||||
|
||||
out_len++;
|
||||
|
||||
out_len += hex_encode ((u8 *) snmpv3->engineID_buf, snmpv3->engineID_len, out_buf + out_len);
|
||||
// remove zero padding from snmpv3->engineID_buf
|
||||
|
||||
u8 *engineID_buf_tmp = (u8 *) snmpv3->engineID_buf;
|
||||
|
||||
u32 engineID_len = snmpv3->engineID_len;
|
||||
|
||||
while (engineID_buf_tmp[engineID_len] == 0x00) engineID_len--;
|
||||
|
||||
engineID_len++;
|
||||
|
||||
// append to output
|
||||
|
||||
out_len += hex_encode ((u8 *) snmpv3->engineID_buf, engineID_len, out_buf + out_len);
|
||||
|
||||
out_buf[out_len] = '$';
|
||||
|
||||
|
@ -624,7 +624,7 @@ static int selftest (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param
|
||||
|
||||
salt_t *salt_buf = &hashes->st_salts_buf[salt_pos];
|
||||
|
||||
const u32 salt_repeats = hashes->salts_buf[salt_pos].salt_repeats;
|
||||
const u32 salt_repeats = salt_buf->salt_repeats;
|
||||
|
||||
for (u32 salt_repeat = 0; salt_repeat <= salt_repeats; salt_repeat++)
|
||||
{
|
||||
|
@ -591,7 +591,7 @@ function attack_0()
|
||||
|
||||
# out-of-memory, workaround
|
||||
|
||||
echo "${output}" | head -1 > tmp_file_out
|
||||
echo "${output}" | grep -v "^Unsupported\|^$" | head -1 > tmp_file_out
|
||||
echo "${search}" > tmp_file_search
|
||||
|
||||
out_md5=$(md5sum tmp_file_out | cut -d' ' -f1)
|
||||
@ -874,7 +874,7 @@ function attack_1()
|
||||
|
||||
# out-of-memory, workaround
|
||||
|
||||
echo "${output}" | head -1 > tmp_file_out
|
||||
echo "${output}" | grep -v "^Unsupported\|^$" | head -1 > tmp_file_out
|
||||
echo "${search}" > tmp_file_search
|
||||
|
||||
out_md5=$(md5sum tmp_file_out | cut -d' ' -f1)
|
||||
@ -1180,7 +1180,7 @@ function attack_3()
|
||||
|
||||
# out-of-memory, workaround
|
||||
|
||||
echo "${output}" | head -1 > tmp_file_out
|
||||
echo "${output}" | grep -v "^Unsupported\|^$" | head -1 > tmp_file_out
|
||||
echo "${search}" > tmp_file_search
|
||||
|
||||
out_md5=$(md5sum tmp_file_out | cut -d' ' -f1)
|
||||
@ -1840,9 +1840,10 @@ function attack_6()
|
||||
newRet=$?
|
||||
|
||||
if [ "${newRet}" -eq 2 ]; then
|
||||
|
||||
# out-of-memory, workaround
|
||||
|
||||
echo "${output}" | head -1 > tmp_file_out
|
||||
echo "${output}" | grep -v "^Unsupported\|^$" | head -1 > tmp_file_out
|
||||
echo "${search}" > tmp_file_search
|
||||
|
||||
out_md5=$(md5sum tmp_file_out | cut -d' ' -f1)
|
||||
@ -2273,7 +2274,7 @@ function attack_7()
|
||||
|
||||
# out-of-memory, workaround
|
||||
|
||||
echo "${output}" | head -1 > tmp_file_out
|
||||
echo "${output}" | grep -v "^Unsupported\|^$" | head -1 > tmp_file_out
|
||||
echo "${search}" > tmp_file_search
|
||||
|
||||
out_md5=$(md5sum tmp_file_out | cut -d' ' -f1)
|
||||
@ -2287,7 +2288,6 @@ function attack_7()
|
||||
fi
|
||||
|
||||
if [ "${newRet}" -ne 0 ]; then
|
||||
|
||||
if [ "${newRet}" -eq 2 ]; then
|
||||
ret=20
|
||||
else
|
||||
|
@ -21,9 +21,6 @@ sub module_generate_hash
|
||||
my $iv = shift // random_hex_string (32);
|
||||
my $ct = shift;
|
||||
|
||||
my $ct_min_len = 30;
|
||||
my $ct_max_len = 64;
|
||||
|
||||
my $kdf = Crypt::PBKDF2->new
|
||||
(
|
||||
hasher => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 256),
|
||||
@ -31,34 +28,18 @@ sub module_generate_hash
|
||||
output_len => 32
|
||||
);
|
||||
|
||||
my $ct_len = 64;
|
||||
|
||||
my $salt_bin = pack ("H*", $salt);
|
||||
|
||||
my $key = $kdf->PBKDF2 ($salt_bin, $word);
|
||||
|
||||
my $iv_bin = pack ("H*", $iv);
|
||||
|
||||
my $pt;
|
||||
|
||||
if (defined $ct)
|
||||
{
|
||||
my $ct_bin = pack ("H*", $ct);
|
||||
my $pt = "[{\"type\":\"HD Key Tree\",\"data\":{\"mnemonic\":[112,97,121,109,101,110,116,32,117,112,115,101,116,32,109,101,116,97,108,32,99,104,97,112,116,101,114,32,114,117,110,32,97,100,109,105,116,32,109,101,97,115,117,114,101,32,114,101,109,105,110,100,32,115,117,112,112,108,121,32,104,111,112,101,32,101,110,101,109,121,32,104,101,100,103,101,104,111,103],\"numberOfAccounts\":1,\"hdPath\":\"m/44'/60'/0'/0\"}}]";
|
||||
|
||||
my $data_bin = $ct_bin;
|
||||
|
||||
my $aes = Crypt::AuthEnc::GCM->new ("AES", $key, $iv_bin);
|
||||
|
||||
$pt = $aes->decrypt_add ($data_bin);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
# generate plaintext
|
||||
|
||||
# TODO now the data is all ASCII 'a', would be better to have it mimic the same structure as the reference data:
|
||||
# [{"type":"HD Key Tree","data":{"mnemonic":[112,97,121,109,101,110,116,32,117,112,115,101,116,32,109,101,116,97,108,32,99,104,97,112,116,101,114,32,114,117,110,32,97,100,109,105,116,32,109,101,97,115,117,114,101,32,114,101,109,105,110,100,32,115,117,112,112,108,121,32,104,111,112,101,32,101,110,101,109,121,32,104,101,100,103,101,104,111,103],"numberOfAccounts":1,"hdPath":"m/44'/60'/0'/0"}}]
|
||||
# generated from tools/2hashcat_tests/metamask2hashcat-test.py
|
||||
$pt = "a" x ($ct_min_len + int (rand ($ct_max_len - $ct_min_len)) + 1);
|
||||
}
|
||||
$pt = substr ($pt, 0, $ct_len);
|
||||
|
||||
my $aes = Crypt::AuthEnc::GCM->new ("AES", $key, $iv_bin);
|
||||
|
||||
@ -80,7 +61,7 @@ sub module_verify_hash
|
||||
my $hash = substr ($line, 0, $idx);
|
||||
my $word = substr ($line, $idx + 1);
|
||||
|
||||
return unless substr ($hash, 0, 10) eq '$metamask-short$';
|
||||
return unless substr ($hash, 0, 16) eq '$metamask-short$';
|
||||
|
||||
my (undef, $signature, $salt, $iv, $ct) = split '\$', $hash;
|
||||
|
||||
@ -95,12 +76,7 @@ sub module_verify_hash
|
||||
|
||||
return unless length $salt_bin == 32;
|
||||
return unless length $iv_bin == 16;
|
||||
|
||||
my $ct_len = length ($ct_bin);
|
||||
my $ct_min_len = 30;
|
||||
my $ct_max_len = 3136;
|
||||
|
||||
return unless ($ct_len >= $ct_min_len && $ct_len <= $ct_max_len);
|
||||
return unless length $ct_bin == 64;
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
|
@ -12,7 +12,7 @@ use Crypt::ScryptKDF qw (scrypt_raw);
|
||||
use Encode;
|
||||
use Crypt::CBC;
|
||||
|
||||
sub module_constraints { [[0, 256], [8, 8], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
sub module_constraints { [[8, 256], [8, 8], [-1, -1], [-1, -1], [-1, -1]] }
|
||||
|
||||
my $SCRYPT_N = 32768;
|
||||
my $SCRYPT_R = 8;
|
||||
|
Loading…
Reference in New Issue
Block a user