Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic iteration count support for hashmodes 26600 and 26610 (Metamask) #3952

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

its5Q
Copy link

@its5Q its5Q commented Feb 21, 2024

Newer metamask versions have an iteration count of 600000 and the iteration count is stored in the vault's JSON. This PR adds support for vaults created with the new version by introducing hashmodes that support an arbitrary iteration count. It also updates the metamask2hashcat tool to parse iteration count if it's present.

tools/metamask2hashcat.py Outdated Show resolved Hide resolved
Comment on lines 149 to 150
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_DIGIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot TOKEN_ATTR_OPTIONAL_ROUNDS be used in old module?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me take a look at that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added support for dynamic iteration count to the old modules with TOKEN_ATTR_OPTIONAL_ROUNDS. One thing though, this attribute works kinda unintuitive and weird, as it actually acts both as a rounds count token, and a salt token at the same time, if that makes sense. Is that intended?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be a little bit unintuitive. I have seen another option with two different tokenizers.

Take a look.

if (strncmp (sigchk, SIGNATURE_SHA512MACOS, 4) == 0)
{
hc_token_t token;
memset (&token, 0, sizeof (hc_token_t));
token.token_cnt = 4;
token.signatures_cnt = 1;
token.signatures_buf[0] = SIGNATURE_SHA512MACOS;
token.len[0] = 4;
token.attr[0] = TOKEN_ATTR_FIXED_LENGTH
| TOKEN_ATTR_VERIFY_SIGNATURE;
token.sep[1] = '$';
token.len_min[1] = 1;
token.len_max[1] = 6;
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_DIGIT;
token.sep[2] = '$';
token.len[2] = 64;
token.attr[2] = TOKEN_ATTR_FIXED_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
token.len_min[3] = 128;
token.len_max[3] = 256;
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
const int hash_len = token.len[3];
if ((hash_len != 128) && (hash_len != 256)) return (PARSER_HASH_LENGTH);
const u8 *hash_pos = token.buf[3];
digest[0] = hex_to_u64 (hash_pos + 0);
digest[1] = hex_to_u64 (hash_pos + 16);
digest[2] = hex_to_u64 (hash_pos + 32);
digest[3] = hex_to_u64 (hash_pos + 48);
digest[4] = hex_to_u64 (hash_pos + 64);
digest[5] = hex_to_u64 (hash_pos + 80);
digest[6] = hex_to_u64 (hash_pos + 96);
digest[7] = hex_to_u64 (hash_pos + 112);
digest[0] = byte_swap_64 (digest[0]);
digest[1] = byte_swap_64 (digest[1]);
digest[2] = byte_swap_64 (digest[2]);
digest[3] = byte_swap_64 (digest[3]);
digest[4] = byte_swap_64 (digest[4]);
digest[5] = byte_swap_64 (digest[5]);
digest[6] = byte_swap_64 (digest[6]);
digest[7] = byte_swap_64 (digest[7]);
const u8 *salt_pos = token.buf[2];
const int salt_len = token.len[2] / 2;
pbkdf2_sha512->salt_buf[0] = hex_to_u32 (salt_pos + 0);
pbkdf2_sha512->salt_buf[1] = hex_to_u32 (salt_pos + 8);
pbkdf2_sha512->salt_buf[2] = hex_to_u32 (salt_pos + 16);
pbkdf2_sha512->salt_buf[3] = hex_to_u32 (salt_pos + 24);
pbkdf2_sha512->salt_buf[4] = hex_to_u32 (salt_pos + 32);
pbkdf2_sha512->salt_buf[5] = hex_to_u32 (salt_pos + 40);
pbkdf2_sha512->salt_buf[6] = hex_to_u32 (salt_pos + 48);
pbkdf2_sha512->salt_buf[7] = hex_to_u32 (salt_pos + 56);
salt->salt_buf[0] = pbkdf2_sha512->salt_buf[0];
salt->salt_buf[1] = pbkdf2_sha512->salt_buf[1];
salt->salt_buf[2] = pbkdf2_sha512->salt_buf[2];
salt->salt_buf[3] = pbkdf2_sha512->salt_buf[3];
salt->salt_buf[4] = pbkdf2_sha512->salt_buf[4];
salt->salt_buf[5] = pbkdf2_sha512->salt_buf[5];
salt->salt_buf[6] = pbkdf2_sha512->salt_buf[6];
salt->salt_buf[7] = pbkdf2_sha512->salt_buf[7];
salt->salt_len = salt_len;
const u8 *iter_pos = token.buf[1];
salt->salt_iter = hc_strtoul ((const char *) iter_pos, NULL, 10) - 1;
return (PARSER_OK);
}
if (strncmp (sigchk, SIGNATURE_SHA512MACOS_JOHN, 20) == 0)
{
hc_token_t token;
memset (&token, 0, sizeof (hc_token_t));
token.token_cnt = 7;
token.signatures_cnt = 1;
token.signatures_buf[0] = SIGNATURE_SHA512MACOS_JOHN;
token.len[0] = 20;
token.attr[0] = TOKEN_ATTR_FIXED_LENGTH
| TOKEN_ATTR_VERIFY_SIGNATURE;
token.len_min[1] = 1;
token.len_max[1] = 6;
token.sep[1] = '.';
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_DIGIT;
token.len_min[2] = 64;
token.len_max[2] = 64;
token.sep[2] = '.';
token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
token.len_min[3] = 128;
token.len_max[3] = 256;
token.sep[3] = ':';
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
| TOKEN_ATTR_VERIFY_HEX;
token.len_min[4] = 0;
token.len_max[4] = 16;
token.sep[4] = ':';
token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH;
token.len_min[5] = 0;
token.len_max[5] = 16;
token.sep[5] = ':';
token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH;
token.len_min[6] = 0;
token.len_max[6] = 32;
token.attr[6] = TOKEN_ATTR_VERIFY_LENGTH;
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
const int hash_len = token.len[3];
if ((hash_len != 128) && (hash_len != 256)) return (PARSER_HASH_LENGTH);
const u8 *hash_pos = token.buf[3];
digest[0] = hex_to_u64 (hash_pos + 0);
digest[1] = hex_to_u64 (hash_pos + 16);
digest[2] = hex_to_u64 (hash_pos + 32);
digest[3] = hex_to_u64 (hash_pos + 48);
digest[4] = hex_to_u64 (hash_pos + 64);
digest[5] = hex_to_u64 (hash_pos + 80);
digest[6] = hex_to_u64 (hash_pos + 96);
digest[7] = hex_to_u64 (hash_pos + 112);
digest[0] = byte_swap_64 (digest[0]);
digest[1] = byte_swap_64 (digest[1]);
digest[2] = byte_swap_64 (digest[2]);
digest[3] = byte_swap_64 (digest[3]);
digest[4] = byte_swap_64 (digest[4]);
digest[5] = byte_swap_64 (digest[5]);
digest[6] = byte_swap_64 (digest[6]);
digest[7] = byte_swap_64 (digest[7]);
const u8 *salt_pos = token.buf[2];
const int salt_len = token.len[2] / 2;
pbkdf2_sha512->salt_buf[0] = hex_to_u32 (salt_pos + 0);
pbkdf2_sha512->salt_buf[1] = hex_to_u32 (salt_pos + 8);
pbkdf2_sha512->salt_buf[2] = hex_to_u32 (salt_pos + 16);
pbkdf2_sha512->salt_buf[3] = hex_to_u32 (salt_pos + 24);
pbkdf2_sha512->salt_buf[4] = hex_to_u32 (salt_pos + 32);
pbkdf2_sha512->salt_buf[5] = hex_to_u32 (salt_pos + 40);
pbkdf2_sha512->salt_buf[6] = hex_to_u32 (salt_pos + 48);
pbkdf2_sha512->salt_buf[7] = hex_to_u32 (salt_pos + 56);
salt->salt_buf[0] = pbkdf2_sha512->salt_buf[0];
salt->salt_buf[1] = pbkdf2_sha512->salt_buf[1];
salt->salt_buf[2] = pbkdf2_sha512->salt_buf[2];
salt->salt_buf[3] = pbkdf2_sha512->salt_buf[3];
salt->salt_buf[4] = pbkdf2_sha512->salt_buf[4];
salt->salt_buf[5] = pbkdf2_sha512->salt_buf[5];
salt->salt_buf[6] = pbkdf2_sha512->salt_buf[6];
salt->salt_buf[7] = pbkdf2_sha512->salt_buf[7];
salt->salt_len = salt_len;
const u8 *iter_pos = token.buf[1];
salt->salt_iter = hc_strtoul ((const char *) iter_pos, NULL, 10) - 1;
return (PARSER_OK);
}

An opinion from maintainers would be very helpful.

@its5Q
Copy link
Author

its5Q commented Feb 24, 2024

I've updated the metamask2hashcat tool to use the new format and added a test vault JSON that you could use it on to try out the new dynamic iteration count support. If everything else looks good, I think it can be merged.

@its5Q its5Q changed the title Add hashmodes 26620 and 26630 for Metamask with dynamic iteration count Add dynamic iteration count support for hashmodes 26600 and 26610 (Metamask) Mar 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants