mirror of
https://github.com/hashcat/hashcat.git
synced 2024-11-22 08:08:10 +00:00
change hash-signature for 26610 (incompatible with 26600), remove debug print statements in attacks, add comments, add reference data
This commit is contained in:
parent
248c4afc09
commit
5208447e72
@ -335,7 +335,6 @@ KERNEL_FQ void m26610_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha256_tmp_t, pbkdf2_sh
|
|||||||
AES_GCM_Init (ukey, key_len, key, subKey, s_te0, s_te1, s_te2, s_te3, s_te4);
|
AES_GCM_Init (ukey, key_len, key, subKey, s_te0, s_te1, s_te2, s_te3, s_te4);
|
||||||
|
|
||||||
// iv
|
// iv
|
||||||
|
|
||||||
const u32 iv[4] = {
|
const u32 iv[4] = {
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].iv_buf[0],
|
esalt_bufs[DIGESTS_OFFSET_HOST].iv_buf[0],
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].iv_buf[1],
|
esalt_bufs[DIGESTS_OFFSET_HOST].iv_buf[1],
|
||||||
@ -349,33 +348,21 @@ KERNEL_FQ void m26610_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha256_tmp_t, pbkdf2_sh
|
|||||||
|
|
||||||
AES_GCM_Prepare_J0 (iv, iv_len, subKey, J0);
|
AES_GCM_Prepare_J0 (iv, iv_len, subKey, J0);
|
||||||
|
|
||||||
// ct
|
//ct
|
||||||
|
|
||||||
//u32 T[4] = { 0 };
|
|
||||||
u32 ct[4] = {
|
u32 ct[4] = {
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[0],
|
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[0],
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[1],
|
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[1],
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[2],
|
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[2],
|
||||||
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[3]
|
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[3]
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 pt[4] = { 0 };
|
u32 pt[4] = { 0 };
|
||||||
|
|
||||||
//u32 S_len = 16;
|
|
||||||
//u32 aad_buf[4] = { 0 };
|
|
||||||
//u32 aad_len = 0;
|
|
||||||
|
|
||||||
//AES_GCM_GHASH_GLOBAL (subKey, aad_buf, aad_len, esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf, esalt_bufs[DIGESTS_OFFSET_HOST].ct_len, S);
|
|
||||||
|
|
||||||
//AES_GCM_GCTR (key, J0, S, S_len, T, s_te0, s_te1, s_te2, s_te3, s_te4);
|
|
||||||
|
|
||||||
// we try to decrypt the ciphertext
|
// we try to decrypt the ciphertext
|
||||||
AES_GCM_inc32(J0); // the first ctr is used to compute the tag, only the second is used for decryption: https://en.wikipedia.org/wiki/Galois/Counter_Mode#/media/File:GCM-Galois_Counter_Mode_with_IV.svg
|
AES_GCM_inc32(J0); // the first ctr is used to compute the tag, only the second is used for decryption: https://en.wikipedia.org/wiki/Galois/Counter_Mode#/media/File:GCM-Galois_Counter_Mode_with_IV.svg
|
||||||
AES_GCM_GCTR (key, J0, ct, 16, pt, s_te0, s_te1, s_te2, s_te3, s_te4); // decrypt the ciphertext
|
AES_GCM_GCTR (key, J0, ct, 16, pt, s_te0, s_te1, s_te2, s_te3, s_te4); // decrypt the ciphertext
|
||||||
|
|
||||||
|
// if ((gid == 0) && (lid == 0)) printf ("pt[0]=%08x\n", pt[0]); // should be 5b7b2274 or [{"type"
|
||||||
if ((gid == 0) && (lid == 0)) printf ("pt[0]=%08x\n", pt[0]); // should be 5b7b2274 or [{"type"
|
|
||||||
|
|
||||||
|
|
||||||
// cast plaintext buffer to byte such that we can do a byte per byte comparison
|
// cast plaintext buffer to byte such that we can do a byte per byte comparison
|
||||||
PRIVATE_AS const u32 *u32OutBufPtr = (PRIVATE_AS u32 *) pt;
|
PRIVATE_AS const u32 *u32OutBufPtr = (PRIVATE_AS u32 *) pt;
|
||||||
@ -389,11 +376,12 @@ KERNEL_FQ void m26610_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha256_tmp_t, pbkdf2_sh
|
|||||||
for(int i=0;i<16;i++)
|
for(int i=0;i<16;i++)
|
||||||
{
|
{
|
||||||
if(u8OutBufPtr[i] >=20 && u8OutBufPtr[i] <= 0x7e) {
|
if(u8OutBufPtr[i] >=20 && u8OutBufPtr[i] <= 0x7e) {
|
||||||
if ((gid == 0) && (lid == 0)) printf("correct ASCII byte[%d]=0x%02x\n", i, u8OutBufPtr[i]);
|
//if ((gid == 0) && (lid == 0)) printf("correct ASCII byte[%d]=0x%02x\n", i, u8OutBufPtr[i]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((gid == 0) && (lid == 0)) printf("NOT correct! byte[%d]=0x%02x\n", i, u8OutBufPtr[i]);
|
//if ((gid == 0) && (lid == 0)) printf("NOT correct! byte[%d]=0x%02x\n", i, u8OutBufPtr[i]);
|
||||||
correct = false;
|
correct = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,23 +393,17 @@ KERNEL_FQ void m26610_comp (KERN_ATTR_TMPS_ESALT (pbkdf2_sha256_tmp_t, pbkdf2_sh
|
|||||||
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[3],
|
esalt_bufs[DIGESTS_OFFSET_HOST].ct_buf[3],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//if ((gid == 0) && (lid == 0)) printf ("ct[0]=%08x\n", ct[0]);
|
||||||
if ((gid == 0) && (lid == 0)) printf ("ct[0]=%08x\n", ct[0]);
|
//if ((gid == 0) && (lid == 0)) printf ("ct[1]=%08x\n", ct[1]);
|
||||||
if ((gid == 0) && (lid == 0)) printf ("ct[1]=%08x\n", ct[1]);
|
//if ((gid == 0) && (lid == 0)) printf ("ct[2]=%08x\n", ct[2]);
|
||||||
if ((gid == 0) && (lid == 0)) printf ("ct[2]=%08x\n", ct[2]);
|
//if ((gid == 0) && (lid == 0)) printf ("ct[3]=%08x\n", ct[3]);
|
||||||
if ((gid == 0) && (lid == 0)) printf ("ct[3]=%08x\n", ct[3]);
|
|
||||||
if ((gid == 0) && (lid == 0)) printf("here0\n");
|
|
||||||
|
|
||||||
if (correct)
|
if (correct)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((gid == 0) && (lid == 0)) printf("here1\n");
|
|
||||||
int digest_pos = find_hash (digest, DIGESTS_CNT, &digests_buf[DIGESTS_OFFSET_HOST]);
|
int digest_pos = find_hash (digest, DIGESTS_CNT, &digests_buf[DIGESTS_OFFSET_HOST]);
|
||||||
|
|
||||||
if (digest_pos != -1)
|
if (digest_pos != -1)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((gid == 0) && (lid == 0)) printf("here2\n");
|
|
||||||
const u32 final_hash_pos = DIGESTS_OFFSET_HOST + digest_pos;
|
const u32 final_hash_pos = DIGESTS_OFFSET_HOST + digest_pos;
|
||||||
|
|
||||||
if (hc_atomic_inc (&hashes_shown[final_hash_pos]) == 0)
|
if (hc_atomic_inc (&hashes_shown[final_hash_pos]) == 0)
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
- Added hash-mode: HMAC-RIPEMD160 (key = $salt)
|
- Added hash-mode: HMAC-RIPEMD160 (key = $salt)
|
||||||
- Added hash-mode: bcrypt(sha256($pass))
|
- Added hash-mode: bcrypt(sha256($pass))
|
||||||
- Added hash-mode: md5(md5($salt).md5(md5($pass)))
|
- Added hash-mode: md5(md5($salt).md5(md5($pass)))
|
||||||
|
- Added hash-mode: metamask (26610) with plaintext check instead of checking tag (26600). No longer needs all data in hash.
|
||||||
|
|
||||||
##
|
##
|
||||||
## Performance
|
## Performance
|
||||||
|
@ -18,7 +18,8 @@ static const u32 DGST_POS2 = 2;
|
|||||||
static const u32 DGST_POS3 = 3;
|
static const u32 DGST_POS3 = 3;
|
||||||
static const u32 DGST_SIZE = DGST_SIZE_4_4;
|
static const u32 DGST_SIZE = DGST_SIZE_4_4;
|
||||||
static const u32 HASH_CATEGORY = HASH_CATEGORY_CRYPTOCURRENCY_WALLET;
|
static const u32 HASH_CATEGORY = HASH_CATEGORY_CRYPTOCURRENCY_WALLET;
|
||||||
static const char *HASH_NAME = "MetaMask Wallet short data";
|
// 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 u64 KERN_TYPE = 26610;
|
||||||
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
|
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
|
||||||
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
|
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
|
||||||
@ -26,6 +27,7 @@ static const u64 OPTS_TYPE = OPTS_TYPE_STOCK_MODULE
|
|||||||
| OPTS_TYPE_PT_GENERATE_LE;
|
| OPTS_TYPE_PT_GENERATE_LE;
|
||||||
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
|
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
|
||||||
static const char *ST_PASS = "hashcat1";
|
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==";
|
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; }
|
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; }
|
||||||
@ -237,15 +239,7 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE
|
|||||||
digest[1] = (metamask->ct_buf[1]);
|
digest[1] = (metamask->ct_buf[1]);
|
||||||
digest[2] = (metamask->ct_buf[2]);
|
digest[2] = (metamask->ct_buf[2]);
|
||||||
digest[3] = (metamask->ct_buf[3]);
|
digest[3] = (metamask->ct_buf[3]);
|
||||||
|
|
||||||
printf ("ct_buf[0]=%08x\n", metamask->ct_buf[0]);
|
|
||||||
printf ("ct_buf[1]=%08x\n", metamask->ct_buf[1]);
|
|
||||||
printf ("ct_buf[2]=%08x\n", metamask->ct_buf[2]);
|
|
||||||
printf ("ct_buf[3]=%08x\n", metamask->ct_buf[3]);
|
|
||||||
printf ("digest[0]=%08x\n", digest[0]);
|
|
||||||
printf ("digest[1]=%08x\n", digest[1]);
|
|
||||||
printf ("digest[2]=%08x\n", digest[2]);
|
|
||||||
printf ("digest[3]=%08x\n", digest[3]);
|
|
||||||
return (PARSER_OK);
|
return (PARSER_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
tools/2hashcat_tests/metamask2hashcat-test.py
Normal file
41
tools/2hashcat_tests/metamask2hashcat-test.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from base64 import b64decode
|
||||||
|
from hashlib import pbkdf2_hmac
|
||||||
|
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
|
||||||
|
#TODO perhaps load the vault from tools/2hashcat_tests/metamask2hashcat.json similar as in tools/metamask2hashcat.py
|
||||||
|
vault = {"data":"R95fzGt4UQ0uwrcrVYnIi4UcSlWn9wlmer+//526ZDwYAp50K82F1u1oacYcdjjhuEvbZnWk/uBG00UkgLLlO3WbINljqmu2QWdDEwjTgo/qWR6MU9d/82rxNiONHQE8UrZ8SV+htVr6XIB0ze3aCV0E+fwI93EeP79ZeDxuOEhuHoiYT0bHWMv5nA48AdluG4DbOo7SrDAWBVCBsEdXsOfYsS3/TIh0a/iFCMX4uhxY2824JwcWp4H36SFWyBYMZCJ3/U4DYFbbjWZtGRthoJlIik5BJq4FLu3Y1jEgza0AWlAvu4MKTEqrYSpUIghfxf1a1f+kPvxsHNq0as0kRwCXu09DObbdsiggbmeoBkxMZiFq0d9ar/3Gon0r3hfc3c124Wlivzbzu1JcZ3wURhLSsUS7b5cfG86aXHJkxmQDA5urBz6lw3bsIvlEUB2ErkQy/zD+cPwCG1Rs/WKt7KNh45lppCUkHccbf+xlpdc8OfUwj01Xp7BdH8LMR7Vx1C4hZCvSdtURVl0VaAMxHDX0MjRkwmqS","iv":"h+BoIf2CQ5BEjaIOShFE7g==","salt":"jfGI3TXguhb8GPnKSXFrMzRk2NCEc131Gt5G3kZr5+s="}
|
||||||
|
password = "hashcat1"
|
||||||
|
|
||||||
|
salt = b64decode(vault["salt"])
|
||||||
|
key = pbkdf2_hmac("sha256", password.encode(), salt, 10_000)
|
||||||
|
|
||||||
|
iv = b64decode(vault["iv"])
|
||||||
|
payload = b64decode(vault["data"])
|
||||||
|
ciphertext = payload[:-16]
|
||||||
|
print(f"ciphertext.hex()={ciphertext.hex()[0:128]}")
|
||||||
|
tag = payload[-16:]
|
||||||
|
|
||||||
|
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
|
||||||
|
plaintext = cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
print(plaintext.hex()[0:128])
|
||||||
|
print(str(plaintext[0:128]))
|
||||||
|
|
||||||
|
print()
|
||||||
|
try:
|
||||||
|
cipher.verify(tag)
|
||||||
|
print("The message is authentic:", plaintext.decode())
|
||||||
|
except ValueError:
|
||||||
|
print("Key incorrect or message corrupted")
|
||||||
|
print()
|
||||||
|
|
||||||
|
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
|
||||||
|
plaintext = cipher.decrypt(ciphertext[:32])
|
||||||
|
print("Partially encrypted message (32 bytes):", plaintext.decode())
|
||||||
|
|
||||||
|
cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
|
||||||
|
plaintext = cipher.decrypt(ciphertext[:450])
|
||||||
|
print("Partially encrypted message (450 bytes):", plaintext.decode())
|
1
tools/2hashcat_tests/metamask2hashcat.json
Normal file
1
tools/2hashcat_tests/metamask2hashcat.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"data":"R95fzGt4UQ0uwrcrVYnIi4UcSlWn9wlmer+//526ZDwYAp50K82F1u1oacYcdjjhuEvbZnWk/uBG00UkgLLlO3WbINljqmu2QWdDEwjTgo/qWR6MU9d/82rxNiONHQE8UrZ8SV+htVr6XIB0ze3aCV0E+fwI93EeP79ZeDxuOEhuHoiYT0bHWMv5nA48AdluG4DbOo7SrDAWBVCBsEdXsOfYsS3/TIh0a/iFCMX4uhxY2824JwcWp4H36SFWyBYMZCJ3/U4DYFbbjWZtGRthoJlIik5BJq4FLu3Y1jEgza0AWlAvu4MKTEqrYSpUIghfxf1a1f+kPvxsHNq0as0kRwCXu09DObbdsiggbmeoBkxMZiFq0d9ar/3Gon0r3hfc3c124Wlivzbzu1JcZ3wURhLSsUS7b5cfG86aXHJkxmQDA5urBz6lw3bsIvlEUB2ErkQy/zD+cPwCG1Rs/WKt7KNh45lppCUkHccbf+xlpdc8OfUwj01Xp7BdH8LMR7Vx1C4hZCvSdtURVl0VaAMxHDX0MjRkwmqS","iv":"h+BoIf2CQ5BEjaIOShFE7g==","salt":"jfGI3TXguhb8GPnKSXFrMzRk2NCEc131Gt5G3kZr5+s="}
|
@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import argparse
|
import argparse
|
||||||
|
import base64
|
||||||
|
|
||||||
def metamask_parser(file):
|
def metamask_parser(file, shortdata):
|
||||||
try:
|
try:
|
||||||
f = open(file)
|
f = open(file)
|
||||||
|
|
||||||
@ -23,7 +24,13 @@ def metamask_parser(file):
|
|||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
print('$metamask$' + j['salt'] + '$' + j['iv'] + '$' + j['data'])
|
if((len(j['data']) > 3000) or shortdata):
|
||||||
|
print("! Data too long, we limit it to 64 bytes, this hash can only be used with m26610!")
|
||||||
|
data_bin = base64.b64decode(j['data'])
|
||||||
|
j['data'] = base64.b64encode(data_bin[0:64]).decode("ascii")
|
||||||
|
print('$metamask-short$' + j['salt'] + '$' + j['iv'] + '$' + j['data'])
|
||||||
|
else:
|
||||||
|
print('$metamask$' + j['salt'] + '$' + j['iv'] + '$' + j['data'])
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(1)
|
exit(1)
|
||||||
@ -33,10 +40,12 @@ def metamask_parser(file):
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description="metamask2hashcat.py extraction tool")
|
parser = argparse.ArgumentParser(description="metamask2hashcat.py extraction tool")
|
||||||
parser.add_argument('--vault', required=True, help='set metamask vault (json) file from path', type=str)
|
parser.add_argument('--vault', required=True, help='set metamask vault (json) file from path', type=str)
|
||||||
|
parser.add_argument('--shortdata', help='force short data, can only be used with m26610, ', action='store_true')
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.vault:
|
if args.vault:
|
||||||
metamask_parser(args.vault)
|
metamask_parser(args.vault, args.shortdata)
|
||||||
else:
|
else:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(1)
|
exit(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user