diff --git a/OpenCL/m09800_a0-optimized.cl b/OpenCL/m09800_a0-optimized.cl index ffa5c1388..3257c0cbb 100644 --- a/OpenCL/m09800_a0-optimized.cl +++ b/OpenCL/m09800_a0-optimized.cl @@ -17,11 +17,15 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -252,21 +256,21 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -279,6 +283,8 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -337,7 +343,93 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_M_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + int digest_pos = find_hash (out, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } @@ -464,21 +556,21 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -491,6 +583,8 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -549,7 +643,92 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_S_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + if (out[0] != search[0]) continue; + if (out[1] != search[1]) continue; + if (out[2] != search[2]) continue; + if (out[3] != search[3]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } diff --git a/OpenCL/m09800_a1-optimized.cl b/OpenCL/m09800_a1-optimized.cl index 07bfb15ca..891d7ca67 100644 --- a/OpenCL/m09800_a1-optimized.cl +++ b/OpenCL/m09800_a1-optimized.cl @@ -15,11 +15,15 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -300,21 +304,21 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -327,6 +331,8 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -385,7 +391,93 @@ KERNEL_FQ void m09800_m04 (KERN_ATTR_ESALT (oldoffice34_t)) rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_M_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + int digest_pos = find_hash (out, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } @@ -562,21 +654,21 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -589,6 +681,8 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -647,7 +741,92 @@ KERNEL_FQ void m09800_s04 (KERN_ATTR_ESALT (oldoffice34_t)) rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_S_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + if (out[0] != search[0]) continue; + if (out[1] != search[1]) continue; + if (out[2] != search[2]) continue; + if (out[3] != search[3]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } diff --git a/OpenCL/m09800_a3-optimized.cl b/OpenCL/m09800_a3-optimized.cl index 303b177a8..8315abfdf 100644 --- a/OpenCL/m09800_a3-optimized.cl +++ b/OpenCL/m09800_a3-optimized.cl @@ -12,11 +12,15 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -223,21 +227,21 @@ DECLSPEC void m09800m (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 w3_t[2] = 0; w3_t[3] = pw_salt_len * 8; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, pass_hash); - w0_t[0] = digest[0]; - w0_t[1] = digest[1]; - w0_t[2] = digest[2]; - w0_t[3] = digest[3]; - w1_t[0] = digest[4]; + w0_t[0] = pass_hash[0]; + w0_t[1] = pass_hash[1]; + w0_t[2] = pass_hash[2]; + w0_t[3] = pass_hash[3]; + w1_t[0] = pass_hash[4]; w1_t[1] = 0; w1_t[2] = 0x80000000; w1_t[3] = 0; @@ -250,6 +254,8 @@ DECLSPEC void m09800m (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 w3_t[2] = 0; w3_t[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -308,7 +314,93 @@ DECLSPEC void m09800m (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_M_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + int digest_pos = find_hash (out, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } @@ -403,21 +495,21 @@ DECLSPEC void m09800s (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 w3_t[2] = 0; w3_t[3] = pw_salt_len * 8; - u32 digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, pass_hash); - w0_t[0] = digest[0]; - w0_t[1] = digest[1]; - w0_t[2] = digest[2]; - w0_t[3] = digest[3]; - w1_t[0] = digest[4]; + w0_t[0] = pass_hash[0]; + w0_t[1] = pass_hash[1]; + w0_t[2] = pass_hash[2]; + w0_t[3] = pass_hash[3]; + w1_t[0] = pass_hash[4]; w1_t[1] = 0; w1_t[2] = 0x80000000; w1_t[3] = 0; @@ -430,6 +522,8 @@ DECLSPEC void m09800s (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 w3_t[2] = 0; w3_t[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; @@ -488,7 +582,92 @@ DECLSPEC void m09800s (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u3 rc4_next_16 (rc4_key, 16, j, digest, out); - COMPARE_S_SIMD (out[0], out[1], out[2], out[3]); + // initial compare + + if (out[0] != search[0]) continue; + if (out[1] != search[1]) continue; + if (out[2] != search[2]) continue; + if (out[3] != search[3]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } diff --git a/OpenCL/m09810_a0-optimized.cl b/OpenCL/m09810_a0-optimized.cl index 5db2264a6..3b911251c 100644 --- a/OpenCL/m09810_a0-optimized.cl +++ b/OpenCL/m09810_a0-optimized.cl @@ -22,6 +22,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; diff --git a/OpenCL/m09810_a1-optimized.cl b/OpenCL/m09810_a1-optimized.cl index 69ecab5c3..b488cdf49 100644 --- a/OpenCL/m09810_a1-optimized.cl +++ b/OpenCL/m09810_a1-optimized.cl @@ -20,6 +20,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; diff --git a/OpenCL/m09810_a3-optimized.cl b/OpenCL/m09810_a3-optimized.cl index 495adc734..760dcb932 100644 --- a/OpenCL/m09810_a3-optimized.cl +++ b/OpenCL/m09810_a3-optimized.cl @@ -20,6 +20,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; diff --git a/OpenCL/m09820_a0-optimized.cl b/OpenCL/m09820_a0-optimized.cl index 0e9a95ca6..3f4bfeb2b 100644 --- a/OpenCL/m09820_a0-optimized.cl +++ b/OpenCL/m09820_a0-optimized.cl @@ -3,7 +3,8 @@ * License.....: MIT */ -#define NEW_SIMD_CODE +//too much register pressure +//#define NEW_SIMD_CODE #ifdef KERNEL_STATIC #include "inc_vendor.h" @@ -16,15 +17,142 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; +typedef struct +{ + u8 S[256]; + + u32 wtf_its_faster; + +} RC4_KEY; + +DECLSPEC void swap (LOCAL_AS RC4_KEY *rc4_key, const u8 i, const u8 j) +{ + u8 tmp; + + tmp = rc4_key->S[i]; + rc4_key->S[i] = rc4_key->S[j]; + rc4_key->S[j] = tmp; +} + +DECLSPEC void rc4_init_16 (LOCAL_AS RC4_KEY *rc4_key, const u32 *data) +{ + u32 v = 0x03020100; + u32 a = 0x04040404; + + LOCAL_AS u32 *ptr = (LOCAL_AS u32 *) rc4_key->S; + + #ifdef _unroll + #pragma unroll + #endif + for (u32 i = 0; i < 64; i++) + { + *ptr++ = v; v += a; + } + + u32 j = 0; + + for (u32 i = 0; i < 16; i++) + { + u32 idx = i * 16; + + u32 v; + + v = data[0]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[1]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[2]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[3]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + } +} + +DECLSPEC u8 rc4_next_16 (LOCAL_AS RC4_KEY *rc4_key, u8 i, u8 j, const u32 *in, u32 *out) +{ + #ifdef _unroll + #pragma unroll + #endif + for (u32 k = 0; k < 4; k++) + { + u32 xor4 = 0; + + u8 idx; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 0; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 8; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 16; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 24; + + out[k] = in[k] ^ xor4; + } + + return j; +} + KERNEL_FQ void m09820_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) { /** @@ -55,6 +183,14 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; + /** + * shared + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -107,21 +243,21 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -134,20 +270,110 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_M_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + int digest_pos = find_hash (digest, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } @@ -189,6 +415,14 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; + /** + * shared + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -253,21 +487,21 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -280,20 +514,107 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_RULES_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_S_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + if (digest[0] != search[0]) continue; + if (digest[1] != search[1]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } diff --git a/OpenCL/m09820_a1-optimized.cl b/OpenCL/m09820_a1-optimized.cl index 028b3d28f..bedc61bb8 100644 --- a/OpenCL/m09820_a1-optimized.cl +++ b/OpenCL/m09820_a1-optimized.cl @@ -3,7 +3,8 @@ * License.....: MIT */ -#define NEW_SIMD_CODE +//too much register pressure +//#define NEW_SIMD_CODE #ifdef KERNEL_STATIC #include "inc_vendor.h" @@ -14,15 +15,142 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; +typedef struct +{ + u8 S[256]; + + u32 wtf_its_faster; + +} RC4_KEY; + +DECLSPEC void swap (LOCAL_AS RC4_KEY *rc4_key, const u8 i, const u8 j) +{ + u8 tmp; + + tmp = rc4_key->S[i]; + rc4_key->S[i] = rc4_key->S[j]; + rc4_key->S[j] = tmp; +} + +DECLSPEC void rc4_init_16 (LOCAL_AS RC4_KEY *rc4_key, const u32 *data) +{ + u32 v = 0x03020100; + u32 a = 0x04040404; + + LOCAL_AS u32 *ptr = (LOCAL_AS u32 *) rc4_key->S; + + #ifdef _unroll + #pragma unroll + #endif + for (u32 i = 0; i < 64; i++) + { + *ptr++ = v; v += a; + } + + u32 j = 0; + + for (u32 i = 0; i < 16; i++) + { + u32 idx = i * 16; + + u32 v; + + v = data[0]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[1]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[2]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[3]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + } +} + +DECLSPEC u8 rc4_next_16 (LOCAL_AS RC4_KEY *rc4_key, u8 i, u8 j, const u32 *in, u32 *out) +{ + #ifdef _unroll + #pragma unroll + #endif + for (u32 k = 0; k < 4; k++) + { + u32 xor4 = 0; + + u8 idx; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 0; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 8; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 16; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 24; + + out[k] = in[k] ^ xor4; + } + + return j; +} + KERNEL_FQ void m09820_m04 (KERN_ATTR_ESALT (oldoffice34_t)) { /** @@ -53,6 +181,14 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_l_len = pws[gid].pw_len & 63; + /** + * shared + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -155,21 +291,21 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -182,20 +318,110 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_M_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + int digest_pos = find_hash (digest, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } @@ -237,6 +463,14 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_l_len = pws[gid].pw_len & 63; + /** + * shared + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -351,21 +585,21 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_ESALT (oldoffice34_t)) w0[1] = salt_buf[1]; w0[0] = salt_buf[0]; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, pass_hash); - w0[0] = digest[0]; - w0[1] = digest[1]; - w0[2] = digest[2]; - w0[3] = digest[3]; - w1[0] = digest[4]; + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; w1[1] = 0; w1[2] = 0x80000000; w1[3] = 0; @@ -378,20 +612,107 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_ESALT (oldoffice34_t)) w3[2] = 0; w3[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0, w1, w2, w3, digest); + sha1_transform (w0, w1, w2, w3, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_S_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + if (digest[0] != search[0]) continue; + if (digest[1] != search[1]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } diff --git a/OpenCL/m09820_a3-optimized.cl b/OpenCL/m09820_a3-optimized.cl index cde918d0e..a0c0a568d 100644 --- a/OpenCL/m09820_a3-optimized.cl +++ b/OpenCL/m09820_a3-optimized.cl @@ -3,7 +3,8 @@ * License.....: MIT */ -#define NEW_SIMD_CODE +//too much register pressure +//#define NEW_SIMD_CODE #ifdef KERNEL_STATIC #include "inc_vendor.h" @@ -14,16 +15,143 @@ #include "inc_hash_sha1.cl" #endif +#define MIN_NULL_BYTES 10 + typedef struct oldoffice34 { u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; -DECLSPEC void m09820m (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KERN_ATTR_ESALT (oldoffice34_t)) +typedef struct +{ + u8 S[256]; + + u32 wtf_its_faster; + +} RC4_KEY; + +DECLSPEC void swap (LOCAL_AS RC4_KEY *rc4_key, const u8 i, const u8 j) +{ + u8 tmp; + + tmp = rc4_key->S[i]; + rc4_key->S[i] = rc4_key->S[j]; + rc4_key->S[j] = tmp; +} + +DECLSPEC void rc4_init_16 (LOCAL_AS RC4_KEY *rc4_key, const u32 *data) +{ + u32 v = 0x03020100; + u32 a = 0x04040404; + + LOCAL_AS u32 *ptr = (LOCAL_AS u32 *) rc4_key->S; + + #ifdef _unroll + #pragma unroll + #endif + for (u32 i = 0; i < 64; i++) + { + *ptr++ = v; v += a; + } + + u32 j = 0; + + for (u32 i = 0; i < 16; i++) + { + u32 idx = i * 16; + + u32 v; + + v = data[0]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[1]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[2]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + + v = data[3]; + + j += rc4_key->S[idx] + (v >> 0); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 8); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 16); swap (rc4_key, idx, j); idx++; + j += rc4_key->S[idx] + (v >> 24); swap (rc4_key, idx, j); idx++; + } +} + +DECLSPEC u8 rc4_next_16 (LOCAL_AS RC4_KEY *rc4_key, u8 i, u8 j, const u32 *in, u32 *out) +{ + #ifdef _unroll + #pragma unroll + #endif + for (u32 k = 0; k < 4; k++) + { + u32 xor4 = 0; + + u8 idx; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 0; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 8; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 16; + + i += 1; + j += rc4_key->S[i]; + + swap (rc4_key, i, j); + + idx = rc4_key->S[i] + rc4_key->S[j]; + + xor4 |= rc4_key->S[idx] << 24; + + out[k] = in[k] ^ xor4; + } + + return j; +} + +DECLSPEC void m09820m (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KERN_ATTR_ESALT (oldoffice34_t)) { /** * modifier @@ -32,6 +160,12 @@ DECLSPEC void m09820m (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER const u64 gid = get_global_id (0); const u64 lid = get_local_id (0); + /** + * shared + */ + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -81,21 +215,21 @@ DECLSPEC void m09820m (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER w3_t[2] = 0; w3_t[3] = (pw_len + 16) * 8; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, pass_hash); - w0_t[0] = digest[0]; - w0_t[1] = digest[1]; - w0_t[2] = digest[2]; - w0_t[3] = digest[3]; - w1_t[0] = digest[4]; + w0_t[0] = pass_hash[0]; + w0_t[1] = pass_hash[1]; + w0_t[2] = pass_hash[2]; + w0_t[3] = pass_hash[3]; + w1_t[0] = pass_hash[4]; w1_t[1] = 0; w1_t[2] = 0x80000000; w1_t[3] = 0; @@ -108,24 +242,114 @@ DECLSPEC void m09820m (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER w3_t[2] = 0; w3_t[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_M_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + int digest_pos = find_hash (digest, digests_cnt, &digests_buf[digests_offset]); + + if (digest_pos == -1) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + const u32 final_hash_pos = digests_offset + digest_pos; + + if (atomic_inc (&hashes_shown[final_hash_pos]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, digest_pos, final_hash_pos, gid, il_pos, 0, 0); + } } } -DECLSPEC void m09820s (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KERN_ATTR_ESALT (oldoffice34_t)) +DECLSPEC void m09820s (LOCAL_AS RC4_KEY *rc4_keys, u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KERN_ATTR_ESALT (oldoffice34_t)) { /** * modifier @@ -134,6 +358,12 @@ DECLSPEC void m09820s (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER const u64 gid = get_global_id (0); const u64 lid = get_local_id (0); + /** + * shared + */ + + LOCAL_AS RC4_KEY *rc4_key = &rc4_keys[lid]; + /** * salt */ @@ -195,21 +425,21 @@ DECLSPEC void m09820s (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER w3_t[2] = 0; w3_t[3] = (pw_len + 16) * 8; - u32x digest[5]; + u32 pass_hash[5]; - digest[0] = SHA1M_A; - digest[1] = SHA1M_B; - digest[2] = SHA1M_C; - digest[3] = SHA1M_D; - digest[4] = SHA1M_E; + pass_hash[0] = SHA1M_A; + pass_hash[1] = SHA1M_B; + pass_hash[2] = SHA1M_C; + pass_hash[3] = SHA1M_D; + pass_hash[4] = SHA1M_E; - sha1_transform_vector (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, pass_hash); - w0_t[0] = digest[0]; - w0_t[1] = digest[1]; - w0_t[2] = digest[2]; - w0_t[3] = digest[3]; - w1_t[0] = digest[4]; + w0_t[0] = pass_hash[0]; + w0_t[1] = pass_hash[1]; + w0_t[2] = pass_hash[2]; + w0_t[3] = pass_hash[3]; + w1_t[0] = pass_hash[4]; w1_t[1] = 0; w1_t[2] = 0x80000000; w1_t[3] = 0; @@ -222,20 +452,107 @@ DECLSPEC void m09820s (u32 *w0, u32 *w1, u32 *w2, u32 *w3, const u32 pw_len, KER w3_t[2] = 0; w3_t[3] = (20 + 4) * 8; + u32 digest[5]; + digest[0] = SHA1M_A; digest[1] = SHA1M_B; digest[2] = SHA1M_C; digest[3] = SHA1M_D; digest[4] = SHA1M_E; - sha1_transform_vector (w0_t, w1_t, w2_t, w3_t, digest); + sha1_transform (w0_t, w1_t, w2_t, w3_t, digest); digest[0] = hc_swap32 (digest[0]); digest[1] = hc_swap32 (digest[1]) & 0xff; digest[2] = 0; digest[3] = 0; - COMPARE_S_SIMD (digest[0], digest[1], digest[2], digest[3]); + // initial compare + + if (digest[0] != search[0]) continue; + if (digest[1] != search[1]) continue; + + if (esalt_bufs[digests_offset].secondBlockLen != 0) + { + w0[0] = pass_hash[0]; + w0[1] = pass_hash[1]; + w0[2] = pass_hash[2]; + w0[3] = pass_hash[3]; + w1[0] = pass_hash[4]; + w1[1] = 0x01000000; + w1[2] = 0x80000000; + 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] = (20 + 4) * 8; + + digest[0] = SHA1M_A; + digest[1] = SHA1M_B; + digest[2] = SHA1M_C; + digest[3] = SHA1M_D; + digest[4] = SHA1M_E; + + sha1_transform (w0, w1, w2, w3, digest); + + digest[0] = hc_swap32_S (digest[0]); + digest[1] = hc_swap32_S (digest[1]); + digest[2] = 0; + digest[3] = 0; + + digest[1] &= 0xff; // only 40-bit key + + // second block decrypt: + + rc4_init_16 (rc4_key, digest); + + u32 secondBlockData[4]; + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[0]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[1]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[2]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[3]; + + u32 out[4]; + + u32 j = rc4_next_16 (rc4_key, 0, 0, secondBlockData, out); + + int null_bytes = 0; + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + secondBlockData[0] = esalt_bufs[digests_offset].secondBlockData[4]; + secondBlockData[1] = esalt_bufs[digests_offset].secondBlockData[5]; + secondBlockData[2] = esalt_bufs[digests_offset].secondBlockData[6]; + secondBlockData[3] = esalt_bufs[digests_offset].secondBlockData[7]; + + rc4_next_16 (rc4_key, 16, j, secondBlockData, out); + + for (int k = 0; k < 4; k++) + { + if ((out[k] & 0x000000ff) == 0) null_bytes++; + if ((out[k] & 0x0000ff00) == 0) null_bytes++; + if ((out[k] & 0x00ff0000) == 0) null_bytes++; + if ((out[k] & 0xff000000) == 0) null_bytes++; + } + + if (null_bytes < MIN_NULL_BYTES) continue; + } + + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, il_pos, 0, 0); + } } } @@ -279,7 +596,13 @@ KERNEL_FQ void m09820_m04 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820m (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820m (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } KERNEL_FQ void m09820_m08 (KERN_ATTR_ESALT (oldoffice34_t)) @@ -322,7 +645,13 @@ KERNEL_FQ void m09820_m08 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820m (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820m (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } KERNEL_FQ void m09820_m16 (KERN_ATTR_ESALT (oldoffice34_t)) @@ -365,7 +694,13 @@ KERNEL_FQ void m09820_m16 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820m (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820m (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } KERNEL_FQ void m09820_s04 (KERN_ATTR_ESALT (oldoffice34_t)) @@ -408,7 +743,13 @@ KERNEL_FQ void m09820_s04 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820s (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820s (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } KERNEL_FQ void m09820_s08 (KERN_ATTR_ESALT (oldoffice34_t)) @@ -451,7 +792,13 @@ KERNEL_FQ void m09820_s08 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820s (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820s (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } KERNEL_FQ void m09820_s16 (KERN_ATTR_ESALT (oldoffice34_t)) @@ -494,5 +841,11 @@ KERNEL_FQ void m09820_s16 (KERN_ATTR_ESALT (oldoffice34_t)) const u32 pw_len = pws[gid].pw_len & 63; - m09820s (w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); + /** + * main + */ + + LOCAL_VK RC4_KEY rc4_keys[64]; + + m09820s (rc4_keys, w0, w1, w2, w3, pw_len, pws, rules_buf, combs_buf, bfs_buf, tmps, hooks, bitmaps_buf_s1_a, bitmaps_buf_s1_b, bitmaps_buf_s1_c, bitmaps_buf_s1_d, bitmaps_buf_s2_a, bitmaps_buf_s2_b, bitmaps_buf_s2_c, bitmaps_buf_s2_d, plains_buf, digests_buf, hashes_shown, salt_bufs, esalt_bufs, d_return_buf, d_extra0_buf, d_extra1_buf, d_extra2_buf, d_extra3_buf, bitmap_mask, bitmap_shift1, bitmap_shift2, salt_pos, loop_pos, loop_cnt, il_cnt, digests_cnt, digests_offset, combs_mode, gid_max); } diff --git a/src/modules/module_09800.c b/src/modules/module_09800.c index b191924dc..61ab1471a 100644 --- a/src/modules/module_09800.c +++ b/src/modules/module_09800.c @@ -49,6 +49,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -137,7 +139,22 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH | TOKEN_ATTR_VERIFY_HEX; - const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + + // alternative format (with second block data): + + if (rc_tokenizer == PARSER_TOKEN_LENGTH) // or just rc_tokenizer != PARSER_OK + { + token.token_cnt = 6; + + token.len_min[5] = 64; + token.len_max[5] = 64; + token.sep[5] = '*'; + token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + } if (rc_tokenizer != PARSER_OK) return (rc_tokenizer); @@ -165,6 +182,24 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE oldoffice34->encryptedVerifierHash[3] = hex_to_u32 (encryptedVerifierHash_pos + 24); oldoffice34->encryptedVerifierHash[4] = hex_to_u32 (encryptedVerifierHash_pos + 32); + // second block (if needed) + + oldoffice34->secondBlockLen = 0; + + if (token.token_cnt == 6) + { + oldoffice34->secondBlockData[0] = 0; + + const u8 *second_block_data = token.buf[5]; + + for (int i = 0, j = 0; i < 8; i += 1, j += 8) + { + oldoffice34->secondBlockData[i] = hex_to_u32 (second_block_data + j); + } + + oldoffice34->secondBlockLen = 64; + } + // salt salt->salt_len = 16; @@ -208,7 +243,23 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE { const oldoffice34_t *oldoffice34 = (const oldoffice34_t *) esalt_buf; - const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x", + u8 secondBlockData[64 + 1 + 1]; + + memset (secondBlockData, 0, sizeof (secondBlockData)); + + if (oldoffice34->secondBlockLen != 0) + { + secondBlockData[0] = '*'; + + u8 *ptr = (u8 *) oldoffice34->secondBlockData; + + for (int i = 0, j = 1; i < 32; i += 1, j += 2) + { + u8_to_hex (ptr[i], secondBlockData + j); + } + } + + const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x%s", SIGNATURE_OLDOFFICE, oldoffice34->version, salt->salt_buf[0], @@ -223,7 +274,8 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE byte_swap_32 (oldoffice34->encryptedVerifierHash[1]), byte_swap_32 (oldoffice34->encryptedVerifierHash[2]), byte_swap_32 (oldoffice34->encryptedVerifierHash[3]), - byte_swap_32 (oldoffice34->encryptedVerifierHash[4])); + byte_swap_32 (oldoffice34->encryptedVerifierHash[4]), + secondBlockData); return line_len; } diff --git a/src/modules/module_09810.c b/src/modules/module_09810.c index fd80151fa..ff9ccd2a5 100644 --- a/src/modules/module_09810.c +++ b/src/modules/module_09810.c @@ -48,6 +48,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -144,7 +146,22 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH | TOKEN_ATTR_VERIFY_HEX; - const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + + // alternative format (with second block data): + + if (rc_tokenizer == PARSER_TOKEN_LENGTH) // or just rc_tokenizer != PARSER_OK + { + token.token_cnt = 6; + + token.len_min[5] = 64; + token.len_max[5] = 64; + token.sep[5] = '*'; + token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + } if (rc_tokenizer != PARSER_OK) return (rc_tokenizer); @@ -172,6 +189,24 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE oldoffice34->encryptedVerifierHash[3] = hex_to_u32 (encryptedVerifierHash_pos + 24); oldoffice34->encryptedVerifierHash[4] = hex_to_u32 (encryptedVerifierHash_pos + 32); + // second block (if needed) + + oldoffice34->secondBlockLen = 0; + + if (token.token_cnt == 6) + { + oldoffice34->secondBlockData[0] = 0; + + const u8 *second_block_data = token.buf[5]; + + for (int i = 0, j = 0; i < 8; i += 1, j += 8) + { + oldoffice34->secondBlockData[i] = hex_to_u32 (second_block_data + j); + } + + oldoffice34->secondBlockLen = 64; + } + // salt salt->salt_len = 16; @@ -215,7 +250,23 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE { const oldoffice34_t *oldoffice34 = (const oldoffice34_t *) esalt_buf; - const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x", + u8 secondBlockData[64 + 1 + 1]; + + memset (secondBlockData, 0, sizeof (secondBlockData)); + + if (oldoffice34->secondBlockLen != 0) + { + secondBlockData[0] = '*'; + + u8 *ptr = (u8 *) oldoffice34->secondBlockData; + + for (int i = 0, j = 1; i < 32; i += 1, j += 2) + { + u8_to_hex (ptr[i], secondBlockData + j); + } + } + + const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x%s", SIGNATURE_OLDOFFICE, oldoffice34->version, salt->salt_buf[0], @@ -230,7 +281,8 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE byte_swap_32 (oldoffice34->encryptedVerifierHash[1]), byte_swap_32 (oldoffice34->encryptedVerifierHash[2]), byte_swap_32 (oldoffice34->encryptedVerifierHash[3]), - byte_swap_32 (oldoffice34->encryptedVerifierHash[4])); + byte_swap_32 (oldoffice34->encryptedVerifierHash[4]), + secondBlockData); return line_len; } diff --git a/src/modules/module_09820.c b/src/modules/module_09820.c index fd1aeabc1..7a6b2869c 100644 --- a/src/modules/module_09820.c +++ b/src/modules/module_09820.c @@ -50,6 +50,8 @@ typedef struct oldoffice34 u32 version; u32 encryptedVerifier[4]; u32 encryptedVerifierHash[5]; + u32 secondBlockData[8]; + u32 secondBlockLen; u32 rc4key[2]; } oldoffice34_t; @@ -117,7 +119,29 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH | TOKEN_ATTR_VERIFY_HEX; - const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + + // alternative format (with second block data): + + if (rc_tokenizer == PARSER_TOKEN_LENGTH) // or just rc_tokenizer != PARSER_OK + { + token.token_cnt = 7; + + token.sep[4] = '*'; + + token.len_min[5] = 64; + token.len_max[5] = 64; + token.sep[5] = ':'; + token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + token.len_min[6] = 10; + token.len_max[6] = 10; + token.attr[6] = TOKEN_ATTR_VERIFY_LENGTH + | TOKEN_ATTR_VERIFY_HEX; + + rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token); + } if (rc_tokenizer != PARSER_OK) return (rc_tokenizer); @@ -125,7 +149,10 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE const u8 *osalt_pos = token.buf[2]; const u8 *encryptedVerifier_pos = token.buf[3]; const u8 *encryptedVerifierHash_pos = token.buf[4]; - const u8 *rc4key_pos = token.buf[5]; + + const u8 rc4_idx = token.token_cnt - 1; + + const u8 *rc4key_pos = token.buf[rc4_idx]; // esalt @@ -163,6 +190,24 @@ int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE oldoffice34->rc4key[0] = byte_swap_32 (oldoffice34->rc4key[0]); oldoffice34->rc4key[1] = byte_swap_32 (oldoffice34->rc4key[1]); + // second block (if needed) + + oldoffice34->secondBlockLen = 0; + + if (token.token_cnt == 7) + { + oldoffice34->secondBlockData[0] = 0; + + const u8 *second_block_data = token.buf[5]; + + for (int i = 0, j = 0; i < 8; i += 1, j += 8) + { + oldoffice34->secondBlockData[i] = hex_to_u32 (second_block_data + j); + } + + oldoffice34->secondBlockLen = 64; + } + // salt salt->salt_len = 16; @@ -208,7 +253,23 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE const u8 *rc4key = (const u8 *) oldoffice34->rc4key; - const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x:%02x%02x%02x%02x%02x", + u8 secondBlockData[64 + 1 + 1]; + + memset (secondBlockData, 0, sizeof (secondBlockData)); + + if (oldoffice34->secondBlockLen != 0) + { + secondBlockData[0] = '*'; + + u8 *ptr = (u8 *) oldoffice34->secondBlockData; + + for (int i = 0, j = 1; i < 32; i += 1, j += 2) + { + u8_to_hex (ptr[i], secondBlockData + j); + } + } + + const int line_len = snprintf (line_buf, line_size, "%s%u*%08x%08x%08x%08x*%08x%08x%08x%08x*%08x%08x%08x%08x%08x%s:%02x%02x%02x%02x%02x", SIGNATURE_OLDOFFICE, oldoffice34->version, salt->salt_buf[0], @@ -224,6 +285,7 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSE byte_swap_32 (oldoffice34->encryptedVerifierHash[2]), byte_swap_32 (oldoffice34->encryptedVerifierHash[3]), byte_swap_32 (oldoffice34->encryptedVerifierHash[4]), + secondBlockData, rc4key[0], rc4key[1], rc4key[2], diff --git a/tools/test_modules/m09800.pm b/tools/test_modules/m09800.pm index 5e4c7a39d..995a92a07 100644 --- a/tools/test_modules/m09800.pm +++ b/tools/test_modules/m09800.pm @@ -20,6 +20,7 @@ sub module_generate_hash my $salt = shift; my $param = shift; my $param2 = shift; + my $param3 = shift; my $salt_bin = pack ("H*", $salt); @@ -64,7 +65,67 @@ sub module_generate_hash my $encrypted1 = $m->RC4 ($data1_buf); my $encrypted2 = $m->RC4 ($data2_buf); - my $hash = sprintf ("\$oldoffice\$%d*%s*%s*%s", $version, $salt, unpack ("H*", $encrypted1), unpack ("H*", $encrypted2)); + + my $secblock = ""; + + if ($version == 3) + { + my $key2 = substr (sha1 ($tmp . "\x01\x00\x00\x00"), 0, 5) . "\x00" x 11; + + my $rc4 = Crypt::RC4->new ($key2); + + if (defined $param3) # verify/decrypt: + { + if (length ($param3) > 0) + { + my $decrypted = $rc4->RC4 (pack ("H*", $param3)); + + # count the number of NUL (\x00) bytes: + + my $num_nul_bytes = 0; + + for (my $i = 0; $i < 32; $i++) + { + $num_nul_bytes++ if (substr ($decrypted, $i, 1) eq "\x00"); + } + + if ($num_nul_bytes < 10) + { + $secblock = "*"; # incorrect/fake/empty result + } + else + { + $secblock = "*$param3"; + } + } + } + else + { + if (random_number (0, 1) == 1) # the second block data is optional + { + my $num_zeros = random_number (10, 32); # at least 10 NUL bytes + + $secblock = "\x00" x $num_zeros; + + # fill the buffer with some random bytes (up to 32 bytes total): + + for (my $i = 0; $i < 32 - $num_zeros; $i++) + { + my $idx = random_number (0, $num_zeros + $i); # insert at random position + + my $c = random_bytes (1); # 0x00-0xff + + $secblock = substr ($secblock, 0, $idx) . $c . substr ($secblock, $idx); + } + + $secblock = $rc4->RC4 ($secblock); + + $secblock = "*" . unpack ("H*", $secblock); + } + } + } + + my $hash = sprintf ("\$oldoffice\$%d*%s*%s*%s%s", $version, $salt, unpack ("H*", $encrypted1), unpack ("H*", $encrypted2), $secblock); return $hash; } @@ -81,7 +142,9 @@ sub module_verify_hash my @data = split /\*/, $hash_in; - return unless scalar @data == 4; + my $num_fields = scalar @data; + + return unless (($num_fields == 4) || ($num_fields == 5)); my $signature = shift @data; @@ -95,6 +158,15 @@ sub module_verify_hash my $param = shift @data; my $param2 = substr ($signature, 11, 1); + my $param3 = ""; + + if ($num_fields == 5) + { + shift @data; # ignore the "digest" + + $param3 = shift @data; + } + return unless defined $salt; return unless defined $word; return unless defined $param; @@ -102,7 +174,7 @@ sub module_verify_hash $word = pack_if_HEX_notation ($word); - my $new_hash = module_generate_hash ($word, $salt, $param, $param2); + my $new_hash = module_generate_hash ($word, $salt, $param, $param2, $param3); return ($new_hash, $word); }