mirror of https://github.com/hashcat/hashcat.git
parent
777c5339a0
commit
3cc828ce0a
@ -0,0 +1,561 @@
|
||||
/**
|
||||
* Author......: See docs/credits.txt
|
||||
* License.....: MIT
|
||||
*/
|
||||
|
||||
#ifdef KERNEL_STATIC
|
||||
#include "inc_vendor.h"
|
||||
#include "inc_types.h"
|
||||
#include "inc_platform.cl"
|
||||
#include "inc_common.cl"
|
||||
#include "inc_hash_sha1.cl"
|
||||
#include "inc_cipher_aes.cl"
|
||||
#endif
|
||||
|
||||
#define COMPARE_S "inc_comp_single.cl"
|
||||
#define COMPARE_M "inc_comp_multi.cl"
|
||||
|
||||
#define ROUNDS 0x40000
|
||||
|
||||
#define PUTCHAR(a,p,c) ((u8 *)(a))[(p)] = (u8) (c)
|
||||
#define GETCHAR(a,p) ((u8 *)(a))[(p)]
|
||||
|
||||
#define PUTCHAR_BE(a,p,c) ((u8 *)(a))[(p) ^ 3] = (u8) (c)
|
||||
#define GETCHAR_BE(a,p) ((u8 *)(a))[(p) ^ 3]
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
typedef struct rar3
|
||||
{
|
||||
u32 data[81920];
|
||||
|
||||
u32 pack_size;
|
||||
u32 unpack_size;
|
||||
|
||||
} rar3_t;
|
||||
|
||||
typedef struct rar3_tmp
|
||||
{
|
||||
u32 dgst[17][5];
|
||||
|
||||
} rar3_tmp_t;
|
||||
|
||||
CONSTANT_VK u32a crc32tab[0x100] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
|
||||
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
|
||||
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
|
||||
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
|
||||
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
|
||||
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
|
||||
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
|
||||
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
|
||||
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
|
||||
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
|
||||
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
|
||||
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
|
||||
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
|
||||
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
|
||||
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
|
||||
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
|
||||
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
DECLSPEC u32 round_crc32 (const u32 a, const u32 v, LOCAL_AS u32 *l_crc32tab)
|
||||
{
|
||||
const u32 k = (a ^ v) & 0xff;
|
||||
|
||||
const u32 s = a >> 8;
|
||||
|
||||
return l_crc32tab[k] ^ s;
|
||||
}
|
||||
|
||||
DECLSPEC u32 round_crc32_16 (const u32 crc32, const u32 *buf, const u32 len, LOCAL_AS u32 *l_crc32tab)
|
||||
{
|
||||
const int crc_len = MIN (len, 16);
|
||||
|
||||
u32 c = crc32;
|
||||
|
||||
for (int i = 0; i < crc_len; i++)
|
||||
{
|
||||
const u32 idx = i / 4;
|
||||
const u32 mod = i % 4;
|
||||
const u32 sht = (3 - mod) * 8;
|
||||
|
||||
const u32 b = buf[idx] >> sht; // b & 0xff (but already done in round_crc32 ())
|
||||
|
||||
c = round_crc32 (c, b, l_crc32tab);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23700_init (KERN_ATTR_TMPS_ESALT (rar3_tmp_t, rar3_t))
|
||||
{
|
||||
/**
|
||||
* base
|
||||
*/
|
||||
|
||||
const u64 gid = get_global_id (0);
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
tmps[gid].dgst[0][0] = SHA1M_A;
|
||||
tmps[gid].dgst[0][1] = SHA1M_B;
|
||||
tmps[gid].dgst[0][2] = SHA1M_C;
|
||||
tmps[gid].dgst[0][3] = SHA1M_D;
|
||||
tmps[gid].dgst[0][4] = SHA1M_E;
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23700_loop (KERN_ATTR_TMPS_ESALT (rar3_tmp_t, rar3_t))
|
||||
{
|
||||
const u64 gid = get_global_id (0);
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
u32 pw_buf[5];
|
||||
|
||||
pw_buf[0] = pws[gid].i[0];
|
||||
pw_buf[1] = pws[gid].i[1];
|
||||
pw_buf[2] = pws[gid].i[2];
|
||||
pw_buf[3] = pws[gid].i[3];
|
||||
pw_buf[4] = pws[gid].i[4];
|
||||
|
||||
const u32 pw_len = MIN (pws[gid].pw_len, 20);
|
||||
|
||||
u32 salt_buf[2];
|
||||
|
||||
salt_buf[0] = salt_bufs[salt_pos].salt_buf[0];
|
||||
salt_buf[1] = salt_bufs[salt_pos].salt_buf[1];
|
||||
|
||||
const u32 salt_len = 8;
|
||||
|
||||
// this is large enough to hold all possible w[] arrays for 64 iterations
|
||||
|
||||
#define LARGEBLOCK_ELEMS ((40 + 8 + 3) * 16)
|
||||
|
||||
u32 largeblock[LARGEBLOCK_ELEMS];
|
||||
|
||||
for (u32 i = 0; i < LARGEBLOCK_ELEMS; i++) largeblock[i] = 0;
|
||||
|
||||
for (u32 i = 0, p = 0; i < 64; i++)
|
||||
{
|
||||
for (u32 j = 0; j < pw_len; j++, p += 2)
|
||||
{
|
||||
PUTCHAR_BE (largeblock, p, GETCHAR (pw_buf, j));
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < salt_len; j++, p += 1)
|
||||
{
|
||||
PUTCHAR_BE (largeblock, p, GETCHAR (salt_buf, j));
|
||||
}
|
||||
|
||||
PUTCHAR_BE (largeblock, p + 2, (loop_pos >> 16) & 0xff);
|
||||
|
||||
p += 3;
|
||||
}
|
||||
|
||||
const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
const u32 init_pos = loop_pos / (ROUNDS / 16);
|
||||
|
||||
u32 dgst[5];
|
||||
|
||||
dgst[0] = tmps[gid].dgst[init_pos][0];
|
||||
dgst[1] = tmps[gid].dgst[init_pos][1];
|
||||
dgst[2] = tmps[gid].dgst[init_pos][2];
|
||||
dgst[3] = tmps[gid].dgst[init_pos][3];
|
||||
dgst[4] = tmps[gid].dgst[init_pos][4];
|
||||
|
||||
u32 iter = loop_pos;
|
||||
|
||||
for (u32 i = 0; i < 256; i += 4)
|
||||
{
|
||||
for (u32 j = 0; j < 64; j++)
|
||||
{
|
||||
const u32 p = ((j + 1) * p3) - 2;
|
||||
|
||||
PUTCHAR_BE (largeblock, p, iter >> 8);
|
||||
}
|
||||
|
||||
for (u32 k = 0; k < 4; k++)
|
||||
{
|
||||
for (u32 j = 0; j < 64; j++)
|
||||
{
|
||||
const u32 p = ((j + 1) * p3) - 3;
|
||||
|
||||
PUTCHAR_BE (largeblock, p, iter >> 0);
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < p3; j++)
|
||||
{
|
||||
const u32 j16 = j * 16;
|
||||
|
||||
u32 w0[4];
|
||||
u32 w1[4];
|
||||
u32 w2[4];
|
||||
u32 w3[4];
|
||||
|
||||
w0[0] = largeblock[j16 + 0];
|
||||
w0[1] = largeblock[j16 + 1];
|
||||
w0[2] = largeblock[j16 + 2];
|
||||
w0[3] = largeblock[j16 + 3];
|
||||
w1[0] = largeblock[j16 + 4];
|
||||
w1[1] = largeblock[j16 + 5];
|
||||
w1[2] = largeblock[j16 + 6];
|
||||
w1[3] = largeblock[j16 + 7];
|
||||
w2[0] = largeblock[j16 + 8];
|
||||
w2[1] = largeblock[j16 + 9];
|
||||
w2[2] = largeblock[j16 + 10];
|
||||
w2[3] = largeblock[j16 + 11];
|
||||
w3[0] = largeblock[j16 + 12];
|
||||
w3[1] = largeblock[j16 + 13];
|
||||
w3[2] = largeblock[j16 + 14];
|
||||
w3[3] = largeblock[j16 + 15];
|
||||
|
||||
sha1_transform (w0, w1, w2, w3, dgst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmps[gid].dgst[init_pos + 1][0] = dgst[0];
|
||||
tmps[gid].dgst[init_pos + 1][1] = dgst[1];
|
||||
tmps[gid].dgst[init_pos + 1][2] = dgst[2];
|
||||
tmps[gid].dgst[init_pos + 1][3] = dgst[3];
|
||||
tmps[gid].dgst[init_pos + 1][4] = dgst[4];
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23700_comp (KERN_ATTR_TMPS_ESALT (rar3_tmp_t, rar3_t))
|
||||
{
|
||||
const u64 gid = get_global_id (0);
|
||||
const u64 lid = get_local_id (0);
|
||||
const u64 lsz = get_local_size (0);
|
||||
|
||||
/**
|
||||
* aes shared
|
||||
*/
|
||||
|
||||
#ifdef REAL_SHM
|
||||
|
||||
LOCAL_VK u32 s_td0[256];
|
||||
LOCAL_VK u32 s_td1[256];
|
||||
LOCAL_VK u32 s_td2[256];
|
||||
LOCAL_VK u32 s_td3[256];
|
||||
LOCAL_VK u32 s_td4[256];
|
||||
|
||||
LOCAL_VK u32 s_te0[256];
|
||||
LOCAL_VK u32 s_te1[256];
|
||||
LOCAL_VK u32 s_te2[256];
|
||||
LOCAL_VK u32 s_te3[256];
|
||||
LOCAL_VK u32 s_te4[256];
|
||||
|
||||
for (u32 i = lid; i < 256; i += lsz)
|
||||
{
|
||||
s_td0[i] = td0[i];
|
||||
s_td1[i] = td1[i];
|
||||
s_td2[i] = td2[i];
|
||||
s_td3[i] = td3[i];
|
||||
s_td4[i] = td4[i];
|
||||
|
||||
s_te0[i] = te0[i];
|
||||
s_te1[i] = te1[i];
|
||||
s_te2[i] = te2[i];
|
||||
s_te3[i] = te3[i];
|
||||
s_te4[i] = te4[i];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CONSTANT_AS u32a *s_td0 = td0;
|
||||
CONSTANT_AS u32a *s_td1 = td1;
|
||||
CONSTANT_AS u32a *s_td2 = td2;
|
||||
CONSTANT_AS u32a *s_td3 = td3;
|
||||
CONSTANT_AS u32a *s_td4 = td4;
|
||||
|
||||
CONSTANT_AS u32a *s_te0 = te0;
|
||||
CONSTANT_AS u32a *s_te1 = te1;
|
||||
CONSTANT_AS u32a *s_te2 = te2;
|
||||
CONSTANT_AS u32a *s_te3 = te3;
|
||||
CONSTANT_AS u32a *s_te4 = te4;
|
||||
|
||||
#endif
|
||||
|
||||
LOCAL_VK u32 l_crc32tab[256];
|
||||
|
||||
for (int i = lid; i < 256; i += lsz)
|
||||
{
|
||||
l_crc32tab[i] = crc32tab[i];
|
||||
}
|
||||
|
||||
SYNC_THREADS ();
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
/**
|
||||
* base
|
||||
*/
|
||||
|
||||
const u32 pw_len = MIN (pws[gid].pw_len, 20);
|
||||
|
||||
const u32 salt_len = 8;
|
||||
|
||||
const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
u32 w0[4];
|
||||
u32 w1[4];
|
||||
u32 w2[4];
|
||||
u32 w3[4];
|
||||
|
||||
w0[0] = 0x80000000;
|
||||
w0[1] = 0;
|
||||
w0[2] = 0;
|
||||
w0[3] = 0;
|
||||
w1[0] = 0;
|
||||
w1[1] = 0;
|
||||
w1[2] = 0;
|
||||
w1[3] = 0;
|
||||
w2[0] = 0;
|
||||
w2[1] = 0;
|
||||
w2[2] = 0;
|
||||
w2[3] = 0;
|
||||
w3[0] = 0;
|
||||
w3[1] = 0;
|
||||
w3[2] = 0;
|
||||
w3[3] = (p3 * ROUNDS) * 8;
|
||||
|
||||
u32 dgst[5];
|
||||
|
||||
dgst[0] = tmps[gid].dgst[16][0];
|
||||
dgst[1] = tmps[gid].dgst[16][1];
|
||||
dgst[2] = tmps[gid].dgst[16][2];
|
||||
dgst[3] = tmps[gid].dgst[16][3];
|
||||
dgst[4] = tmps[gid].dgst[16][4];
|
||||
|
||||
sha1_transform (w0, w1, w2, w3, dgst);
|
||||
|
||||
u32 ukey[4];
|
||||
|
||||
ukey[0] = hc_swap32_S (dgst[0]);
|
||||
ukey[1] = hc_swap32_S (dgst[1]);
|
||||
ukey[2] = hc_swap32_S (dgst[2]);
|
||||
ukey[3] = hc_swap32_S (dgst[3]);
|
||||
|
||||
u32 ks[44];
|
||||
|
||||
AES128_set_decrypt_key (ks, ukey, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3);
|
||||
|
||||
u32 iv[4];
|
||||
|
||||
iv[0] = 0;
|
||||
iv[1] = 0;
|
||||
iv[2] = 0;
|
||||
iv[3] = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
u32 pw_buf[5];
|
||||
|
||||
pw_buf[0] = pws[gid].i[0];
|
||||
pw_buf[1] = pws[gid].i[1];
|
||||
pw_buf[2] = pws[gid].i[2];
|
||||
pw_buf[3] = pws[gid].i[3];
|
||||
pw_buf[4] = pws[gid].i[4];
|
||||
|
||||
//const u32 pw_len = pws[gid].pw_len;
|
||||
|
||||
u32 salt_buf[2];
|
||||
|
||||
salt_buf[0] = salt_bufs[salt_pos].salt_buf[0];
|
||||
salt_buf[1] = salt_bufs[salt_pos].salt_buf[1];
|
||||
|
||||
//const u32 salt_len = 8;
|
||||
|
||||
//const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
u32 w[16];
|
||||
|
||||
w[ 0] = 0;
|
||||
w[ 1] = 0;
|
||||
w[ 2] = 0;
|
||||
w[ 3] = 0;
|
||||
w[ 4] = 0;
|
||||
w[ 5] = 0;
|
||||
w[ 6] = 0;
|
||||
w[ 7] = 0;
|
||||
w[ 8] = 0;
|
||||
w[ 9] = 0;
|
||||
w[10] = 0;
|
||||
w[11] = 0;
|
||||
w[12] = 0;
|
||||
w[13] = 0;
|
||||
w[14] = 0;
|
||||
w[15] = 0;
|
||||
|
||||
u32 p = 0;
|
||||
|
||||
for (u32 j = 0; j < pw_len; j++, p += 2)
|
||||
{
|
||||
PUTCHAR_BE (w, p, GETCHAR (pw_buf, j));
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < salt_len; j++, p += 1)
|
||||
{
|
||||
PUTCHAR_BE (w, p, GETCHAR (salt_buf, j));
|
||||
}
|
||||
|
||||
const u32 iter_pos = i * (ROUNDS / 16);
|
||||
|
||||
PUTCHAR_BE (w, p + 0, (iter_pos >> 0) & 0xff);
|
||||
PUTCHAR_BE (w, p + 1, (iter_pos >> 8) & 0xff);
|
||||
PUTCHAR_BE (w, p + 2, (iter_pos >> 16) & 0xff);
|
||||
|
||||
PUTCHAR_BE (w, p3, 0x80);
|
||||
|
||||
w[15] = ((iter_pos + 1) * p3) * 8;
|
||||
|
||||
u32 dgst[5];
|
||||
|
||||
dgst[0] = tmps[gid].dgst[i][0];
|
||||
dgst[1] = tmps[gid].dgst[i][1];
|
||||
dgst[2] = tmps[gid].dgst[i][2];
|
||||
dgst[3] = tmps[gid].dgst[i][3];
|
||||
dgst[4] = tmps[gid].dgst[i][4];
|
||||
|
||||
sha1_transform (w + 0, w + 4, w + 8, w + 12, dgst);
|
||||
|
||||
PUTCHAR (iv, i, dgst[4] & 0xff);
|
||||
}
|
||||
|
||||
iv[0] = hc_swap32_S (iv[0]);
|
||||
iv[1] = hc_swap32_S (iv[1]);
|
||||
iv[2] = hc_swap32_S (iv[2]);
|
||||
iv[3] = hc_swap32_S (iv[3]);
|
||||
|
||||
const u32 pack_size = esalt_bufs[digests_offset].pack_size;
|
||||
const u32 unpack_size = esalt_bufs[digests_offset].unpack_size;
|
||||
|
||||
if (pack_size > unpack_size) // could be aligned
|
||||
{
|
||||
if (pack_size >= 32) // otherwise IV...
|
||||
{
|
||||
const u32 pack_size_elements = pack_size / 4;
|
||||
|
||||
u32 last_block_encrypted[4];
|
||||
|
||||
last_block_encrypted[0] = esalt_bufs[digests_offset].data[pack_size_elements - 4 + 0];
|
||||
last_block_encrypted[1] = esalt_bufs[digests_offset].data[pack_size_elements - 4 + 1];
|
||||
last_block_encrypted[2] = esalt_bufs[digests_offset].data[pack_size_elements - 4 + 2];
|
||||
last_block_encrypted[3] = esalt_bufs[digests_offset].data[pack_size_elements - 4 + 3];
|
||||
|
||||
u32 last_block_decrypted[4];
|
||||
|
||||
AES128_decrypt (ks, last_block_encrypted, last_block_decrypted, s_td0, s_td1, s_td2, s_td3, s_td4);
|
||||
|
||||
u32 last_block_iv[4];
|
||||
|
||||
last_block_iv[0] = esalt_bufs[digests_offset].data[pack_size_elements - 8 + 0];
|
||||
last_block_iv[1] = esalt_bufs[digests_offset].data[pack_size_elements - 8 + 1];
|
||||
last_block_iv[2] = esalt_bufs[digests_offset].data[pack_size_elements - 8 + 2];
|
||||
last_block_iv[3] = esalt_bufs[digests_offset].data[pack_size_elements - 8 + 3];
|
||||
|
||||
last_block_decrypted[0] ^= last_block_iv[0];
|
||||
last_block_decrypted[1] ^= last_block_iv[1];
|
||||
last_block_decrypted[2] ^= last_block_iv[2];
|
||||
last_block_decrypted[3] ^= last_block_iv[3];
|
||||
|
||||
if ((last_block_decrypted[3] & 0xff) != 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
u32 data_left = unpack_size;
|
||||
|
||||
u32 crc32 = ~0;
|
||||
|
||||
for (u32 i = 0, j = 0; i < pack_size / 16; i += 1, j += 4)
|
||||
{
|
||||
u32 data[4];
|
||||
|
||||
data[0] = esalt_bufs[digests_offset].data[j + 0];
|
||||
data[1] = esalt_bufs[digests_offset].data[j + 1];
|
||||
data[2] = esalt_bufs[digests_offset].data[j + 2];
|
||||
data[3] = esalt_bufs[digests_offset].data[j + 3];
|
||||
|
||||
u32 out[4];
|
||||
|
||||
AES128_decrypt (ks, data, out, s_td0, s_td1, s_td2, s_td3, s_td4);
|
||||
|
||||
out[0] ^= iv[0];
|
||||
out[1] ^= iv[1];
|
||||
out[2] ^= iv[2];
|
||||
out[3] ^= iv[3];
|
||||
|
||||
crc32 = round_crc32_16 (crc32, out, data_left, l_crc32tab);
|
||||
|
||||
iv[0] = data[0];
|
||||
iv[1] = data[1];
|
||||
iv[2] = data[2];
|
||||
iv[3] = data[3];
|
||||
|
||||
data_left -= 16;
|
||||
}
|
||||
|
||||
const u32 r0 = crc32;
|
||||
const u32 r1 = 0;
|
||||
const u32 r2 = 0;
|
||||
const u32 r3 = 0;
|
||||
|
||||
#define il_pos 0
|
||||
|
||||
#ifdef KERNEL_STATIC
|
||||
#include COMPARE_M
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,436 @@
|
||||
/**
|
||||
* Author......: See docs/credits.txt
|
||||
* License.....: MIT
|
||||
*/
|
||||
|
||||
#ifdef KERNEL_STATIC
|
||||
#include "inc_vendor.h"
|
||||
#include "inc_types.h"
|
||||
#include "inc_platform.cl"
|
||||
#include "inc_common.cl"
|
||||
#include "inc_hash_sha1.cl"
|
||||
#include "inc_cipher_aes.cl"
|
||||
#endif
|
||||
|
||||
#define COMPARE_S "inc_comp_single.cl"
|
||||
#define COMPARE_M "inc_comp_multi.cl"
|
||||
|
||||
#define ROUNDS 0x40000
|
||||
|
||||
#define PUTCHAR(a,p,c) ((u8 *)(a))[(p)] = (u8) (c)
|
||||
#define GETCHAR(a,p) ((u8 *)(a))[(p)]
|
||||
|
||||
#define PUTCHAR_BE(a,p,c) ((u8 *)(a))[(p) ^ 3] = (u8) (c)
|
||||
#define GETCHAR_BE(a,p) ((u8 *)(a))[(p) ^ 3]
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
typedef struct rar3
|
||||
{
|
||||
u32 first_block_encrypted[4];
|
||||
|
||||
} rar3_t;
|
||||
|
||||
typedef struct rar3_tmp
|
||||
{
|
||||
u32 dgst[17][5];
|
||||
|
||||
} rar3_tmp_t;
|
||||
|
||||
typedef struct rar3_hook
|
||||
{
|
||||
u32 key[4];
|
||||
u32 iv[4];
|
||||
|
||||
u32 first_block_decrypted[4];
|
||||
|
||||
u32 crc32;
|
||||
|
||||
} rar3_hook_t;
|
||||
|
||||
KERNEL_FQ void m23800_init (KERN_ATTR_TMPS_HOOKS_ESALT (rar3_tmp_t, rar3_hook_t, rar3_t))
|
||||
{
|
||||
/**
|
||||
* base
|
||||
*/
|
||||
|
||||
const u64 gid = get_global_id (0);
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
tmps[gid].dgst[0][0] = SHA1M_A;
|
||||
tmps[gid].dgst[0][1] = SHA1M_B;
|
||||
tmps[gid].dgst[0][2] = SHA1M_C;
|
||||
tmps[gid].dgst[0][3] = SHA1M_D;
|
||||
tmps[gid].dgst[0][4] = SHA1M_E;
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23800_loop (KERN_ATTR_TMPS_HOOKS_ESALT (rar3_tmp_t, rar3_hook_t, rar3_t))
|
||||
{
|
||||
const u64 gid = get_global_id (0);
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
u32 pw_buf[5];
|
||||
|
||||
pw_buf[0] = pws[gid].i[0];
|
||||
pw_buf[1] = pws[gid].i[1];
|
||||
pw_buf[2] = pws[gid].i[2];
|
||||
pw_buf[3] = pws[gid].i[3];
|
||||
pw_buf[4] = pws[gid].i[4];
|
||||
|
||||
const u32 pw_len = MIN (pws[gid].pw_len, 20);
|
||||
|
||||
u32 salt_buf[2];
|
||||
|
||||
salt_buf[0] = salt_bufs[salt_pos].salt_buf[0];
|
||||
salt_buf[1] = salt_bufs[salt_pos].salt_buf[1];
|
||||
|
||||
const u32 salt_len = 8;
|
||||
|
||||
// this is large enough to hold all possible w[] arrays for 64 iterations
|
||||
|
||||
#define LARGEBLOCK_ELEMS ((40 + 8 + 3) * 16)
|
||||
|
||||
u32 largeblock[LARGEBLOCK_ELEMS];
|
||||
|
||||
for (u32 i = 0; i < LARGEBLOCK_ELEMS; i++) largeblock[i] = 0;
|
||||
|
||||
for (u32 i = 0, p = 0; i < 64; i++)
|
||||
{
|
||||
for (u32 j = 0; j < pw_len; j++, p += 2)
|
||||
{
|
||||
PUTCHAR_BE (largeblock, p, GETCHAR (pw_buf, j));
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < salt_len; j++, p += 1)
|
||||
{
|
||||
PUTCHAR_BE (largeblock, p, GETCHAR (salt_buf, j));
|
||||
}
|
||||
|
||||
PUTCHAR_BE (largeblock, p + 2, (loop_pos >> 16) & 0xff);
|
||||
|
||||
p += 3;
|
||||
}
|
||||
|
||||
const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
const u32 init_pos = loop_pos / (ROUNDS / 16);
|
||||
|
||||
u32 dgst[5];
|
||||
|
||||
dgst[0] = tmps[gid].dgst[init_pos][0];
|
||||
dgst[1] = tmps[gid].dgst[init_pos][1];
|
||||
dgst[2] = tmps[gid].dgst[init_pos][2];
|
||||
dgst[3] = tmps[gid].dgst[init_pos][3];
|
||||
dgst[4] = tmps[gid].dgst[init_pos][4];
|
||||
|
||||
u32 iter = loop_pos;
|
||||
|
||||
for (u32 i = 0; i < 256; i += 4)
|
||||
{
|
||||
for (u32 j = 0; j < 64; j++)
|
||||
{
|
||||
const u32 p = ((j + 1) * p3) - 2;
|
||||
|
||||
PUTCHAR_BE (largeblock, p, iter >> 8);
|
||||
}
|
||||
|
||||
for (u32 k = 0; k < 4; k++)
|
||||
{
|
||||
for (u32 j = 0; j < 64; j++)
|
||||
{
|
||||
const u32 p = ((j + 1) * p3) - 3;
|
||||
|
||||
PUTCHAR_BE (largeblock, p, iter >> 0);
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < p3; j++)
|
||||
{
|
||||
const u32 j16 = j * 16;
|
||||
|
||||
u32 w0[4];
|
||||
u32 w1[4];
|
||||
u32 w2[4];
|
||||
u32 w3[4];
|
||||
|
||||
w0[0] = largeblock[j16 + 0];
|
||||
w0[1] = largeblock[j16 + 1];
|
||||
w0[2] = largeblock[j16 + 2];
|
||||
w0[3] = largeblock[j16 + 3];
|
||||
w1[0] = largeblock[j16 + 4];
|
||||
w1[1] = largeblock[j16 + 5];
|
||||
w1[2] = largeblock[j16 + 6];
|
||||
w1[3] = largeblock[j16 + 7];
|
||||
w2[0] = largeblock[j16 + 8];
|
||||
w2[1] = largeblock[j16 + 9];
|
||||
w2[2] = largeblock[j16 + 10];
|
||||
w2[3] = largeblock[j16 + 11];
|
||||
w3[0] = largeblock[j16 + 12];
|
||||
w3[1] = largeblock[j16 + 13];
|
||||
w3[2] = largeblock[j16 + 14];
|
||||
w3[3] = largeblock[j16 + 15];
|
||||
|
||||
sha1_transform (w0, w1, w2, w3, dgst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmps[gid].dgst[init_pos + 1][0] = dgst[0];
|
||||
tmps[gid].dgst[init_pos + 1][1] = dgst[1];
|
||||
tmps[gid].dgst[init_pos + 1][2] = dgst[2];
|
||||
tmps[gid].dgst[init_pos + 1][3] = dgst[3];
|
||||
tmps[gid].dgst[init_pos + 1][4] = dgst[4];
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23800_hook23 (KERN_ATTR_TMPS_HOOKS_ESALT (rar3_tmp_t, rar3_hook_t, rar3_t))
|
||||
{
|
||||
const u64 gid = get_global_id (0);
|
||||
const u64 lid = get_local_id (0);
|
||||
const u64 lsz = get_local_size (0);
|
||||
|
||||
/**
|
||||
* aes shared
|
||||
*/
|
||||
|
||||
#ifdef REAL_SHM
|
||||
|
||||
LOCAL_VK u32 s_td0[256];
|
||||
LOCAL_VK u32 s_td1[256];
|
||||
LOCAL_VK u32 s_td2[256];
|
||||
LOCAL_VK u32 s_td3[256];
|
||||
LOCAL_VK u32 s_td4[256];
|
||||
|
||||
LOCAL_VK u32 s_te0[256];
|
||||
LOCAL_VK u32 s_te1[256];
|
||||
LOCAL_VK u32 s_te2[256];
|
||||
LOCAL_VK u32 s_te3[256];
|
||||
LOCAL_VK u32 s_te4[256];
|
||||
|
||||
for (u32 i = lid; i < 256; i += lsz)
|
||||
{
|
||||
s_td0[i] = td0[i];
|
||||
s_td1[i] = td1[i];
|
||||
s_td2[i] = td2[i];
|
||||
s_td3[i] = td3[i];
|
||||
s_td4[i] = td4[i];
|
||||
|
||||
s_te0[i] = te0[i];
|
||||
s_te1[i] = te1[i];
|
||||
s_te2[i] = te2[i];
|
||||
s_te3[i] = te3[i];
|
||||
s_te4[i] = te4[i];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CONSTANT_AS u32a *s_td0 = td0;
|
||||
CONSTANT_AS u32a *s_td1 = td1;
|
||||
CONSTANT_AS u32a *s_td2 = td2;
|
||||
CONSTANT_AS u32a *s_td3 = td3;
|
||||
CONSTANT_AS u32a *s_td4 = td4;
|
||||
|
||||
CONSTANT_AS u32a *s_te0 = te0;
|
||||
CONSTANT_AS u32a *s_te1 = te1;
|
||||
CONSTANT_AS u32a *s_te2 = te2;
|
||||
CONSTANT_AS u32a *s_te3 = te3;
|
||||
CONSTANT_AS u32a *s_te4 = te4;
|
||||
|
||||
#endif
|
||||
|
||||
SYNC_THREADS ();
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
/**
|
||||
* base
|
||||
*/
|
||||
|
||||
const u32 pw_len = MIN (pws[gid].pw_len, 20);
|
||||
|
||||
const u32 salt_len = 8;
|
||||
|
||||
const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
u32 w0[4];
|
||||
u32 w1[4];
|
||||
u32 w2[4];
|
||||
u32 w3[4];
|
||||
|
||||
w0[0] = 0x80000000;
|
||||
w0[1] = 0;
|
||||
w0[2] = 0;
|
||||
w0[3] = 0;
|
||||
w1[0] = 0;
|
||||
w1[1] = 0;
|
||||
w1[2] = 0;
|
||||
w1[3] = 0;
|
||||
w2[0] = 0;
|
||||
w2[1] = 0;
|
||||
w2[2] = 0;
|
||||
w2[3] = 0;
|
||||
w3[0] = 0;
|
||||
w3[1] = 0;
|
||||
w3[2] = 0;
|
||||
w3[3] = (p3 * ROUNDS) * 8;
|
||||
|
||||
u32 h[5];
|
||||
|
||||
h[0] = tmps[gid].dgst[16][0];
|
||||
h[1] = tmps[gid].dgst[16][1];
|
||||
h[2] = tmps[gid].dgst[16][2];
|
||||
h[3] = tmps[gid].dgst[16][3];
|
||||
h[4] = tmps[gid].dgst[16][4];
|
||||
|
||||
sha1_transform (w0, w1, w2, w3, h);
|
||||
|
||||
u32 iv[4];
|
||||
|
||||
iv[0] = 0;
|
||||
iv[1] = 0;
|
||||
iv[2] = 0;
|
||||
iv[3] = 0;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
u32 pw_buf[5];
|
||||
|
||||
pw_buf[0] = pws[gid].i[0];
|
||||
pw_buf[1] = pws[gid].i[1];
|
||||
pw_buf[2] = pws[gid].i[2];
|
||||
pw_buf[3] = pws[gid].i[3];
|
||||
pw_buf[4] = pws[gid].i[4];
|
||||
|
||||
//const u32 pw_len = pws[gid].pw_len;
|
||||
|
||||
u32 salt_buf[2];
|
||||
|
||||
salt_buf[0] = salt_bufs[salt_pos].salt_buf[0];
|
||||
salt_buf[1] = salt_bufs[salt_pos].salt_buf[1];
|
||||
|
||||
//const u32 salt_len = 8;
|
||||
|
||||
//const u32 p3 = (pw_len * 2) + salt_len + 3;
|
||||
|
||||
u32 w[16];
|
||||
|
||||
w[ 0] = 0;
|
||||
w[ 1] = 0;
|
||||
w[ 2] = 0;
|
||||
w[ 3] = 0;
|
||||
w[ 4] = 0;
|
||||
w[ 5] = 0;
|
||||
w[ 6] = 0;
|
||||
w[ 7] = 0;
|
||||
w[ 8] = 0;
|
||||
w[ 9] = 0;
|
||||
w[10] = 0;
|
||||
w[11] = 0;
|
||||
w[12] = 0;
|
||||
w[13] = 0;
|
||||
w[14] = 0;
|
||||
w[15] = 0;
|
||||
|
||||
u32 p = 0;
|
||||
|
||||
for (u32 j = 0; j < pw_len; j++, p += 2)
|
||||
{
|
||||
PUTCHAR_BE (w, p, GETCHAR (pw_buf, j));
|
||||
}
|
||||
|
||||
for (u32 j = 0; j < salt_len; j++, p += 1)
|
||||
{
|
||||
PUTCHAR_BE (w, p, GETCHAR (salt_buf, j));
|
||||
}
|
||||
|
||||
const u32 iter_pos = i * (ROUNDS / 16);
|
||||
|
||||
PUTCHAR_BE (w, p + 0, (iter_pos >> 0) & 0xff);
|
||||
PUTCHAR_BE (w, p + 1, (iter_pos >> 8) & 0xff);
|
||||
PUTCHAR_BE (w, p + 2, (iter_pos >> 16) & 0xff);
|
||||
|
||||
PUTCHAR_BE (w, p3, 0x80);
|
||||
|
||||
w[15] = ((iter_pos + 1) * p3) * 8;
|
||||
|
||||
u32 dgst[5];
|
||||
|
||||
dgst[0] = tmps[gid].dgst[i][0];
|
||||
dgst[1] = tmps[gid].dgst[i][1];
|
||||
dgst[2] = tmps[gid].dgst[i][2];
|
||||
dgst[3] = tmps[gid].dgst[i][3];
|
||||
dgst[4] = tmps[gid].dgst[i][4];
|
||||
|
||||
sha1_transform (w + 0, w + 4, w + 8, w + 12, dgst);
|
||||
|
||||
PUTCHAR (iv, i, dgst[4] & 0xff);
|
||||
}
|
||||
|
||||
hooks[gid].key[0] = h[0];
|
||||
hooks[gid].key[1] = h[1];
|
||||
hooks[gid].key[2] = h[2];
|
||||
hooks[gid].key[3] = h[3];
|
||||
|
||||
hooks[gid].iv[0] = iv[0];
|
||||
hooks[gid].iv[1] = iv[1];
|
||||
hooks[gid].iv[2] = iv[2];
|
||||
hooks[gid].iv[3] = iv[3];
|
||||
|
||||
u32 ukey[4];
|
||||
|
||||
ukey[0] = hc_swap32_S (h[0]);
|
||||
ukey[1] = hc_swap32_S (h[1]);
|
||||
ukey[2] = hc_swap32_S (h[2]);
|
||||
ukey[3] = hc_swap32_S (h[3]);
|
||||
|
||||
u32 ks[44];
|
||||
|
||||
AES128_set_decrypt_key (ks, ukey, s_te0, s_te1, s_te2, s_te3, s_td0, s_td1, s_td2, s_td3);
|
||||
|
||||
u32 data[4];
|
||||
|
||||
data[0] = hc_swap32_S (esalt_bufs[digests_offset].first_block_encrypted[0]);
|
||||
data[1] = hc_swap32_S (esalt_bufs[digests_offset].first_block_encrypted[1]);
|
||||
data[2] = hc_swap32_S (esalt_bufs[digests_offset].first_block_encrypted[2]);
|
||||
data[3] = hc_swap32_S (esalt_bufs[digests_offset].first_block_encrypted[3]);
|
||||
|
||||
u32 out[4];
|
||||
|
||||
AES128_decrypt (ks, data, out, s_td0, s_td1, s_td2, s_td3, s_td4);
|
||||
|
||||
out[0] ^= hc_swap32_S (iv[0]);
|
||||
out[1] ^= hc_swap32_S (iv[1]);
|
||||
out[2] ^= hc_swap32_S (iv[2]);
|
||||
out[3] ^= hc_swap32_S (iv[3]);
|
||||
|
||||
hooks[gid].first_block_decrypted[0] = hc_swap32_S (out[0]);
|
||||
hooks[gid].first_block_decrypted[1] = hc_swap32_S (out[1]);
|
||||
hooks[gid].first_block_decrypted[2] = hc_swap32_S (out[2]);
|
||||
hooks[gid].first_block_decrypted[3] = hc_swap32_S (out[3]);
|
||||
}
|
||||
|
||||
KERNEL_FQ void m23800_comp (KERN_ATTR_TMPS_HOOKS_ESALT (rar3_tmp_t, rar3_hook_t, rar3_t))
|
||||
{
|
||||
/**
|
||||
* base
|
||||
*/
|
||||
|
||||
const u64 gid = get_global_id (0);
|
||||
|
||||
if (gid >= gid_max) return;
|
||||
|
||||
u32 crc32 = hooks[gid].crc32;
|
||||
|
||||
const u32 r0 = crc32;
|
||||
const u32 r1 = 0;
|
||||
const u32 r2 = 0;
|
||||
const u32 r3 = 0;
|
||||
|
||||
#define il_pos 0
|
||||
|
||||
#ifdef KERNEL_STATIC
|
||||
#include COMPARE_M
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Author......: See docs/credits.txt
|
||||
* License.....: MIT
|
||||
*/
|
||||
|
||||
// CREDITS go to the UnRAR project from rarlab.com
|
||||
// see license.txt file
|
||||
|
||||
#include "rar.hpp"
|
||||
|
||||
#define WINSIZE 0x100000 // minimum window size 0x20000 (MinAllocSize is 0x40000), 1 MiB
|
||||
#define SOLID false
|
||||
#define METHOD VER_UNPACK // 29 for RAR3 archives
|
||||
|
||||
extern "C" unsigned int hc_decompress_rar (unsigned char *Win, unsigned char *Inp, unsigned char *VM, unsigned char *PPM, const unsigned int OutputSize, const unsigned char *Input, const unsigned int PackSize, const unsigned int UnpackSize, const unsigned char *Key, const unsigned char *IV)
|
||||
{
|
||||
ComprDataIO DataIO;
|
||||
|
||||
DataIO.InitRijindal ((byte *) Key, (byte *) IV);
|
||||
|
||||
DataIO.SetPackedSizeToRead (PackSize);
|
||||
|
||||
DataIO.SetTestMode (false);
|
||||
DataIO.SetSkipUnpCRC (false); // or 'true', if we use our own crc32 code
|
||||
DataIO.UnpHash.Init (HASH_CRC32, 1); // 1: 1 single thread ?
|
||||
|
||||
DataIO.SetUnpackFromMemory ((byte *) Input, PackSize);
|
||||
DataIO.SetUnpackToMemory ((byte *) NULL, UnpackSize);
|
||||
|
||||
Unpack *Unp = new Unpack (&DataIO);
|
||||
|
||||
// not needed in our tests (no false positives):
|
||||
// memset (Win, 0, UnpackSize);
|
||||
// #define INPSIZE 0x50000
|
||||
// memset (Inp, 0, INPSIZE);
|
||||
// memset (VM, 0, INPSIZE);
|
||||
// #define PPMSIZE 216 * 1024 * 1024
|
||||
// memset (PPM, 0, PPMSIZE);
|
||||
|
||||
Unp->SetWin (Win);
|
||||
Unp->SetPPM (PPM);
|
||||
|
||||
Unp->Init (WINSIZE, SOLID);
|
||||
Unp->SetDestSize (UnpackSize);
|
||||
|
||||
Unp->SetExternalBuffer (Inp, VM);
|
||||
|
||||
Unp->DoUnpack (METHOD, SOLID); // sets output
|
||||
|
||||
unsigned int crc32 = (unsigned int) DataIO.UnpHash.GetCRC32 ();
|
||||
|
||||
delete Unp;
|
||||
|
||||
return crc32;
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
****** ***** ****** UnRAR - free utility for RAR archives
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
****** ******* ****** License for use and distribution of
|
||||
** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
** ** ** ** ** ** FREE portable version
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The source code of UnRAR utility is freeware. This means:
|
||||
|
||||
1. All copyrights to RAR and the utility UnRAR are exclusively
|
||||
owned by the author - Alexander Roshal.
|
||||
|
||||
2. UnRAR source code may be used in any software to handle
|
||||
RAR archives without limitations free of charge, but cannot be
|
||||
used to develop RAR (WinRAR) compatible archiver and to
|
||||
re-create RAR compression algorithm, which is proprietary.
|
||||
Distribution of modified UnRAR source code in separate form
|
||||
or as a part of other software is permitted, provided that
|
||||
full text of this paragraph, starting from "UnRAR source code"
|
||||
words, is included in license, or in documentation if license
|
||||
is not available, and in source code comments of resulting package.
|
||||
|
||||
3. The UnRAR utility may be freely distributed. It is allowed
|
||||
to distribute UnRAR inside of other software packages.
|
||||
|
||||
4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
|
||||
NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
|
||||
YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
|
||||
DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
|
||||
OR MISUSING THIS SOFTWARE.
|
||||
|
||||
5. Installing and using the UnRAR utility signifies acceptance of
|
||||
these terms and conditions of the license.
|
||||
|
||||
6. If you don't agree with terms of the license you must remove
|
||||
UnRAR files from your storage devices and cease to use the
|
||||
utility.
|
||||
|
||||
Thank you for your interest in RAR and UnRAR.
|
||||
|
||||
|
||||
Alexander L. Roshal
|
@ -0,0 +1,397 @@
|
||||
/**
|
||||
* Author......: See docs/credits.txt
|
||||
* License.....: MIT
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "modules.h"
|
||||
#include "bitops.h"
|
||||
#include "convert.h"
|
||||
#include "shared.h"
|
||||
|
||||
static const u32 ATTACK_EXEC = ATTACK_EXEC_OUTSIDE_KERNEL;
|
||||
static const u32 DGST_POS0 = 0;
|
||||
static const u32 DGST_POS1 = 1;
|
||||
static const u32 DGST_POS2 = 2;
|
||||
static const u32 DGST_POS3 = 3;
|
||||
static const u32 DGST_SIZE = DGST_SIZE_4_4; // actually only DGST_SIZE_4_1
|
||||
static const u32 HASH_CATEGORY = HASH_CATEGORY_ARCHIVE;
|
||||
static const char *HASH_NAME = "RAR3-p (Uncompressed)";
|
||||
static const u64 KERN_TYPE = 23700;
|
||||
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE;
|
||||
static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE;
|
||||
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
|
||||
static const char *ST_PASS = "hashcat";
|
||||
static const char *ST_HASH = "$RAR3$*1*e54a73729887cb53*49b0a846*16*14*1*34620bcca8176642a210b1051901921e*30";
|
||||
|
||||
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_dgst_pos0 (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 DGST_POS0; }
|
||||
u32 module_dgst_pos1 (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 DGST_POS1; }
|
||||
u32 module_dgst_pos2 (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 DGST_POS2; }
|
||||
u32 module_dgst_pos3 (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 DGST_POS3; }
|
||||
u32 module_dgst_size (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 DGST_SIZE; }
|
||||
u32 module_hash_category (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 HASH_CATEGORY; }
|
||||
const char *module_hash_name (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 HASH_NAME; }
|
||||
u64 module_kern_type (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 KERN_TYPE; }
|
||||
u32 module_opti_type (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 OPTI_TYPE; }
|
||||
u64 module_opts_type (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 OPTS_TYPE; }
|
||||
u32 module_salt_type (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 SALT_TYPE; }
|
||||
const char *module_st_hash (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 ST_HASH; }
|
||||
const char *module_st_pass (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 ST_PASS; }
|
||||
|
||||
typedef struct rar3
|
||||
{
|
||||
u32 data[81920];
|
||||
|
||||
u32 pack_size;
|
||||
u32 unpack_size;
|
||||
|
||||
} rar3_t;
|
||||
|
||||
typedef struct rar3_tmp
|
||||
{
|
||||
u32 dgst[5];
|
||||
|
||||
u32 w[66]; // 256 byte pass + 8 byte salt
|
||||
|
||||
u32 iv[4];
|
||||
|
||||
} rar3_tmp_t;
|
||||
|
||||
typedef struct rar3_tmp_optimized
|
||||
{
|
||||
u32 dgst[17][5];
|
||||
|
||||
} rar3_tmp_optimized_t;
|
||||
|
||||
static const int ROUNDS_RAR3 = 262144;
|
||||
static const char *SIGNATURE_RAR3 = "$RAR3$";
|
||||
|
||||
u64 module_tmp_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const bool optimized_kernel = user_options->optimized_kernel_enable;
|
||||
|
||||
u64 tmp_size = (u64) sizeof (rar3_tmp_t);
|
||||
|
||||
if (optimized_kernel == true)
|
||||
{
|
||||
tmp_size = (u64) sizeof (rar3_tmp_optimized_t);
|
||||
}
|
||||
|
||||
return tmp_size;
|
||||
}
|
||||
|
||||
u64 module_esalt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
u64 esalt_size = (u64) sizeof (rar3_t);
|
||||
|
||||
return esalt_size;
|
||||
}
|
||||
|
||||
u32 module_kernel_loops_min (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u32 kernel_loops_min = ROUNDS_RAR3 / 16;
|
||||
|
||||
return kernel_loops_min;
|
||||
}
|
||||
|
||||
u32 module_kernel_loops_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u32 kernel_loops_max = ROUNDS_RAR3 / 16;
|
||||
|
||||
return kernel_loops_max;
|
||||
}
|
||||
|
||||
u32 module_kernel_threads_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
// -T 128 works slightly faster but it's free for the user to change
|
||||
|
||||
const u32 kernel_threads_max = (user_options->kernel_threads_chgd == true) ? user_options->kernel_threads : 128;
|
||||
|
||||
return kernel_threads_max;
|
||||
}
|
||||
|
||||
u32 module_pw_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const bool optimized_kernel = (hashconfig->opti_type & OPTI_TYPE_OPTIMIZED_KERNEL);
|
||||
|
||||
u32 pw_max = 127;
|
||||
|
||||
if (optimized_kernel == true)
|
||||
{
|
||||
pw_max = 20;
|
||||
}
|
||||
|
||||
return pw_max;
|
||||
}
|
||||
|
||||
const char *module_benchmark_mask (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const char *mask = "?b?b?b?b?b";
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED void *hook_salt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
|
||||
{
|
||||
u32 *digest = (u32 *) digest_buf;
|
||||
|
||||
rar3_t *rar3 = (rar3_t *) esalt_buf;
|
||||
|
||||
token_t token;
|
||||
|
||||
token.token_cnt = 9;
|
||||
|
||||
token.signatures_cnt = 1;
|
||||
token.signatures_buf[0] = SIGNATURE_RAR3;
|
||||
|
||||
token.sep[0] = '*';
|
||||
token.len_min[0] = 6;
|
||||
token.len_max[0] = 6;
|
||||
token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_SIGNATURE;
|
||||
|
||||
token.sep[1] = '*';
|
||||
token.len_min[1] = 1;
|
||||
token.len_max[1] = 1;
|
||||
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[2] = '*';
|
||||
token.len_min[2] = 16;
|
||||
token.len_max[2] = 16;
|
||||
token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.sep[3] = '*';
|
||||
token.len_min[3] = 8;
|
||||
token.len_max[3] = 8;
|
||||
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.sep[4] = '*';
|
||||
token.len_min[4] = 1;
|
||||
token.len_max[4] = 7;
|
||||
token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[5] = '*';
|
||||
token.len_min[5] = 1;
|
||||
token.len_max[5] = 6;
|
||||
token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[6] = '*';
|
||||
token.len_min[6] = 1;
|
||||
token.len_max[6] = 1;
|
||||
token.attr[6] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[7] = '*';
|
||||
token.len_min[7] = 2;
|
||||
token.len_max[7] = 655056;
|
||||
token.attr[7] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.len[8] = 2;
|
||||
token.attr[8] = TOKEN_ATTR_FIXED_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
|
||||
|
||||
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
|
||||
|
||||
const u8 *type_pos = token.buf[1];
|
||||
|
||||
if (type_pos[0] != '1') return (PARSER_SIGNATURE_UNMATCHED);
|
||||
|
||||
// salt
|
||||
|
||||
const u8 *salt_pos = token.buf[2];
|
||||
|
||||
salt->salt_buf[0] = hex_to_u32 (salt_pos + 0);
|
||||
salt->salt_buf[1] = hex_to_u32 (salt_pos + 8);
|
||||
|
||||
salt->salt_len = 8;
|
||||
salt->salt_iter = ROUNDS_RAR3;
|
||||
|
||||
// CRC32
|
||||
|
||||
const u8 *crc32_pos = token.buf[3];
|
||||
|
||||
u32 crc32_sum = hex_to_u32 (crc32_pos);
|
||||
|
||||
// pack size
|
||||
|
||||
const u8 *pack_size_pos = token.buf[4];
|
||||
|
||||
const u32 pack_size = hc_strtoul ((const char *) pack_size_pos, NULL, 10);
|
||||
|
||||
if (pack_size < 1) return (PARSER_SALT_VALUE);
|
||||
if (pack_size > 327680) return (PARSER_SALT_VALUE);
|
||||
|
||||
if ((pack_size % 16) != 0) return (PARSER_SALT_VALUE);
|
||||
|
||||
rar3->pack_size = pack_size;
|
||||
|
||||
// unpack size
|
||||
|
||||
const u8 *unpack_size_pos = token.buf[5];
|
||||
|
||||
const u32 unpack_size = hc_strtoul ((const char *) unpack_size_pos, NULL, 10);
|
||||
|
||||
if (unpack_size < 1) return (PARSER_SALT_VALUE);
|
||||
if (unpack_size > 655360) return (PARSER_SALT_VALUE);
|
||||
|
||||
if (unpack_size > pack_size) return (PARSER_SALT_VALUE);
|
||||
|
||||
rar3->unpack_size = unpack_size;
|
||||
|
||||
// data is within the hash line
|
||||
|
||||
const u8 *is_data_pos = token.buf[6];
|
||||
|
||||
if (is_data_pos[0] != '1') return (PARSER_SALT_VALUE);
|
||||
|
||||
// data
|
||||
|
||||
const u8 *data_pos = token.buf[7];
|
||||
const u32 data_len = token.len[7];
|
||||
|
||||
if (data_len != (pack_size * 2)) return (PARSER_SALT_VALUE);
|
||||
|
||||
// like hex decode, but swapped:
|
||||
// hex_decode (data_pos, data_len, (u8 *) rar3->data);
|
||||
|
||||
for (u32 i = 0, j = 0; i < data_len; i += 8, j++)
|
||||
{
|
||||
rar3->data[j] = hex_to_u32 (data_pos + i);
|
||||
|
||||
rar3->data[j] = byte_swap_32 (rar3->data[j]);
|
||||
}
|
||||
|
||||
// method
|
||||
|
||||
const u8 *method_pos = token.buf[8];
|
||||
|
||||
const u32 method = hc_strtoul ((const char *) method_pos, NULL, 10);
|
||||
|
||||
if (method != 30) return (PARSER_SALT_VALUE);
|
||||
|
||||
// digest
|
||||
|
||||
digest[0] = crc32_sum ^ 0xffffffff;
|
||||
digest[1] = 0;
|
||||
digest[2] = 0;
|
||||
digest[3] = 0;
|
||||
|
||||
return (PARSER_OK);
|
||||
}
|
||||
|
||||
int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const void *digest_buf, MAYBE_UNUSED const salt_t *salt, MAYBE_UNUSED const void *esalt_buf, MAYBE_UNUSED const void *hook_salt_buf, MAYBE_UNUSED const hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
|
||||
{
|
||||
const u32 *digest = (const u32 *) digest_buf;
|
||||
const rar3_t *rar3 = (const rar3_t *) esalt_buf;
|
||||
|
||||
u8 data[655360] = { 0 };
|
||||
|
||||
const u32 data_len = rar3->pack_size;
|
||||
|
||||
// like hex encode, but swapped:
|
||||
// hex_encode ((const u8 *) rar3->data, rar3->pack_size, data);
|
||||
|
||||
for (u32 i = 0, j = 0; i < data_len / 4; i += 1, j += 8)
|
||||
{
|
||||
const u32 d = byte_swap_32 (rar3->data[i]);
|
||||
|
||||
u32_to_hex (d, data + j);
|
||||
}
|
||||
|
||||
const int line_len = snprintf (line_buf, line_size, "%s*1*%08x%08x*%08x*%u*%u*1*%s*30",
|
||||
SIGNATURE_RAR3,
|
||||
byte_swap_32 (salt->salt_buf[0]),
|
||||
byte_swap_32 (salt->salt_buf[1]),
|
||||
byte_swap_32 (digest[0]) ^ 0xffffffff,
|
||||
rar3->pack_size,
|
||||
rar3->unpack_size,
|
||||
data);
|
||||
|
||||
return line_len;
|
||||
}
|
||||
|
||||
void module_init (module_ctx_t *module_ctx)
|
||||
{
|
||||
module_ctx->module_context_size = MODULE_CONTEXT_SIZE_CURRENT;
|
||||
module_ctx->module_interface_version = MODULE_INTERFACE_VERSION_CURRENT;
|
||||
|
||||
module_ctx->module_attack_exec = module_attack_exec;
|
||||
module_ctx->module_benchmark_esalt = MODULE_DEFAULT;
|
||||
module_ctx->module_benchmark_hook_salt = MODULE_DEFAULT;
|
||||
module_ctx->module_benchmark_mask = module_benchmark_mask;
|
||||
module_ctx->module_benchmark_salt = MODULE_DEFAULT;
|
||||
module_ctx->module_build_plain_postprocess = MODULE_DEFAULT;
|
||||
module_ctx->module_deep_comp_kernel = MODULE_DEFAULT;
|
||||
module_ctx->module_dgst_pos0 = module_dgst_pos0;
|
||||
module_ctx->module_dgst_pos1 = module_dgst_pos1;
|
||||
module_ctx->module_dgst_pos2 = module_dgst_pos2;
|
||||
module_ctx->module_dgst_pos3 = module_dgst_pos3;
|
||||
module_ctx->module_dgst_size = module_dgst_size;
|
||||
module_ctx->module_dictstat_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_esalt_size = module_esalt_size;
|
||||
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
|
||||
module_ctx->module_extra_tmp_size = MODULE_DEFAULT;
|
||||
module_ctx->module_forced_outfile_format = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_count = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_parse = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_save = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode_potfile = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode = module_hash_decode;
|
||||
module_ctx->module_hash_encode_status = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_encode_potfile = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_encode = module_hash_encode;
|
||||
module_ctx->module_hash_init_selftest = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_mode = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_category = module_hash_category;
|
||||
module_ctx->module_hash_name = module_hash_name;
|
||||
module_ctx->module_hashes_count_min = MODULE_DEFAULT;
|
||||
module_ctx->module_hashes_count_max = MODULE_DEFAULT;
|
||||
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_extra_param_size = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_extra_param_init = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_extra_param_term = MODULE_DEFAULT;
|
||||
module_ctx->module_hook12 = MODULE_DEFAULT;
|
||||
module_ctx->module_hook23 = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_salt_size = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_size = MODULE_DEFAULT;
|
||||
module_ctx->module_jit_build_options = MODULE_DEFAULT;
|
||||
module_ctx->module_jit_cache_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_accel_max = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_accel_min = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_loops_max = module_kernel_loops_max;
|
||||
module_ctx->module_kernel_loops_min = module_kernel_loops_min;
|
||||
module_ctx->module_kernel_threads_max = module_kernel_threads_max;
|
||||
module_ctx->module_kernel_threads_min = MODULE_DEFAULT;
|
||||
module_ctx->module_kern_type = module_kern_type;
|
||||
module_ctx->module_kern_type_dynamic = MODULE_DEFAULT;
|
||||
module_ctx->module_opti_type = module_opti_type;
|
||||
module_ctx->module_opts_type = module_opts_type;
|
||||
module_ctx->module_outfile_check_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_outfile_check_nocomp = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_custom_check = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_keep_all_hashes = MODULE_DEFAULT;
|
||||
module_ctx->module_pwdump_column = MODULE_DEFAULT;
|
||||
module_ctx->module_pw_max = module_pw_max;
|
||||
module_ctx->module_pw_min = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_max = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_min = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_type = module_salt_type;
|
||||
module_ctx->module_separator = MODULE_DEFAULT;
|
||||
module_ctx->module_st_hash = module_st_hash;
|
||||
module_ctx->module_st_pass = module_st_pass;
|
||||
module_ctx->module_tmp_size = module_tmp_size;
|
||||
module_ctx->module_unstable_warning = MODULE_DEFAULT;
|
||||
module_ctx->module_warmup_disable = MODULE_DEFAULT;
|
||||
}
|
@ -0,0 +1,663 @@
|
||||
/**
|
||||
* Author......: See docs/credits.txt
|
||||
* License.....: MIT
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
#include "modules.h"
|
||||
#include "bitops.h"
|
||||
#include "convert.h"
|
||||
#include "shared.h"
|
||||
#include "memory.h"
|
||||
|
||||
static const u32 ATTACK_EXEC = ATTACK_EXEC_OUTSIDE_KERNEL;
|
||||
static const u32 DGST_POS0 = 0;
|
||||
static const u32 DGST_POS1 = 1;
|
||||
static const u32 DGST_POS2 = 2;
|
||||
static const u32 DGST_POS3 = 3;
|
||||
static const u32 DGST_SIZE = DGST_SIZE_4_4; // actually only DGST_SIZE_4_1
|
||||
static const u32 HASH_CATEGORY = HASH_CATEGORY_ARCHIVE;
|
||||
static const char *HASH_NAME = "RAR3-p (Compressed)";
|
||||
static const u64 KERN_TYPE = 23800;
|
||||
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE;
|
||||
static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE
|
||||
| OPTS_TYPE_HOOK23;
|
||||
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
|
||||
static const char *ST_PASS = "hashcat";
|
||||
static const char *ST_HASH = "$RAR3$*1*ad56eb40219c9da2*834064ce*32*13*1*eb47b1abe17a1a75bce6c92ab1cef3f4126035ea95deaf08b3f32a0c7b8078e1*33";
|
||||
|
||||
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_dgst_pos0 (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 DGST_POS0; }
|
||||
u32 module_dgst_pos1 (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 DGST_POS1; }
|
||||
u32 module_dgst_pos2 (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 DGST_POS2; }
|
||||
u32 module_dgst_pos3 (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 DGST_POS3; }
|
||||
u32 module_dgst_size (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 DGST_SIZE; }
|
||||
u32 module_hash_category (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 HASH_CATEGORY; }
|
||||
const char *module_hash_name (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 HASH_NAME; }
|
||||
u64 module_kern_type (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 KERN_TYPE; }
|
||||
u32 module_opti_type (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 OPTI_TYPE; }
|
||||
u64 module_opts_type (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 OPTS_TYPE; }
|
||||
u32 module_salt_type (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 SALT_TYPE; }
|
||||
const char *module_st_hash (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 ST_HASH; }
|
||||
const char *module_st_pass (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 ST_PASS; }
|
||||
|
||||
typedef struct rar3
|
||||
{
|
||||
u32 first_block_encrypted[4];
|
||||
|
||||
} rar3_t;
|
||||
|
||||
typedef struct rar3_tmp
|
||||
{
|
||||
u32 dgst[5];
|
||||
|
||||
u32 w[66]; // 256 byte pass + 8 byte salt
|
||||
|
||||
u32 iv[4];
|
||||
|
||||
} rar3_tmp_t;
|
||||
|
||||
typedef struct rar3_tmp_optimized
|
||||
{
|
||||
u32 dgst[17][5];
|
||||
|
||||
} rar3_tmp_optimized_t;
|
||||
|
||||
typedef struct rar3_hook
|
||||
{
|
||||
u32 key[4];
|
||||
u32 iv[4];
|
||||
|
||||
u32 first_block_decrypted[4];
|
||||
|
||||
u32 crc32;
|
||||
|
||||
} rar3_hook_t;
|
||||
|
||||
typedef struct rar3_hook_salt
|
||||
{
|
||||
u32 data[81920];
|
||||
|
||||
u32 pack_size;
|
||||
u32 unpack_size;
|
||||
|
||||
u32 method;
|
||||
|
||||
} rar3_hook_salt_t;
|
||||
|
||||
typedef struct rar3_hook_extra
|
||||
{
|
||||
void **win;
|
||||
void **inp;
|
||||
void **vm;
|
||||
void **ppm;
|
||||
|
||||
} rar3_hook_extra_t;
|
||||
|
||||
static const int ROUNDS_RAR3 = 262144;
|
||||
static const char *SIGNATURE_RAR3 = "$RAR3$";
|
||||
|
||||
#define ADD_BITS(n) \
|
||||
{ \
|
||||
if (bits < 9) \
|
||||
{ \
|
||||
hold |= ((unsigned int) *next++ << (24 - bits)); \
|
||||
bits += 8; \
|
||||
} \
|
||||
\
|
||||
hold <<= n; \
|
||||
bits -= n; \
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function was implemented similar to the check_huffman ()
|
||||
* function from John The Ripper.
|
||||
* Thanks go to magnum and JTR for the permission.
|
||||
*/
|
||||
|
||||
static int check_huffman (const unsigned char *next)
|
||||
{
|
||||
unsigned int bits;
|
||||
unsigned int hold;
|
||||
unsigned int i;
|
||||
int left;
|
||||
unsigned int ncount[4];
|
||||
unsigned char *count = (unsigned char*) ncount;
|
||||
unsigned char bit_length[20];
|
||||
|
||||
hold = next[3]
|
||||
+ (((unsigned int) next[2]) << 8)
|
||||
+ (((unsigned int) next[1]) << 16)
|
||||
+ (((unsigned int) next[0]) << 24);
|
||||
|
||||
next += 4; // we already have the first 32 bits
|
||||
hold <<= 2; // we already processed 2 bits, PPM and keepOldTable
|
||||
bits = 32 - 2;
|
||||
|
||||
/* First, read 20 pairs of (bitlength[, zerocount]) */
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
int length, zero_count;
|
||||
|
||||
length = hold >> 28;
|
||||
|
||||
ADD_BITS (4);
|
||||
|
||||
if (length == 15)
|
||||
{
|
||||
zero_count = hold >> 28;
|
||||
|
||||
ADD_BITS (4);
|
||||
|
||||
if (zero_count == 0)
|
||||
{
|
||||
bit_length[i] = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
zero_count += 2;
|
||||
|
||||
while (zero_count-- > 0 && i < sizeof(bit_length) / sizeof (bit_length[0]))
|
||||
{
|
||||
bit_length[i++] = 0;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bit_length[i] = length;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the number of codes for each code length */
|
||||
memset (count, 0, 16);
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
++count[bit_length[i]];
|
||||
}
|
||||
|
||||
count[0] = 0;
|
||||
|
||||
if (!ncount[0] && !ncount[1] && !ncount[2] && !ncount[3]) return 0; /* No codes at all */
|
||||
|
||||
left = 1;
|
||||
|
||||
for (i = 1; i < 16; ++i)
|
||||
{
|
||||
left <<= 1;
|
||||
left -= count[i];
|
||||
|
||||
if (left < 0) return 0; /* over-subscribed */
|
||||
}
|
||||
|
||||
if (left) return 0; /* incomplete set */
|
||||
|
||||
return 1; /* Passed this check! */
|
||||
}
|
||||
|
||||
bool module_hook_extra_param_init (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const folder_config_t *folder_config, MAYBE_UNUSED const backend_ctx_t *backend_ctx, void *hook_extra_param)
|
||||
{
|
||||
rar3_hook_extra_t *rar3_hook_extra = (rar3_hook_extra_t *) hook_extra_param;
|
||||
|
||||
#define WINSIZE 0x100000
|
||||
#define INPSIZE 0x50000
|
||||
#define PPMSIZE 216 * 1024 * 1024
|
||||
|
||||
rar3_hook_extra->win = hccalloc (backend_ctx->backend_devices_cnt, sizeof (void *));
|
||||
|
||||
if (rar3_hook_extra->win == NULL) return false;
|
||||
|
||||
rar3_hook_extra->inp = hccalloc (backend_ctx->backend_devices_cnt, sizeof (void *));
|
||||
|
||||
if (rar3_hook_extra->inp == NULL) return false;
|
||||
|
||||
rar3_hook_extra->vm = hccalloc (backend_ctx->backend_devices_cnt, sizeof (void *));
|
||||
|
||||
if (rar3_hook_extra->vm == NULL) return false;
|
||||
|
||||
rar3_hook_extra->ppm = hccalloc (backend_ctx->backend_devices_cnt, sizeof (void *));
|
||||
|
||||
if (rar3_hook_extra->ppm == NULL) return false;
|
||||
|
||||
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
|
||||
{
|
||||
hc_device_param_t *device_param = &backend_ctx->devices_param[backend_devices_idx];
|
||||
|
||||
if (device_param->skipped == true) continue;
|
||||
|
||||
rar3_hook_extra->win[backend_devices_idx] = hcmalloc (WINSIZE);
|
||||
|
||||
if (rar3_hook_extra->win[backend_devices_idx] == NULL) return false;
|
||||
|
||||
rar3_hook_extra->inp[backend_devices_idx] = hcmalloc (INPSIZE);
|
||||
|
||||
if (rar3_hook_extra->inp[backend_devices_idx] == NULL) return false;
|
||||
|
||||
rar3_hook_extra->vm [backend_devices_idx] = hcmalloc (INPSIZE);
|
||||
|
||||
if (rar3_hook_extra->vm [backend_devices_idx] == NULL) return false;
|
||||
|
||||
rar3_hook_extra->ppm[backend_devices_idx] = hcmalloc (PPMSIZE);
|
||||
|
||||
if (rar3_hook_extra->ppm[backend_devices_idx] == NULL) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool module_hook_extra_param_term (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const folder_config_t *folder_config, MAYBE_UNUSED const backend_ctx_t *backend_ctx, void *hook_extra_param)
|
||||
{
|
||||
rar3_hook_extra_t *rar3_hook_extra = (rar3_hook_extra_t *) hook_extra_param;
|
||||
|
||||
for (int backend_devices_idx = 0; backend_devices_idx < backend_ctx->backend_devices_cnt; backend_devices_idx++)
|
||||
{
|
||||
hc_device_param_t *device_param = &backend_ctx->devices_param[backend_devices_idx];
|
||||
|
||||
if (device_param->skipped == true) continue;
|
||||
|
||||
hcfree (rar3_hook_extra->ppm[backend_devices_idx]);
|
||||
hcfree (rar3_hook_extra->win[backend_devices_idx]);
|
||||
hcfree (rar3_hook_extra->inp[backend_devices_idx]);
|
||||
hcfree (rar3_hook_extra->vm [backend_devices_idx]);
|
||||
}
|
||||
|
||||
hcfree (rar3_hook_extra->win);
|
||||
hcfree (rar3_hook_extra->inp);
|
||||
hcfree (rar3_hook_extra->vm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int hc_decompress_rar (unsigned char *Win, unsigned char *Inp, unsigned char *VM, unsigned char *PPM, const unsigned int OutputSize, const unsigned char *Input, const unsigned int PackSize, const unsigned int UnpackSize, const unsigned char *Key, const unsigned char *IV);
|
||||
|
||||
void module_hook23 (hc_device_param_t *device_param, const void *hook_extra_param, const void *hook_salts_buf, const u32 salt_pos, const u64 pw_pos)
|
||||
{
|
||||
rar3_hook_t *hook_items = (rar3_hook_t *) device_param->hooks_buf;
|
||||
rar3_hook_t *hook_item = &hook_items[pw_pos];
|
||||
|
||||
rar3_hook_salt_t *rar3s = (rar3_hook_salt_t *) hook_salts_buf;
|
||||
rar3_hook_salt_t *rar3 = &rar3s[salt_pos];
|
||||
|
||||
rar3_hook_extra_t *rar3_hook_extra = (rar3_hook_extra_t *) hook_extra_param;
|
||||
|
||||
const unsigned int pack_size = (const unsigned int) rar3->pack_size;
|
||||
const unsigned int unpack_size = (const unsigned int) rar3->unpack_size;
|
||||
|
||||
const u8 *first_block_decrypted = (const u8 *) hook_item->first_block_decrypted;
|
||||
|
||||
/* Early rejection */
|
||||
if (first_block_decrypted[0] & 0x80)
|
||||
{
|
||||
// PPM checks here.
|
||||
if (((first_block_decrypted[0] & 0x20) == 0) // Reset bit must be set
|
||||
|| (first_block_decrypted[1] & 0x80)) // MaxMB must be < 128
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// LZ checks here.
|
||||
if ((first_block_decrypted[0] & 0x40) // KeepOldTable can't be set
|
||||
|| (check_huffman (first_block_decrypted)) == 0) // Huffman table check
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const u8 *data = (u8 *) rar3->data;
|
||||
|
||||
const u8 *key = (u8 *) hook_item->key;
|
||||
const u8 *iv = (u8 *) hook_item->iv;
|
||||
|
||||
const u32 crc32 = hc_decompress_rar (rar3_hook_extra->win[device_param->device_id], rar3_hook_extra->inp[device_param->device_id], rar3_hook_extra->vm[device_param->device_id], rar3_hook_extra->ppm[device_param->device_id], unpack_size, data, pack_size, unpack_size, key, iv);
|
||||
|
||||
hook_item->crc32 = crc32;
|
||||
}
|
||||
|
||||
u64 module_hook_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u64 hook_size = (const u64) sizeof (rar3_hook_t);
|
||||
|
||||
return hook_size;
|
||||
}
|
||||
|
||||
u64 module_hook_salt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u64 hook_salt_size = (const u64) sizeof (rar3_hook_salt_t);
|
||||
|
||||
return hook_salt_size;
|
||||
}
|
||||
|
||||
u64 module_hook_extra_param_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u64 hook_extra_param_size = (const u64) sizeof (rar3_hook_extra_t);
|
||||
|
||||
return hook_extra_param_size;
|
||||
}
|
||||
|
||||
u64 module_tmp_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const bool optimized_kernel = user_options->optimized_kernel_enable;
|
||||
|
||||
u64 tmp_size = (u64) sizeof (rar3_tmp_t);
|
||||
|
||||
if (optimized_kernel == true)
|
||||
{
|
||||
tmp_size = (u64) sizeof (rar3_tmp_optimized_t);
|
||||
}
|
||||
|
||||
return tmp_size;
|
||||
}
|
||||
|
||||
u64 module_esalt_size (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
u64 esalt_size = (u64) sizeof (rar3_t);
|
||||
|
||||
return esalt_size;
|
||||
}
|
||||
|
||||
u32 module_kernel_loops_min (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u32 kernel_loops_min = ROUNDS_RAR3 / 16;
|
||||
|
||||
return kernel_loops_min;
|
||||
}
|
||||
|
||||
u32 module_kernel_loops_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const u32 kernel_loops_max = ROUNDS_RAR3 / 16;
|
||||
|
||||
return kernel_loops_max;
|
||||
}
|
||||
|
||||
u32 module_kernel_threads_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
// -T 128 works slightly faster but it's free for the user to change
|
||||
|
||||
const u32 kernel_threads_max = (user_options->kernel_threads_chgd == true) ? user_options->kernel_threads : 128;
|
||||
|
||||
return kernel_threads_max;
|
||||
}
|
||||
|
||||
u32 module_pw_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const bool optimized_kernel = (hashconfig->opti_type & OPTI_TYPE_OPTIMIZED_KERNEL);
|
||||
|
||||
u32 pw_max = 127;
|
||||
|
||||
if (optimized_kernel == true)
|
||||
{
|
||||
pw_max = 20;
|
||||
}
|
||||
|
||||
return pw_max;
|
||||
}
|
||||
|
||||
const char *module_benchmark_mask (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
||||
{
|
||||
const char *mask = "?b?b?b?b?b";
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
int module_hash_decode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED void *hook_salt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
|
||||
{
|
||||
u32 *digest = (u32 *) digest_buf;
|
||||
|
||||
rar3_t *rar3 = (rar3_t *) esalt_buf;
|
||||
|
||||
rar3_hook_salt_t *rar3_hook_salt = (rar3_hook_salt_t *) hook_salt_buf;
|
||||
|
||||
token_t token;
|
||||
|
||||
token.token_cnt = 9;
|
||||
|
||||
token.signatures_cnt = 1;
|
||||
token.signatures_buf[0] = SIGNATURE_RAR3;
|
||||
|
||||
token.sep[0] = '*';
|
||||
token.len_min[0] = 6;
|
||||
token.len_max[0] = 6;
|
||||
token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_SIGNATURE;
|
||||
|
||||
token.sep[1] = '*';
|
||||
token.len_min[1] = 1;
|
||||
token.len_max[1] = 1;
|
||||
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[2] = '*';
|
||||
token.len_min[2] = 16;
|
||||
token.len_max[2] = 16;
|
||||
token.attr[2] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.sep[3] = '*';
|
||||
token.len_min[3] = 8;
|
||||
token.len_max[3] = 8;
|
||||
token.attr[3] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.sep[4] = '*';
|
||||
token.len_min[4] = 1;
|
||||
token.len_max[4] = 7;
|
||||
token.attr[4] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[5] = '*';
|
||||
token.len_min[5] = 1;
|
||||
token.len_max[5] = 6;
|
||||
token.attr[5] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[6] = '*';
|
||||
token.len_min[6] = 1;
|
||||
token.len_max[6] = 1;
|
||||
token.attr[6] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
token.sep[7] = '*';
|
||||
token.len_min[7] = 2;
|
||||
token.len_max[7] = 655056;
|
||||
token.attr[7] = TOKEN_ATTR_VERIFY_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_HEX;
|
||||
|
||||
token.len[8] = 2;
|
||||
token.attr[8] = TOKEN_ATTR_FIXED_LENGTH
|
||||
| TOKEN_ATTR_VERIFY_DIGIT;
|
||||
|
||||
const int rc_tokenizer = input_tokenizer ((const u8 *) line_buf, line_len, &token);
|
||||
|
||||
if (rc_tokenizer != PARSER_OK) return (rc_tokenizer);
|
||||
|
||||
const u8 *type_pos = token.buf[1];
|
||||
|
||||
if (type_pos[0] != '1') return (PARSER_SIGNATURE_UNMATCHED);
|
||||
|
||||
// salt
|
||||
|
||||
const u8 *salt_pos = token.buf[2];
|
||||
|
||||
salt->salt_buf[0] = hex_to_u32 (salt_pos + 0);
|
||||
salt->salt_buf[1] = hex_to_u32 (salt_pos + 8);
|
||||
|
||||
salt->salt_len = 8;
|
||||
salt->salt_iter = ROUNDS_RAR3;
|
||||
|
||||
// CRC32
|
||||
|
||||
const u8 *crc32_pos = token.buf[3];
|
||||
|
||||
u32 crc32_sum = hex_to_u32 (crc32_pos);
|
||||
|
||||
// pack size
|
||||
|
||||
const u8 *pack_size_pos = token.buf[4];
|
||||
|
||||
const u32 pack_size = hc_strtoul ((const char *) pack_size_pos, NULL, 10);
|
||||
|
||||
if (pack_size < 1) return (PARSER_SALT_VALUE);
|
||||
if (pack_size > 327680) return (PARSER_SALT_VALUE);
|
||||
|
||||
if ((pack_size % 16) != 0) return (PARSER_SALT_VALUE);
|
||||
|
||||
rar3_hook_salt->pack_size = pack_size;
|
||||
|
||||
// unpack size
|
||||
|
||||
const u8 *unpack_size_pos = token.buf[5];
|
||||
|
||||
const u32 unpack_size = hc_strtoul ((const char *) unpack_size_pos, NULL, 10);
|
||||
|
||||
if (unpack_size < 1) return (PARSER_SALT_VALUE);
|
||||
if (unpack_size > 655360) return (PARSER_SALT_VALUE);
|
||||
|
||||
rar3_hook_salt->unpack_size = unpack_size;
|
||||
|
||||
// data is within the hash line
|
||||
|
||||
const u8 *is_data_pos = token.buf[6];
|
||||
|
||||
if (is_data_pos[0] != '1') return (PARSER_SALT_VALUE);
|
||||
|
||||
// data
|
||||
|
||||
const u8 *data_pos = token.buf[7];
|
||||
const u32 data_len = token.len[7];
|
||||
|
||||
if (data_len != (pack_size * 2)) return (PARSER_SALT_VALUE);
|
||||
|
||||
hex_decode (data_pos, data_len, (u8 *) rar3_hook_salt->data);
|
||||
|
||||
rar3->first_block_encrypted[0] = rar3_hook_salt->data[0];
|
||||
rar3->first_block_encrypted[1] = rar3_hook_salt->data[1];
|
||||
rar3->first_block_encrypted[2] = rar3_hook_salt->data[2];
|
||||
rar3->first_block_encrypted[3] = rar3_hook_salt->data[3];
|
||||
|
||||
// method
|
||||
|
||||
const u8 *method_pos = token.buf[8];
|
||||
|
||||
const u32 method = hc_strtoul ((const char *) method_pos, NULL, 10);
|
||||
|
||||
if (method < 31) return (PARSER_SALT_VALUE);
|
||||
if (method > 35) return (PARSER_SALT_VALUE);
|
||||
|
||||
rar3_hook_salt->method = method;
|
||||
|
||||
// digest
|
||||
|
||||
digest[0] = crc32_sum;
|
||||
digest[1] = 0;
|
||||
digest[2] = 0;
|
||||
digest[3] = 0;
|
||||
|
||||
return (PARSER_OK);
|
||||
}
|
||||
|
||||
int module_hash_encode (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const void *digest_buf, MAYBE_UNUSED const salt_t *salt, MAYBE_UNUSED const void *esalt_buf, MAYBE_UNUSED const void *hook_salt_buf, MAYBE_UNUSED const hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
|
||||
{
|
||||
const u32 *digest = (const u32 *) digest_buf;
|
||||
|
||||
rar3_hook_salt_t *rar3_hook_salt = (rar3_hook_salt_t *) hook_salt_buf;
|
||||
|
||||
u8 data[655360] = { 0 };
|
||||
|
||||
const u32 data_len = rar3_hook_salt->pack_size;
|
||||
|
||||
hex_encode ((const u8 *) rar3_hook_salt->data, data_len, data);
|
||||
|
||||
const int line_len = snprintf (line_buf, line_size, "%s*1*%08x%08x*%08x*%u*%u*1*%s*%i",
|
||||
SIGNATURE_RAR3,
|
||||
byte_swap_32 (salt->salt_buf[0]),
|
||||
byte_swap_32 (salt->salt_buf[1]),
|
||||
byte_swap_32 (digest[0]),
|
||||
rar3_hook_salt->pack_size,
|
||||
rar3_hook_salt->unpack_size,
|
||||
data,
|
||||
rar3_hook_salt->method);
|
||||
|
||||
return line_len;
|
||||
}
|
||||
|
||||
void module_init (module_ctx_t *module_ctx)
|
||||
{
|
||||
module_ctx->module_context_size = MODULE_CONTEXT_SIZE_CURRENT;
|
||||
module_ctx->module_interface_version = MODULE_INTERFACE_VERSION_CURRENT;
|
||||
|
||||
module_ctx->module_attack_exec = module_attack_exec;
|
||||
module_ctx->module_benchmark_esalt = MODULE_DEFAULT;
|
||||
module_ctx->module_benchmark_hook_salt = MODULE_DEFAULT;
|
||||
module_ctx->module_benchmark_mask = module_benchmark_mask;
|
||||
module_ctx->module_benchmark_salt = MODULE_DEFAULT;
|
||||
module_ctx->module_build_plain_postprocess = MODULE_DEFAULT;
|
||||
module_ctx->module_deep_comp_kernel = MODULE_DEFAULT;
|
||||
module_ctx->module_dgst_pos0 = module_dgst_pos0;
|
||||
module_ctx->module_dgst_pos1 = module_dgst_pos1;
|
||||
module_ctx->module_dgst_pos2 = module_dgst_pos2;
|
||||
module_ctx->module_dgst_pos3 = module_dgst_pos3;
|
||||
module_ctx->module_dgst_size = module_dgst_size;
|
||||
module_ctx->module_dictstat_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_esalt_size = module_esalt_size;
|
||||
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
|
||||
module_ctx->module_extra_tmp_size = MODULE_DEFAULT;
|
||||
module_ctx->module_forced_outfile_format = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_count = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_parse = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_binary_save = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode_potfile = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_decode = module_hash_decode;
|
||||
module_ctx->module_hash_encode_status = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_encode_potfile = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_encode = module_hash_encode;
|
||||
module_ctx->module_hash_init_selftest = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_mode = MODULE_DEFAULT;
|
||||
module_ctx->module_hash_category = module_hash_category;
|
||||
module_ctx->module_hash_name = module_hash_name;
|
||||
module_ctx->module_hashes_count_min = MODULE_DEFAULT;
|
||||
module_ctx->module_hashes_count_max = MODULE_DEFAULT;
|
||||
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_hook_extra_param_size = module_hook_extra_param_size;
|
||||
module_ctx->module_hook_extra_param_init = module_hook_extra_param_init;
|
||||
module_ctx->module_hook_extra_param_term = module_hook_extra_param_term;
|
||||
module_ctx->module_hook12 = MODULE_DEFAULT;
|
||||
module_ctx->module_hook23 = module_hook23;
|
||||
module_ctx->module_hook_salt_size = module_hook_salt_size;
|
||||
module_ctx->module_hook_size = module_hook_size;
|
||||
module_ctx->module_jit_build_options = MODULE_DEFAULT;
|
||||
module_ctx->module_jit_cache_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_accel_max = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_accel_min = MODULE_DEFAULT;
|
||||
module_ctx->module_kernel_loops_max = module_kernel_loops_max;
|
||||
module_ctx->module_kernel_loops_min = module_kernel_loops_min;
|
||||
module_ctx->module_kernel_threads_max = module_kernel_threads_max;
|
||||
module_ctx->module_kernel_threads_min = MODULE_DEFAULT;
|
||||
module_ctx->module_kern_type = module_kern_type;
|
||||
module_ctx->module_kern_type_dynamic = MODULE_DEFAULT;
|
||||
module_ctx->module_opti_type = module_opti_type;
|
||||
module_ctx->module_opts_type = module_opts_type;
|
||||
module_ctx->module_outfile_check_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_outfile_check_nocomp = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_custom_check = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_disable = MODULE_DEFAULT;
|
||||
module_ctx->module_potfile_keep_all_hashes = MODULE_DEFAULT;
|
||||
module_ctx->module_pwdump_column = MODULE_DEFAULT;
|
||||
module_ctx->module_pw_max = module_pw_max;
|
||||
module_ctx->module_pw_min = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_max = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_min = MODULE_DEFAULT;
|
||||
module_ctx->module_salt_type = module_salt_type;
|
||||
module_ctx->module_separator = MODULE_DEFAULT;
|
||||
module_ctx->module_st_hash = module_st_hash;
|
||||
module_ctx->module_st_pass = module_st_pass;
|
||||
module_ctx->module_tmp_size = module_tmp_size;
|
||||
module_ctx->module_unstable_warning = MODULE_DEFAULT;
|
||||
module_ctx->module_warmup_disable = MODULE_DEFAULT;
|
||||
}
|
@ -0,0 +1,496 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
##
|
||||
## Author......: See docs/credits.txt
|
||||
## License.....: MIT
|
||||
##
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Digest::SHA;
|
||||
use Crypt::CBC;
|
||||
use Encode;
|
||||
use Digest::CRC qw (crc32);
|
||||
|
||||
sub module_constraints { [[0, 127], [8, 8], [0, 20], [8, 8], [-1, -1]] }
|
||||
|
||||
my $ITERATIONS = 0x40000;
|
||||
|
||||
my $FIXED_RAW_STRING = pack ("H*", "c43d7b00400700000000000000000000");
|
||||
|
||||
my $SHA1C00 = 0x5a827999;
|
||||
my $SHA1C01 = 0x6ed9eba1;
|
||||
my $SHA1C02 = 0x8f1bbcdc;
|
||||
my $SHA1C03 = 0xca62c1d6;
|
||||
|
||||
my $SHA1M_A = 0x67452301;
|
||||
my $SHA1M_B = 0xefcdab89;
|
||||
my $SHA1M_C = 0x98badcfe;
|
||||
my $SHA1M_D = 0x10325476;
|
||||
my $SHA1M_E = 0xc3d2e1f0;
|
||||
|
||||
sub rotl32
|
||||
{
|
||||
my $x = shift;
|
||||
my $n = shift;
|
||||
|
||||
return (($x << $n) | ($x >> (32 - $n))) & 0xffffffff;
|
||||
}
|
||||
|
||||
sub blk
|
||||
{
|
||||
my $b = shift;
|
||||
my $i = shift;
|
||||
|
||||
$$b[$i & 15] = rotl32 ($$b[($i + 13) & 15] ^
|
||||
$$b[($i + 8) & 15] ^
|
||||
$$b[($i + 2) & 15] ^
|
||||
$$b[($i + 0) & 15], 1);
|
||||
|
||||
return $$b[$i & 15];
|
||||
}
|
||||
|
||||
sub R0
|
||||
{
|
||||
my ($b, $v, $w, $x, $y, $z, $i) = @_;
|
||||
|
||||
$$b[$i] = unpack ("L<", pack ("L>", $$b[$i])); # blk0 or just swap_byte32 ()
|
||||
|
||||
$z += (($w & ($x ^ $y)) ^ $y) + $$b[$i] + $SHA1C00 + rotl32 ($v, 5);
|
||||
|
||||
$z &= 0xffffffff;
|
||||
|
||||
$w = rotl32 ($w, 30);
|
||||
|
||||
return ($z, $w);
|
||||
}
|
||||
|
||||
sub R1
|
||||
{
|
||||
my ($b, $v, $w, $x, $y, $z, $i) = @_;
|
||||
|
||||
$z += (($w & ($x ^ $y)) ^ $y) + blk ($b, $i) + $SHA1C00 + rotl32 ($v, 5);
|
||||
|
||||
$z &= 0xffffffff;
|
||||
|
||||
$w = rotl32 ($w, 30);
|
||||
|
||||
return ($z, $w);
|
||||
}
|
||||
|
||||
sub R2
|
||||
{
|
||||
my ($b, $v, $w, $x, $y, $z, $i) = @_;
|
||||
|
||||
$z += ($w ^ $x ^ $y) + blk ($b, $i) + $SHA1C01 + rotl32 ($v, 5);
|
||||
|
||||
$z &= 0xffffffff;
|
||||
|
||||
$w = rotl32 ($w, 30);
|
||||
|
||||
return ($z, $w);
|
||||
}
|
||||
|
||||
sub R3
|
||||
{
|
||||
my ($b, $v, $w, $x, $y, $z, $i) = @_;
|
||||
|
||||
$z += ((($w | $x) & $y) | ($w & $x)) + blk ($b, $i) + $SHA1C02 + rotl32 ($v, 5);
|
||||
|
||||
$z &= 0xffffffff;
|
||||
|
||||
$w = rotl32 ($w, 30);
|
||||
|
||||
return ($z, $w);
|
||||
}
|
||||
|
||||
sub R4
|
||||
{
|
||||
my ($b, $v, $w, $x, $y, $z, $i) = @_;
|
||||
|
||||
$z += ($w ^ $x ^ $y) + blk ($b, $i) + $SHA1C03 + rotl32 ($v, 5);
|
||||
|
||||
$z &= 0xffffffff;
|
||||
|
||||
$w = rotl32 ($w, 30);
|
||||
|
||||
return ($z, $w);
|
||||
}
|
||||
|
||||
sub sha1_transform
|
||||
{
|
||||
my ($state, $buffer) = @_;
|
||||
|
||||
my @block = unpack ("L<*", $$buffer);
|
||||
|
||||
my $a = $$state[0];
|
||||
my $b = $$state[1];
|
||||
my $c = $$state[2];
|
||||
my $d = $$state[3];
|
||||
my $e = $$state[4];
|
||||
|
||||
($e, $b) = R0 (\@block, $a, $b, $c, $d, $e, 0);
|
||||
($d, $a) = R0 (\@block, $e, $a, $b, $c, $d, 1);
|
||||
($c, $e) = R0 (\@block, $d, $e, $a, $b, $c, 2);
|
||||
($b, $d) = R0 (\@block, $c, $d, $e, $a, $b, 3);
|
||||
|
||||
($a, $c) = R0 (\@block, $b, $c, $d, $e, $a, 4);
|
||||
($e, $b) = R0 (\@block, $a, $b, $c, $d, $e, 5);
|
||||
($d, $a) = R0 (\@block, $e, $a, $b, $c, $d, 6);
|
||||
($c, $e) = R0 (\@block, $d, $e, $a, $b, $c, 7);
|
||||
|
||||
($b, $d) = R0 (\@block, $c, $d, $e, $a, $b, 8);
|
||||
($a, $c) = R0 (\@block, $b, $c, $d, $e, $a, 9);
|
||||
($e, $b) = R0 (\@block, $a, $b, $c, $d, $e, 10);
|
||||
($d, $a) = R0 (\@block, $e, $a, $b, $c, $d, 11);
|
||||
|
||||
($c, $e) = R0 (\@block, $d, $e, $a, $b, $c, 12);
|
||||
($b, $d) = R0 (\@block, $c, $d, $e, $a, $b, 13);
|
||||
($a, $c) = R0 (\@block, $b, $c, $d, $e, $a, 14);
|
||||
($e, $b) = R0 (\@block, $a, $b, $c, $d, $e, 15);
|
||||
|
||||
($d, $a) = R1 (\@block, $e, $a, $b, $c, $d, 16);
|
||||
($c, $e) = R1 (\@block, $d, $e, $a, $b, $c, 17);
|
||||
($b, $d) = R1 (\@block, $c, $d, $e, $a, $b, 18);
|
||||
($a, $c) = R1 (\@block, $b, $c, $d, $e, $a, 19);
|
||||
|
||||
($e, $b) = R2 (\@block, $a, $b, $c, $d, $e, 20);
|
||||
($d, $a) = R2 (\@block, $e, $a, $b, $c, $d, 21);
|
||||
($c, $e) = R2 (\@block, $d, $e, $a, $b, $c, 22);
|
||||
($b, $d) = R2 (\@block, $c, $d, $e, $a, $b, 23);
|
||||
|
||||
($a, $c) = R2 (\@block, $b, $c, $d, $e, $a, 24);
|
||||
($e, $b) = R2 (\@block, $a, $b, $c, $d, $e, 25);
|
||||
($d, $a) = R2 (\@block, $e, $a, $b, $c, $d, 26);
|
||||
($c, $e) = R2 (\@block, $d, $e, $a, $b, $c, 27);
|
||||
|
||||
($b, $d) = R2 (\@block, $c, $d, $e, $a, $b, 28);
|
||||
($a, $c) = R2 (\@block, $b, $c, $d, $e, $a, 29);
|
||||
($e, $b) = R2 (\@block, $a, $b, $c, $d, $e, 30);
|
||||
($d, $a) = R2 (\@block, $e, $a, $b, $c, $d, 31);
|
||||
|
||||
($c, $e) = R2 (\@block, $d, $e, $a, $b, $c, 32);
|
||||
($b, $d) = R2 (\@block, $c, $d, $e, $a, $b, 33);
|
||||
($a, $c) = R2 (\@block, $b, $c, $d, $e, $a, 34);
|
||||
($e, $b) = R2 (\@block, $a, $b, $c, $d, $e, 35);
|
||||
|
||||
($d, $a) = R2 (\@block, $e, $a, $b, $c, $d, 36);
|
||||
($c, $e) = R2 (\@block, $d, $e, $a, $b, $c, 37);
|
||||
($b, $d) = R2 (\@block, $c, $d, $e, $a, $b, 38);
|
||||
($a, $c) = R2 (\@block, $b, $c, $d, $e, $a, 39);
|
||||
|
||||
($e, $b) = R3 (\@block, $a, $b, $c, $d, $e, 40);
|
||||
($d, $a) = R3 (\@block, $e, $a, $b, $c, $d, 41);
|
||||
($c, $e) = R3 (\@block, $d, $e, $a, $b, $c, 42);
|
||||
($b, $d) = R3 (\@block, $c, $d, $e, $a, $b, 43);
|
||||
|
||||
($a, $c) = R3 (\@block, $b, $c, $d, $e, $a, 44);
|
||||
($e, $b) = R3 (\@block, $a, $b, $c, $d, $e, 45);
|
||||
($d, $a) = R3 (\@block, $e, $a, $b, $c, $d, 46);
|
||||
($c, $e) = R3 (\@block, $d, $e, $a, $b, $c, 47);
|
||||
|
||||
($b, $d) = R3 (\@block, $c, $d, $e, $a, $b, 48);
|
||||
($a, $c) = R3 (\@block, $b, $c, $d, $e, $a, 49);
|
||||
($e, $b) = R3 (\@block, $a, $b, $c, $d, $e, 50);
|
||||
($d, $a) = R3 (\@block, $e, $a, $b, $c, $d, 51);
|
||||
|
||||
($c, $e) = R3 (\@block, $d, $e, $a, $b, $c, 52);
|
||||
($b, $d) = R3 (\@block, $c, $d, $e, $a, $b, 53);
|
||||
($a, $c) = R3 (\@block, $b, $c, $d, $e, $a, 54);
|
||||
($e, $b) = R3 (\@block, $a, $b, $c, $d, $e, 55);
|
||||
|
||||
($d, $a) = R3 (\@block, $e, $a, $b, $c, $d, 56);
|
||||
($c, $e) = R3 (\@block, $d, $e, $a, $b, $c, 57);
|
||||
($b, $d) = R3 (\@block, $c, $d, $e, $a, $b, 58);
|
||||
($a, $c) = R3 (\@block, $b, $c, $d, $e, $a, 59);
|
||||
|
||||
($e, $b) = R4 (\@block, $a, $b, $c, $d, $e, 60);
|
||||
($d, $a) = R4 (\@block, $e, $a, $b, $c, $d, 61);
|
||||
($c, $e) = R4 (\@block, $d, $e, $a, $b, $c, 62);
|
||||
($b, $d) = R4 (\@block, $c, $d, $e, $a, $b, 63);
|
||||
|
||||
($a, $c) = R4 (\@block, $b, $c, $d, $e, $a, 64);
|
||||
($e, $b) = R4 (\@block, $a, $b, $c, $d, $e, 65);
|
||||
($d, $a) = R4 (\@block, $e, $a, $b, $c, $d, 66);
|
||||
($c, $e) = R4 (\@block, $d, $e, $a, $b, $c, 67);
|
||||
|
||||
($b, $d) = R4 (\@block, $c, $d, $e, $a, $b, 68);
|
||||
($a, $c) = R4 (\@block, $b, $c, $d, $e, $a, 69);
|
||||
($e, $b) = R4 (\@block, $a, $b, $c, $d, $e, 70);
|
||||
($d, $a) = R4 (\@block, $e, $a, $b, $c, $d, 71);
|
||||
|
||||
($c, $e) = R4 (\@block, $d, $e, $a, $b, $c, 72);
|
||||
($b, $d) = R4 (\@block, $c, $d, $e, $a, $b, 73);
|
||||
($a, $c) = R4 (\@block, $b, $c, $d, $e, $a, 74);
|
||||
($e, $b) = R4 (\@block, $a, $b, $c, $d, $e, 75);
|
||||
|
||||
($d, $a) = R4 (\@block, $e, $a, $b, $c, $d, 76);
|
||||
($c, $e) = R4 (\@block, $d, $e, $a, $b, $c, 77);
|
||||
($b, $d) = R4 (\@block, $c, $d, $e, $a, $b, 78);
|
||||
($a, $c) = R4 (\@block, $b, $c, $d, $e, $a, 79);
|
||||
|
||||
$$state[0] = ($$state[0] + $a) & 0xffffffff;
|
||||
$$state[1] = ($$state[1] + $b) & 0xffffffff;
|
||||
$$state[2] = ($$state[2] + $c) & 0xffffffff;
|
||||
$$state[3] = ($$state[3] + $d) & 0xffffffff;
|
||||
$$state[4] = ($$state[4] + $e) & 0xffffffff;
|
||||
|
||||
$$buffer = pack ("L<*", @block);
|
||||
}
|
||||
|
||||
sub sha1_getstate
|
||||
{
|
||||
my $ctx = shift;
|
||||
|
||||
my $info = $ctx->getstate;
|
||||
|
||||
# state:
|
||||
|
||||
my $idx = index ($info, "H:");
|
||||
|
||||
my $state = substr ($info, $idx + 2, 44);
|
||||
|
||||
$state =~ s/://g;
|
||||
|
||||
my @state_arr = unpack ("L>*", pack ("H*", $state));
|
||||
|
||||
# block:
|
||||
|
||||
$idx = index ($info, "block:");
|
||||
|
||||
my $block = substr ($info, $idx + 6, 191);
|
||||
|
||||
$block =~ s/://g;
|
||||
|
||||
$block = pack ("H*", $block);
|
||||
|
||||
|
||||
return (\@state_arr, $block);
|
||||
}
|
||||
|
||||
sub sha1_update_rar29
|
||||
{
|
||||
my $ctx = shift;
|
||||
my $data = shift;
|
||||
my $len = shift;
|
||||
my $count = shift;
|
||||
|
||||
my $ctx_orig = $ctx->clone;
|
||||
|
||||
$ctx->add ($$data);
|
||||
|
||||
|
||||
# two early exits from this function, if (strange data) manipulation is not needed:
|
||||
|
||||
my $j = $count & 63;
|
||||
|
||||
return if (($j + $len) <= 63);
|
||||
|
||||
|
||||
my $i = 64 - $j;
|
||||
|
||||
return if (($i + 63) >= $len);
|
||||
|
||||
|
||||
# proceed with updating $data:
|
||||
|
||||
my ($state, $block) = sha1_getstate ($ctx_orig);
|
||||
|
||||
|
||||
substr ($block, $j, $i) = substr ($$data, 0, $i);
|
||||
|
||||
sha1_transform ($state, \$block);
|
||||
|
||||
|
||||
while (($i + 63) < $len)
|
||||
{
|
||||
my $workspace = substr ($$data, $i, 64);
|
||||
|
||||
sha1_transform ($state, \$workspace);
|
||||
|
||||
substr ($$data, $i, 64) = $workspace;
|
||||
|
||||
$i += 64;
|
||||
}
|
||||
}
|
||||
|
||||
sub module_generate_hash
|
||||
{
|
||||
my $word = shift;
|
||||
my $salt = shift;
|
||||
my $crc32_sum = shift;
|
||||
my $pack_size = shift;
|
||||
my $unpack_size = shift;
|
||||
my $data = shift;
|
||||
|
||||
# convert to utf16le:
|
||||
|
||||
my $buf = encode ("UTF-16LE", $word);
|
||||
|
||||
# add the salt to the password buffer:
|
||||
|
||||
$buf .= $salt;
|
||||
|
||||
my $len = length ($buf);
|
||||
|
||||
my $count = 0;
|
||||
|
||||
my $ctx = Digest::SHA->new ('SHA1');
|
||||
|
||||
my $iv = "";
|
||||
|
||||
# main loop:
|
||||
|
||||
for (my $i = 0; $i < $ITERATIONS; $i++)
|
||||
{
|
||||
sha1_update_rar29 ($ctx, \$buf, $len, $count);
|
||||
|
||||
$count += $len;
|
||||
|
||||
my $pos = substr (pack ("L<", $i), 0, 3);
|
||||
|
||||
$ctx->add ($pos);
|
||||
|
||||
$count += 3;
|
||||
|
||||
if (($i & 0x3fff) == 0)
|
||||
{
|
||||
my $dgst = $ctx->clone->digest;
|
||||
|
||||
$iv .= substr ($dgst, 19, 1);
|
||||
}
|
||||
}
|
||||
|
||||
my $k = $ctx->digest;
|
||||
|
||||
$k = pack ("L<*", unpack ("L>4", $k)); # byte swap the first 4 * 4 = 16 bytes
|
||||
|
||||
# AES-128 encrypt:
|
||||
|
||||
my $aes = Crypt::CBC->new (
|
||||
-cipher => "Crypt::Rijndael",
|
||||
-key => $k,
|
||||
-iv => $iv,
|
||||
-keysize => 16,
|
||||
-literal_key => 1,
|
||||
-header => 'none',
|
||||
-padding => 'null'
|
||||
);
|
||||
|
||||
if (defined ($data))
|
||||
{
|
||||
my $data_orig = $data;
|
||||
|
||||
my $data_encrypted = substr ($data, 0, $pack_size);
|
||||
my $data_decrypted = $aes->decrypt ($data_encrypted);
|
||||
|
||||
# CRC32 checksum of the decrypted data:
|
||||
|
||||
my $data_crc = substr ($data_decrypted, 0, $unpack_size);
|
||||
|
||||
my $crc32_computed = crc32 ($data_crc);
|
||||
|
||||
|
||||
$data = "WRONG";
|
||||
|
||||
# verify:
|
||||
|
||||
if ($crc32_computed eq $crc32_sum)
|
||||
{
|
||||
$data = $data_crc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
my $data_len = random_number (1, 4096);
|
||||
|
||||
$data = random_bytes ($data_len);
|
||||
}
|
||||
|
||||
my $crc32_computed = crc32 ($data);
|
||||
|
||||
# byte-swap CRC32 checksum:
|
||||
|
||||
$crc32_computed = unpack ("L<", pack ("L>", $crc32_computed));
|
||||
|
||||
my $data_encrypted = $aes->encrypt ($data);
|
||||
|
||||
$pack_size = length ($data_encrypted);
|
||||
$unpack_size = length ($data);
|
||||
|
||||
return sprintf ("\$RAR3\$*1*%s*%08x*%i*%i*1*%s*30", unpack ("H*", $salt), $crc32_computed, $pack_size, $unpack_size, unpack ("H*", $data_encrypted));
|
||||
}
|
||||
|
||||
sub module_verify_hash
|
||||
{
|
||||
my $line = shift;
|
||||
|
||||
my $idx1 = index ($line, ':');
|
||||
|
||||
return if ($idx1 < 1);
|
||||
|
||||
my $hash = substr ($line, 0, $idx1);
|
||||
my $word = substr ($line, $idx1 + 1);
|
||||
|
||||
return if (substr ($hash, 0, 9) ne "\$RAR3\$*1*");
|
||||
|
||||
$idx1 = index ($hash, '*', 9);
|
||||
|
||||
return if ($idx1 < 1);
|
||||
|
||||
# salt
|
||||
|
||||
my $salt = substr ($hash, 9, $idx1 - 9);
|
||||
|
||||
# crc32
|
||||
|
||||
my $idx2 = index ($hash, '*', $idx1 + 1);
|
||||
|
||||
return if ($idx2 < 1);
|
||||
|
||||
my $crc32_sum = substr ($hash, $idx1 + 1, $idx2 - $idx1 - 1);
|
||||
|
||||
# pack size
|
||||
|
||||
$idx1 = index ($hash, '*', $idx2 + 1);
|
||||
|
||||
return if ($idx1 < 1);
|
||||
|
||||
my $pack_size = substr ($hash, $idx2 + 1, $idx1 - $idx2 - 1);
|
||||
|
||||
# unpack size
|
||||
|
||||
$idx2 = index ($hash, '*', $idx1 + 1);
|
||||
|
||||
return if ($idx2 < 1);
|
||||
|
||||
my $unpack_size = substr ($hash, $idx1 + 1, $idx2 - $idx1 - 1);
|
||||
|
||||
return unless (substr ($hash, $idx2, 3) eq "*1*");
|
||||
|
||||
# data
|
||||
|
||||
$idx1 = index ($hash, '*', $idx2 + 3);
|
||||
|
||||
return if ($idx1 < 1);
|
||||
|
||||
my $data = substr ($hash, $idx2 + 3, $idx1 - $idx2 - 3);
|
||||
|
||||
return unless (substr ($hash, $idx1, 3) eq "*30");
|
||||
|
||||
# convert to hex:
|
||||
|
||||
$salt = pack ("H*", $salt);
|
||||
$data = pack ("H*", $data);
|
||||
|
||||
$crc32_sum = unpack ("L<", pack ("H*", $crc32_sum));
|
||||
|
||||
my $word_packed = pack_if_HEX_notation ($word);
|
||||
|
||||
my $new_hash = module_generate_hash ($word_packed, $salt, $crc32_sum, $pack_size, $unpack_size, $data);
|
||||
|
||||
return ($new_hash, $word);
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in new issue