Add -m 500 unit test

pull/1880/head
jsteube 5 years ago
parent 6a39617949
commit 06a5e736b9

@ -9,58 +9,6 @@ static const float MIN_SUFFICIENT_ENTROPY_FILE = 7.0f;
* algo specific
*/
typedef struct wpa_eapol
{
u32 pke[32];
u32 eapol[64 + 16];
u16 eapol_len;
u8 message_pair;
int message_pair_chgd;
u8 keyver;
u8 orig_mac_ap[6];
u8 orig_mac_sta[6];
u8 orig_nonce_ap[32];
u8 orig_nonce_sta[32];
u8 essid_len;
u8 essid[32];
u32 keymic[4];
u32 hash[4];
int nonce_compare;
int nonce_error_corrections;
int detected_le;
int detected_be;
} wpa_eapol_t;
static const u32 ROUNDS_WPA_PBKDF2 = 4096;
#define HCCAPX_VERSION 4
#define HCCAPX_SIGNATURE 0x58504348 // HCPX
// this is required to force mingw to accept the packed attribute
#pragma pack(push,1)
struct hccapx
{
u32 signature;
u32 version;
u8 message_pair;
u8 essid_len;
u8 essid[32];
u8 keyver;
u8 keymic[16];
u8 mac_ap[6];
u8 nonce_ap[32];
u8 mac_sta[6];
u8 nonce_sta[32];
u16 eapol_len;
u8 eapol[256];
} __attribute__((packed));
typedef struct hccapx hccapx_t;
#pragma pack(pop)
typedef struct itunes_backup
{
@ -489,15 +437,7 @@ typedef struct sha512crypt_tmp
} sha512crypt_tmp_t;
typedef struct wpa_pbkdf2_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[10];
u32 out[10];
} wpa_pbkdf2_tmp_t;
typedef struct wpa_pmk_tmp
{
@ -908,7 +848,6 @@ typedef enum hash_type
HASH_TYPE_SHA384 = 7,
HASH_TYPE_SHA512 = 8,
HASH_TYPE_DCC2 = 9,
HASH_TYPE_WPA_EAPOL = 10,
HASH_TYPE_LM = 11,
HASH_TYPE_ORACLEH = 13,
HASH_TYPE_DESRACF = 14,
@ -999,7 +938,6 @@ typedef enum kern_type
KERN_TYPE_STDOUT = 2000,
KERN_TYPE_DCC2 = 2100,
KERN_TYPE_MD5ASA = 2410,
KERN_TYPE_WPA_EAPOL_PBKDF2 = 2500,
KERN_TYPE_WPA_EAPOL_PMK = 2501,
KERN_TYPE_MD55 = 2600,
KERN_TYPE_MD55_PWSLT1 = 2610,
@ -1170,7 +1108,6 @@ typedef enum kern_type
typedef enum rounds_count
{
ROUNDS_DCC2 = 10240,
ROUNDS_WPA_PBKDF2 = 4096,
ROUNDS_WPA_PMK = 1,
ROUNDS_BCRYPT = (1 << 5),
ROUNDS_PSAFE3 = 2048,
@ -1287,7 +1224,6 @@ int sha512_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_bu
int sha512s_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int sha512crypt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int vb30_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int wpa_eapol_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int psafe2_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int psafe3_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
int ikepsk_md5_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);

@ -4,7 +4,7 @@
##
SHARED := 0
DEBUG := 0
DEBUG := 1
PRODUCTION := 0
PRODUCTION_VERSION := v5.1.0
ENABLE_BRAIN := 0

@ -195,6 +195,8 @@ int save_hash (hashcat_ctx_t *hashcat_ctx)
const int binary_len = module_ctx->module_hash_binary_save (hashes, salt_pos, digest_pos, &binary_buf);
hc_fwrite (binary_buf, binary_len, 1, fp);
hcfree (binary_buf);
}
else
{

@ -60,7 +60,6 @@
" 10900 | PBKDF2-HMAC-SHA256 | Generic KDF",
" 12100 | PBKDF2-HMAC-SHA512 | Generic KDF",
" 23 | Skype | Network Protocols",
" 2500 | WPA-EAPOL-PBKDF2 | Network Protocols",
" 2501 | WPA-EAPOL-PMK | Network Protocols",
" 16800 | WPA-PMKID-PBKDF2 | Network Protocols",
" 16801 | WPA-PMKID-PMK | Network Protocols",
@ -320,7 +319,6 @@ static const char *ST_HASH_01750 = "138c00f17a1a0363f274817c91118f019aff09f937bf
static const char *ST_HASH_01760 = "7d02921299935179d509e6dd4f3d0f2944e3451ea9de3af16baead6a7297e5653577d2473a0fff743d9fe78a89bd49296114319989dc7e7870fc7f62bc96accb:114";
static const char *ST_HASH_01800 = "$6$72820166$U4DVzpcYxgw7MVVDGGvB2/H5lRistD5.Ah4upwENR5UtffLR4X4SxSzfREv8z6wVl0jRFX40/KnYVvK4829kD1";
static const char *ST_HASH_02100 = "$DCC2$10240#6848#e2829c8af2232fa53797e2f0e35e4626";
static const char *ST_HASH_02500 = "4843505804000000000235380000000000000000000000000000000000000000000000000000000000000151aecc428f182acefbd1a9e62d369a079265784da83ba4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b823a1cd402aed449cced04f552c5b5acfebf06ae96a09c96d9a01c443a17aa62258c4f651a68aa67b0001030077fe010900200000000000000001a4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b8230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018dd160050f20101000050f20201000050f20201000050f20200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
static const char *ST_HASH_02501 = "4843505804000000000235380000000000000000000000000000000000000000000000000000000000000151aecc428f182acefbd1a9e62d369a079265784da83ba4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b823a1cd402aed449cced04f552c5b5acfebf06ae96a09c96d9a01c443a17aa62258c4f651a68aa67b0001030077fe010900200000000000000001a4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b8230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018dd160050f20101000050f20201000050f20201000050f20200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
static const char *ST_HASH_02410 = "YjDBNr.A0AN7DA8s:4684";
static const char *ST_HASH_02600 = "a936af92b0ae20b1ff6c3347a72e5fbe";
@ -535,7 +533,6 @@ static const char *HT_01760 = "HMAC-SHA512 (key = $salt)";
static const char *HT_01800 = "sha512crypt $6$, SHA512 (Unix)";
static const char *HT_02100 = "Domain Cached Credentials 2 (DCC2), MS Cache 2";
static const char *HT_02410 = "Cisco-ASA MD5";
static const char *HT_02500 = "WPA-EAPOL-PBKDF2";
static const char *HT_02501 = "WPA-EAPOL-PMK";
static const char *HT_02600 = "md5(md5($pass))";
static const char *HT_03000 = "LM";
@ -3534,251 +3531,6 @@ int dpapimk_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UN
return (PARSER_OK);
}
int wpa_eapol_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig)
{
u32 *digest = (u32 *) hash_buf->digest;
salt_t *salt = hash_buf->salt;
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) hash_buf->esalt;
// the *wpa was partially initialized beforehand, we can not simply memset it to zero
hccapx_t in;
memcpy (&in, input_buf, input_len);
if (in.signature != HCCAPX_SIGNATURE) return (PARSER_HCCAPX_SIGNATURE);
if (in.version != HCCAPX_VERSION) return (PARSER_HCCAPX_VERSION);
if (in.eapol_len < 1 || in.eapol_len > 255) return (PARSER_HCCAPX_EAPOL_LEN);
memcpy (wpa_eapol->keymic, in.keymic, 16);
/*
http://www.one-net.eu/jsw/j_sec/m_ptype.html
The phrase "Pairwise key expansion"
Access Point Address (referred to as Authenticator Address AA)
Supplicant Address (referred to as Supplicant Address SA)
Access Point Nonce (referred to as Authenticator Anonce)
Wireless Device Nonce (referred to as Supplicant Nonce Snonce)
*/
u32 salt_len = in.essid_len;
if (salt_len > 32) return (PARSER_SALT_LENGTH);
memcpy (salt->salt_buf, in.essid, in.essid_len);
salt->salt_len = salt_len;
salt->salt_iter = ROUNDS_WPA_PBKDF2 - 1;
memcpy (wpa_eapol->essid, in.essid, in.essid_len);
wpa_eapol->essid_len = in.essid_len;
wpa_eapol->keyver = in.keyver;
if ((wpa_eapol->keyver != 1) && (wpa_eapol->keyver != 2) && (wpa_eapol->keyver != 3)) return (PARSER_SALT_VALUE);
u8 *pke_ptr = (u8 *) wpa_eapol->pke;
memset (pke_ptr, 0, 128);
if ((wpa_eapol->keyver == 1) || (wpa_eapol->keyver == 2))
{
memcpy (pke_ptr, "Pairwise key expansion", 23);
if (memcmp (in.mac_ap, in.mac_sta, 6) < 0)
{
memcpy (pke_ptr + 23, in.mac_ap, 6);
memcpy (pke_ptr + 29, in.mac_sta, 6);
}
else
{
memcpy (pke_ptr + 23, in.mac_sta, 6);
memcpy (pke_ptr + 29, in.mac_ap, 6);
}
wpa_eapol->nonce_compare = memcmp (in.nonce_ap, in.nonce_sta, 32);
if (wpa_eapol->nonce_compare < 0)
{
memcpy (pke_ptr + 35, in.nonce_ap, 32);
memcpy (pke_ptr + 67, in.nonce_sta, 32);
}
else
{
memcpy (pke_ptr + 35, in.nonce_sta, 32);
memcpy (pke_ptr + 67, in.nonce_ap, 32);
}
}
else if (wpa_eapol->keyver == 3)
{
pke_ptr[0] = 1;
pke_ptr[1] = 0;
memcpy (pke_ptr + 2, "Pairwise key expansion", 22);
if (memcmp (in.mac_ap, in.mac_sta, 6) < 0)
{
memcpy (pke_ptr + 24, in.mac_ap, 6);
memcpy (pke_ptr + 30, in.mac_sta, 6);
}
else
{
memcpy (pke_ptr + 24, in.mac_sta, 6);
memcpy (pke_ptr + 30, in.mac_ap, 6);
}
wpa_eapol->nonce_compare = memcmp (in.nonce_ap, in.nonce_sta, 32);
if (wpa_eapol->nonce_compare < 0)
{
memcpy (pke_ptr + 36, in.nonce_ap, 32);
memcpy (pke_ptr + 68, in.nonce_sta, 32);
}
else
{
memcpy (pke_ptr + 36, in.nonce_sta, 32);
memcpy (pke_ptr + 68, in.nonce_ap, 32);
}
pke_ptr[100] = 0x80;
pke_ptr[101] = 1;
}
for (int i = 0; i < 32; i++)
{
wpa_eapol->pke[i] = byte_swap_32 (wpa_eapol->pke[i]);
}
memcpy (wpa_eapol->orig_mac_ap, in.mac_ap, 6);
memcpy (wpa_eapol->orig_mac_sta, in.mac_sta, 6);
memcpy (wpa_eapol->orig_nonce_ap, in.nonce_ap, 32);
memcpy (wpa_eapol->orig_nonce_sta, in.nonce_sta, 32);
u8 message_pair_orig = in.message_pair;
in.message_pair &= 0x7f; // ignore the highest bit (it is used to indicate if the replay counters did match)
if (wpa_eapol->message_pair_chgd == true)
{
if (wpa_eapol->message_pair != in.message_pair) return (PARSER_HCCAPX_MESSAGE_PAIR);
}
wpa_eapol->message_pair = message_pair_orig;
wpa_eapol->eapol_len = in.eapol_len;
u8 *eapol_ptr = (u8 *) wpa_eapol->eapol;
memcpy (eapol_ptr, in.eapol, wpa_eapol->eapol_len);
memset (eapol_ptr + wpa_eapol->eapol_len, 0, (256 + 64) - wpa_eapol->eapol_len);
eapol_ptr[wpa_eapol->eapol_len] = 0x80;
if (wpa_eapol->keyver == 1)
{
// nothing to do
}
else if (wpa_eapol->keyver == 2)
{
wpa_eapol->keymic[0] = byte_swap_32 (wpa_eapol->keymic[0]);
wpa_eapol->keymic[1] = byte_swap_32 (wpa_eapol->keymic[1]);
wpa_eapol->keymic[2] = byte_swap_32 (wpa_eapol->keymic[2]);
wpa_eapol->keymic[3] = byte_swap_32 (wpa_eapol->keymic[3]);
for (int i = 0; i < 64; i++)
{
wpa_eapol->eapol[i] = byte_swap_32 (wpa_eapol->eapol[i]);
}
}
else if (wpa_eapol->keyver == 3)
{
// nothing to do
}
// Create a hash of the nonce as ESSID is not unique enough
// Not a regular MD5 but good enough
// We can also ignore cases where we should bzero the work buffer
u32 hash[4];
hash[0] = 0;
hash[1] = 1;
hash[2] = 2;
hash[3] = 3;
u32 block[16];
memset (block, 0, sizeof (block));
u8 *block_ptr = (u8 *) block;
for (int i = 0; i < 16; i++) block[i] = salt->salt_buf[i];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->pke[i + 0];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->pke[i + 16];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 0];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 16];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 32];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 48];
md5_64 (block, hash);
for (int i = 0; i < 6; i++) block_ptr[i + 0] = wpa_eapol->orig_mac_ap[i];
for (int i = 0; i < 6; i++) block_ptr[i + 6] = wpa_eapol->orig_mac_sta[i];
md5_64 (block, hash);
for (int i = 0; i < 32; i++) block_ptr[i + 0] = wpa_eapol->orig_nonce_ap[i];
for (int i = 0; i < 32; i++) block_ptr[i + 32] = wpa_eapol->orig_nonce_sta[i];
md5_64 (block, hash);
block[0] = wpa_eapol->keymic[0];
block[1] = wpa_eapol->keymic[1];
block[2] = wpa_eapol->keymic[2];
block[3] = wpa_eapol->keymic[3];
md5_64 (block, hash);
wpa_eapol->hash[0] = hash[0];
wpa_eapol->hash[1] = hash[1];
wpa_eapol->hash[2] = hash[2];
wpa_eapol->hash[3] = hash[3];
// make all this stuff unique
digest[0] = wpa_eapol->hash[0];
digest[1] = wpa_eapol->hash[1];
digest[2] = wpa_eapol->hash[2];
digest[3] = wpa_eapol->hash[3];
return (PARSER_OK);
}
int psafe2_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig)
{
u32 *digest = (u32 *) hash_buf->digest;
@ -17617,8 +17369,6 @@ void hashconfig_benchmark_defaults (hashcat_ctx_t *hashcat_ctx, salt_t *salt, vo
break;
case 2410: salt->salt_len = 4;
break;
case 2500: memcpy (salt->salt_buf, "hashcat.net", 11);
break;
case 2501: memcpy (salt->salt_buf, "hashcat.net", 11);
break;
case 3100: salt->salt_len = 1;
@ -17714,8 +17464,6 @@ void hashconfig_benchmark_defaults (hashcat_ctx_t *hashcat_ctx, salt_t *salt, vo
switch (hashconfig->hash_mode)
{
case 2500: ((wpa_eapol_t *) esalt)->eapol_len = 128;
break;
case 2501: ((wpa_eapol_t *) esalt)->eapol_len = 128;
break;
case 5300: ((ikepsk_t *) esalt)->nr_len = 1;
@ -17797,8 +17545,6 @@ void hashconfig_benchmark_defaults (hashcat_ctx_t *hashcat_ctx, salt_t *salt, vo
break;
case 2100: salt->salt_iter = ROUNDS_DCC2;
break;
case 2500: salt->salt_iter = ROUNDS_WPA_PBKDF2;
break;
case 2501: salt->salt_iter = ROUNDS_WPA_PMK;
break;
case 3200: salt->salt_iter = ROUNDS_BCRYPT;
@ -18376,52 +18122,6 @@ int ascii_digest (hashcat_ctx_t *hashcat_ctx, char *out_buf, const int out_size,
out_buf[16] = 0;
}
else if ((hash_mode == 2500) || (hash_mode == 2501))
{
wpa_eapol_t *wpa_eapols = (wpa_eapol_t *) esalts_buf;
wpa_eapol_t *wpa_eapol = &wpa_eapols[digest_cur];
char *essid = (char *) wpa_eapol->essid;
int tmp_len = 0;
if (need_hexify (wpa_eapol->essid, wpa_eapol->essid_len, hashconfig->separator, 0) == true)
{
tmp_buf[tmp_len++] = '$';
tmp_buf[tmp_len++] = 'H';
tmp_buf[tmp_len++] = 'E';
tmp_buf[tmp_len++] = 'X';
tmp_buf[tmp_len++] = '[';
exec_hexify (wpa_eapol->essid, wpa_eapol->essid_len, (u8 *) tmp_buf + tmp_len);
tmp_len += wpa_eapol->essid_len * 2;
tmp_buf[tmp_len++] = ']';
essid = tmp_buf;
}
snprintf (out_buf, out_size, "%08x%08x%08x%08x:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%s",
wpa_eapol->hash[0],
wpa_eapol->hash[1],
wpa_eapol->hash[2],
wpa_eapol->hash[3],
wpa_eapol->orig_mac_ap[0],
wpa_eapol->orig_mac_ap[1],
wpa_eapol->orig_mac_ap[2],
wpa_eapol->orig_mac_ap[3],
wpa_eapol->orig_mac_ap[4],
wpa_eapol->orig_mac_ap[5],
wpa_eapol->orig_mac_sta[0],
wpa_eapol->orig_mac_sta[1],
wpa_eapol->orig_mac_sta[2],
wpa_eapol->orig_mac_sta[3],
wpa_eapol->orig_mac_sta[4],
wpa_eapol->orig_mac_sta[5],
essid);
}
else if (hash_mode == 4400)
{
snprintf (out_buf, out_size, "%08x%08x%08x%08x",
@ -22606,28 +22306,6 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx)
hashconfig->st_pass = ST_PASS_HASHCAT_PLAIN;
break;
case 2500: hashconfig->hash_type = HASH_TYPE_WPA_EAPOL;
hashconfig->salt_type = SALT_TYPE_EMBEDDED;
hashconfig->attack_exec = ATTACK_EXEC_OUTSIDE_KERNEL;
hashconfig->opts_type = OPTS_TYPE_PT_GENERATE_LE
| OPTS_TYPE_AUX1
| OPTS_TYPE_AUX2
| OPTS_TYPE_AUX3
| OPTS_TYPE_DEEP_COMP_KERNEL
| OPTS_TYPE_BINARY_HASHFILE;
hashconfig->kern_type = KERN_TYPE_WPA_EAPOL_PBKDF2;
hashconfig->dgst_size = DGST_SIZE_4_4;
hashconfig->parse_func = wpa_eapol_parse_hash;
hashconfig->opti_type = OPTI_TYPE_ZERO_BYTE
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
hashconfig->dgst_pos0 = 0;
hashconfig->dgst_pos1 = 1;
hashconfig->dgst_pos2 = 2;
hashconfig->dgst_pos3 = 3;
hashconfig->st_hash = ST_HASH_02500;
hashconfig->st_pass = ST_PASS_HASHCAT_EXCL;
break;
case 2501: hashconfig->hash_type = HASH_TYPE_WPA_EAPOL;
hashconfig->salt_type = SALT_TYPE_EMBEDDED;
hashconfig->attack_exec = ATTACK_EXEC_OUTSIDE_KERNEL;
@ -26204,7 +25882,6 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx)
switch (hashconfig->hash_mode)
{
case 2500: hashconfig->esalt_size = sizeof (wpa_eapol_t); break;
case 2501: hashconfig->esalt_size = sizeof (wpa_eapol_t); break;
case 5300: hashconfig->esalt_size = sizeof (ikepsk_t); break;
case 5400: hashconfig->esalt_size = sizeof (ikepsk_t); break;
@ -26315,7 +25992,6 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx)
{
case 1800: hashconfig->tmp_size = sizeof (sha512crypt_tmp_t); break;
case 2100: hashconfig->tmp_size = sizeof (dcc2_tmp_t); break;
case 2500: hashconfig->tmp_size = sizeof (wpa_pbkdf2_tmp_t); break;
case 2501: hashconfig->tmp_size = sizeof (wpa_pmk_tmp_t); break;
case 3200: hashconfig->tmp_size = sizeof (bcrypt_tmp_t); break;
case 5200: hashconfig->tmp_size = sizeof (pwsafe3_tmp_t); break;
@ -26427,7 +26103,6 @@ u32 default_pw_min (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED co
switch (hashconfig->hash_mode)
{
case 2500: pw_min = 8; break; // WPA-EAPOL-PBKDF2: min RFC
case 2501: pw_min = 64; break; // WPA-EAPOL-PMK: fixed
case 9710: pw_min = 5; break; // RC4-40 fixed
case 9810: pw_min = 5; break; // RC4-40 fixed
@ -26497,7 +26172,6 @@ u32 default_pw_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED co
{
case 112: pw_max = 30; break; // https://www.toadworld.com/platforms/oracle/b/weblog/archive/2013/11/12/oracle-12c-passwords
case 2100: pw_max = PW_MAX; break;
case 2500: pw_max = 63; break; // WPA-EAPOL-PBKDF2: limits itself to 63 by RFC
case 2501: pw_max = 64; break; // WPA-EAPOL-PMK: fixed length
case 3000: pw_max = 7; break; // LM max
case 3100: pw_max = 30; break; // http://www.red-database-security.de/whitepaper/oracle_passwords.html
@ -26661,11 +26335,8 @@ u32 default_salt_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED
const char *default_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)
{
switch (hashconfig->hash_mode)
{
case 2500: mask = "?a?a?a?a?a?a?a?a";
break;
case 2501: mask = "?a?a?a?a?a?a?a?axxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
break;
case 9710: mask = "?b?b?b?b?b";
@ -26951,94 +26622,6 @@ int module_hash_decode_outfile (MAYBE_UNUSED const hashconfig_t *hashconfig, MAY
{
if ((hash_mode == 2500) || (hash_mode == 2501)) // special case WPA/WPA2
{
// fake the parsing of the salt
u32 identifier_len = 32 + 1 + 12 + 1 + 12 + 1; // format is [ID_MD5]:[MAC1]:[MAC2]:$salt:$pass
if (line_len < identifier_len) continue;
hash_buf.salt->salt_len = line_len - identifier_len;
memcpy (hash_buf.salt->salt_buf, line_buf + identifier_len, hash_buf.salt->salt_len);
// fake the parsing of the digest
if (is_valid_hex_string ((u8 *) line_buf, 32) == false) break;
u32 *digest = (u32 *) hash_buf.digest;
digest[0] = hex_to_u32 ((u8 *) line_buf + 0);
digest[1] = hex_to_u32 ((u8 *) line_buf + 8);
digest[2] = hex_to_u32 ((u8 *) line_buf + 16);
digest[3] = hex_to_u32 ((u8 *) line_buf + 24);
digest[0] = byte_swap_32 (digest[0]);
digest[1] = byte_swap_32 (digest[1]);
digest[2] = byte_swap_32 (digest[2]);
digest[3] = byte_swap_32 (digest[3]);
return PARSER_OK;
/* this is from old potfile.c, seems to be more detailed
// here we have in line_hash_buf: hash:macap:macsta:essid:password
char *sep_pos = strrchr (line_hash_buf, ':');
if (sep_pos == NULL) continue;
sep_pos[0] = 0;
char *hash_pos = line_hash_buf;
const size_t hash_len = strlen (hash_pos);
if (hash_len != 32 + 1 + 12 + 1 + 12) continue;
char *essid_pos = sep_pos + 1;
size_t essid_len = strlen (essid_pos);
if (is_hexify ((const u8 *) essid_pos, essid_len) == true)
{
essid_len = exec_unhexify ((const u8 *) essid_pos, essid_len, (u8 *) essid_pos, essid_len);
}
if (essid_len > 32) continue;
if (hashconfig->is_salted == true)
{
// this should be always true, but we need it to make scan-build happy
memcpy (hash_buf.salt->salt_buf, essid_pos, essid_len);
hash_buf.salt->salt_len = (u32) essid_len;
hash_buf.salt->salt_iter = ROUNDS_WPA_PBKDF2 - 1;
u32 hash[4];
hash[0] = hex_to_u32 ((const u8 *) &hash_pos[ 0]);
hash[1] = hex_to_u32 ((const u8 *) &hash_pos[ 8]);
hash[2] = hex_to_u32 ((const u8 *) &hash_pos[16]);
hash[3] = hex_to_u32 ((const u8 *) &hash_pos[24]);
hash[0] = byte_swap_32 (hash[0]);
hash[1] = byte_swap_32 (hash[1]);
hash[2] = byte_swap_32 (hash[2]);
hash[3] = byte_swap_32 (hash[3]);
u32 *digest = (u32 *) hash_buf.digest;
digest[0] = hash[0];
digest[1] = hash[1];
digest[2] = hash[2];
digest[3] = hash[3];
}
*/
}
else if (hash_mode == 6800) // special case LastPass (only email address in outfile/potfile)
{
// fake the parsing of the hash/salt
@ -27470,27 +27053,6 @@ bool module_unstable_warning (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE
u32 module_deep_comp_kernel (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
const u32 digests_offset = hashes->salts_buf[salt_pos].digests_offset;
wpa_eapol_t *wpa_eapols = (wpa_eapol_t *) hashes->esalts_buf;
wpa_eapol_t *wpa_eapol = &wpa_eapols[digests_offset + digest_pos];
if (wpa_eapol->keyver == 1)
{
return KERN_RUN_AUX1;
}
else if (wpa_eapol->keyver == 2)
{
return KERN_RUN_AUX2;
}
else if (wpa_eapol->keyver == 3)
{
return KERN_RUN_AUX3;
}
}
else if (hashconfig->hash_mode == 9600)
{
return KERN_RUN_3;
@ -27505,29 +27067,6 @@ int module_hash_encode_status (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYB
{
if (hashes->digests_cnt == 1)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
char *tmp_buf;
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) hashes->esalts_buf;
hc_asprintf (&tmp_buf, "%s (AP:%02x:%02x:%02x:%02x:%02x:%02x STA:%02x:%02x:%02x:%02x:%02x:%02x)",
(char *) hashes->salts_buf[0].salt_buf,
wpa_eapol->orig_mac_ap[0],
wpa_eapol->orig_mac_ap[1],
wpa_eapol->orig_mac_ap[2],
wpa_eapol->orig_mac_ap[3],
wpa_eapol->orig_mac_ap[4],
wpa_eapol->orig_mac_ap[5],
wpa_eapol->orig_mac_sta[0],
wpa_eapol->orig_mac_sta[1],
wpa_eapol->orig_mac_sta[2],
wpa_eapol->orig_mac_sta[3],
wpa_eapol->orig_mac_sta[4],
wpa_eapol->orig_mac_sta[5]);
return tmp_buf;
}
else if (hashconfig->hash_mode == 5200)
{
return hashes->hashfile;
@ -27565,267 +27104,19 @@ int module_hash_encode_status (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYB
}
int module_hash_init_selftest (MAYBE_UNUSED const hashconfig_t *hashconfig, hash_t *hash)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
char *tmpdata = (char *) hcmalloc (sizeof (hccapx_t));
const size_t st_hash_len = strlen (hashconfig->st_hash);
for (size_t i = 0, j = 0; j < st_hash_len; i += 1, j += 2)
{
const u8 c = hex_to_u8 ((const u8 *) hashconfig->st_hash + j);
tmpdata[i] = c;
}
parser_status = module_ctx->module_hash_decode (hashconfig, hash.digest, hash.salt, hash.esalt, tmpdata, sizeof (hccapx_t));
hcfree (tmpdata);
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) st_esalts_buf;
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 0;
wpa_eapol->nonce_error_corrections = 3;
}
}
int module_hash_binary_save (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos, const char **buf)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
hccapx_t hccapx;
to_hccapx_t (hashcat_ctx, &hccapx, salt_pos, digest_pos);
hc_fwrite (&hccapx, sizeof (hccapx_t), 1, fp);
}
}
int module_hash_binary_count (MAYBE_UNUSED const hashes_t *hashes)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
struct stat st;
if (stat (hashes->hashfile, &st) == -1) return -1;
return st.st_size / sizeof (hccapx_t);
}
else if (hashconfig->hash_mode == 14600)
{
return LUKS_NUMKEYS;
}
}
void to_hccapx_t (hashcat_ctx_t *hashcat_ctx, hccapx_t *hccapx, const u32 salt_pos, const u32 digest_pos)
{
const hashes_t *hashes = hashcat_ctx->hashes;
const salt_t *salts_buf = hashes->salts_buf;
const void *esalts_buf = hashes->esalts_buf;
memset (hccapx, 0, sizeof (hccapx_t));
hccapx->signature = HCCAPX_SIGNATURE;
hccapx->version = HCCAPX_VERSION;
const salt_t *salt = &salts_buf[salt_pos];
const u32 digest_cur = salt->digests_offset + digest_pos;
hccapx->essid_len = salt->salt_len;
memcpy (hccapx->essid, salt->salt_buf, hccapx->essid_len);
wpa_eapol_t *wpa_eapols = (wpa_eapol_t *) esalts_buf;
wpa_eapol_t *wpa_eapol = &wpa_eapols[digest_cur];
hccapx->message_pair = wpa_eapol->message_pair;
hccapx->keyver = wpa_eapol->keyver;
hccapx->eapol_len = wpa_eapol->eapol_len;
if (wpa_eapol->keyver != 1)
{
u32 eapol_tmp[64] = { 0 };
for (u32 i = 0; i < 64; i++)
{
eapol_tmp[i] = byte_swap_32 (wpa_eapol->eapol[i]);
}
memcpy (hccapx->eapol, eapol_tmp, wpa_eapol->eapol_len);
}
else
{
memcpy (hccapx->eapol, wpa_eapol->eapol, wpa_eapol->eapol_len);
}
memcpy (hccapx->mac_ap, wpa_eapol->orig_mac_ap, 6);
memcpy (hccapx->mac_sta, wpa_eapol->orig_mac_sta, 6);
memcpy (hccapx->nonce_ap, wpa_eapol->orig_nonce_ap, 32);
memcpy (hccapx->nonce_sta, wpa_eapol->orig_nonce_sta, 32);
if (wpa_eapol->keyver != 1)
{
u32 digest_tmp[4];
digest_tmp[0] = byte_swap_32 (wpa_eapol->keymic[0]);
digest_tmp[1] = byte_swap_32 (wpa_eapol->keymic[1]);
digest_tmp[2] = byte_swap_32 (wpa_eapol->keymic[2]);
digest_tmp[3] = byte_swap_32 (wpa_eapol->keymic[3]);
memcpy (hccapx->keymic, digest_tmp, 16);
}
else
{
memcpy (hccapx->keymic, wpa_eapol->keymic, 16);
}
}
int check_old_hccap (const char *hashfile)
{
FILE *fp = fopen (hashfile, "rb");
if (fp == NULL) return -1;
u32 signature;
const size_t nread = hc_fread (&signature, sizeof (u32), 1, fp);
fclose (fp);
if (nread != 1) return -1;
if (signature == HCCAPX_SIGNATURE) return 0;
return 1;
}
int module_hash_binary_parse ()
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
hashes->hashlist_mode = HL_MODE_FILE;
FILE *fp = fopen (hash_buf, "rb");
if (fp == NULL)
{
event_log_error (hashcat_ctx, "%s: %s", hash_buf, strerror (errno));
return -1;
}
char *in = (char *) hcmalloc (sizeof (hccapx_t));
while (!feof (fp))
{
const size_t nread = hc_fread (in, sizeof (hccapx_t), 1, fp);
if (nread == 0) break;
if (hashconfig->is_salted == true)
{
memset (hashes_buf[hashes_cnt].salt, 0, sizeof (salt_t));
}
if (hashconfig->esalt_size > 0)
{
memset (hashes_buf[hashes_cnt].esalt, 0, hashconfig->esalt_size);
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) hashes_buf[hashes_cnt].esalt;
if (user_options->hccapx_message_pair_chgd == true)
{
wpa_eapol->message_pair_chgd = (int) user_options->hccapx_message_pair_chgd;
wpa_eapol->message_pair = (u8) user_options->hccapx_message_pair;
}
if (wpa_eapol->message_pair & (1 << 4))
{
// ap-less attack detected, nc not needed
wpa_eapol->nonce_error_corrections = 0;
}
else
{
if (wpa_eapol->message_pair & (1 << 7))
{
// replaycount not checked, nc needed
wpa_eapol->nonce_error_corrections = user_options->nonce_error_corrections;
}
else
{
// replaycount checked, nc not needed, but we allow user overwrites
if (user_options->nonce_error_corrections_chgd == true)
{
wpa_eapol->nonce_error_corrections = user_options->nonce_error_corrections;
}
else
{
wpa_eapol->nonce_error_corrections = 0;
}
}
}
// now some optimization related to replay counter endianess
// hcxtools has techniques to detect them
// since we can not guarantee to get our handshakes from hcxtools we enable both by default
// this means that we check both even if both are not set!
// however if one of them is set, we can assume that the endianess has been checked and the other one is not needed
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 1;
if (wpa_eapol->message_pair & (1 << 5))
{
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 0;
}
else if (wpa_eapol->message_pair & (1 << 6))
{
wpa_eapol->detected_le = 0;
wpa_eapol->detected_be = 1;
}
}
}
if (hashconfig->hook_salt_size > 0)
{
memset (hashes_buf[hashes_cnt].hook_salt, 0, hashconfig->hook_salt_size);
}
hash_t *hash = &hashes_buf[hashes_cnt];
parser_status = module_ctx->module_hash_decode (hashconfig, hash->digest, hash->salt, hash->esalt, in, sizeof (hccapx_t));
if (parser_status != PARSER_OK) continue;
hashes_cnt++;
}
hcfree (in);
fclose (fp);
}
else if (hashconfig->hash_mode == 14600)
{
hashes->hashlist_mode = HL_MODE_FILE;
@ -27848,26 +27139,7 @@ int module_hash_binary_parse ()
bool module_hash_binary_verify (MAYBE_UNUSED const hashes_t *hashes)
{
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
{
struct stat st;
if (stat (hashes->hashfile, &st) == -1) return false;
// 392 = old hccap_t size
if ((st.st_size % 392) == 0)
{
const int rc = check_old_hccap (hashes->hashfile);
if (rc == 1) return false;
//{
// event_log_error (hashcat_ctx, "%s: Old hccap format detected! You need to update: https://hashcat.net/q/hccapx", hashes->hashfile);
//
// return -1;
//}
}
else if (hashconfig->hash_mode == 14600)
{

@ -0,0 +1,850 @@
/**
* 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"
#include "cpu_md5.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;
static const u32 HASH_CATEGORY = HASH_CATEGORY_NETWORK_PROTOCOL;
static const char *HASH_NAME = "WPA-EAPOL-PBKDF2";
static const u32 HASH_TYPE = HASH_TYPE_GENERIC;
static const u64 KERN_TYPE = 2500;
static const u32 OPTI_TYPE = OPTI_TYPE_ZERO_BYTE
| OPTI_TYPE_SLOW_HASH_SIMD_LOOP;
static const u64 OPTS_TYPE = OPTS_TYPE_PT_GENERATE_LE
| OPTS_TYPE_AUX1
| OPTS_TYPE_AUX2
| OPTS_TYPE_AUX3
| OPTS_TYPE_DEEP_COMP_KERNEL
| OPTS_TYPE_BINARY_HASHFILE;
static const u32 SALT_TYPE = SALT_TYPE_EMBEDDED;
static const char *ST_PASS = "hashcat!";
static const char *ST_HASH = "4843505804000000000235380000000000000000000000000000000000000000000000000000000000000151aecc428f182acefbd1a9e62d369a079265784da83ba4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b823a1cd402aed449cced04f552c5b5acfebf06ae96a09c96d9a01c443a17aa62258c4f651a68aa67b0001030077fe010900200000000000000001a4cf88375c44c830e6e5aa5d6faf352aa496a9ee129fb8292f7435df5420b8230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018dd160050f20101000050f20201000050f20201000050f20200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
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; }
u32 module_hash_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 HASH_TYPE; }
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; }
static const u32 ROUNDS_WPA_PBKDF2 = 4096;
typedef struct wpa_eapol
{
u32 pke[32];
u32 eapol[64 + 16];
u16 eapol_len;
u8 message_pair;
int message_pair_chgd;
u8 keyver;
u8 orig_mac_ap[6];
u8 orig_mac_sta[6];
u8 orig_nonce_ap[32];
u8 orig_nonce_sta[32];
u8 essid_len;
u8 essid[32];
u32 keymic[4];
u32 hash[4];
int nonce_compare;
int nonce_error_corrections;
int detected_le;
int detected_be;
} wpa_eapol_t;
typedef struct wpa_pbkdf2_tmp
{
u32 ipad[5];
u32 opad[5];
u32 dgst[10];
u32 out[10];
} wpa_pbkdf2_tmp_t;
#define HCCAPX_VERSION 4
#define HCCAPX_SIGNATURE 0x58504348 // HCPX
// this is required to force mingw to accept the packed attribute
#pragma pack(push,1)
struct hccapx
{
u32 signature;
u32 version;
u8 message_pair;
u8 essid_len;
u8 essid[32];
u8 keyver;
u8 keymic[16];
u8 mac_ap[6];
u8 nonce_ap[32];
u8 mac_sta[6];
u8 nonce_sta[32];
u16 eapol_len;
u8 eapol[256];
} __attribute__((packed));
typedef struct hccapx hccapx_t;
#pragma pack(pop)
static void to_hccapx_t (const hashes_t *hashes, hccapx_t *hccapx, const u32 salt_pos, const u32 digest_pos)
{
const salt_t *salts_buf = hashes->salts_buf;
const void *esalts_buf = hashes->esalts_buf;
memset (hccapx, 0, sizeof (hccapx_t));
hccapx->signature = HCCAPX_SIGNATURE;
hccapx->version = HCCAPX_VERSION;
const salt_t *salt = &salts_buf[salt_pos];
const u32 digest_cur = salt->digests_offset + digest_pos;
hccapx->essid_len = salt->salt_len;
memcpy (hccapx->essid, salt->salt_buf, hccapx->essid_len);
wpa_eapol_t *wpa_eapols = (wpa_eapol_t *) esalts_buf;
wpa_eapol_t *wpa_eapol = &wpa_eapols[digest_cur];
hccapx->message_pair = wpa_eapol->message_pair;
hccapx->keyver = wpa_eapol->keyver;
hccapx->eapol_len = wpa_eapol->eapol_len;
if (wpa_eapol->keyver != 1)
{
u32 eapol_tmp[64] = { 0 };
for (u32 i = 0; i < 64; i++)
{
eapol_tmp[i] = byte_swap_32 (wpa_eapol->eapol[i]);
}
memcpy (hccapx->eapol, eapol_tmp, wpa_eapol->eapol_len);
}
else
{
memcpy (hccapx->eapol, wpa_eapol->eapol, wpa_eapol->eapol_len);
}
memcpy (hccapx->mac_ap, wpa_eapol->orig_mac_ap, 6);
memcpy (hccapx->mac_sta, wpa_eapol->orig_mac_sta, 6);
memcpy (hccapx->nonce_ap, wpa_eapol->orig_nonce_ap, 32);
memcpy (hccapx->nonce_sta, wpa_eapol->orig_nonce_sta, 32);
if (wpa_eapol->keyver != 1)
{
u32 digest_tmp[4];
digest_tmp[0] = byte_swap_32 (wpa_eapol->keymic[0]);
digest_tmp[1] = byte_swap_32 (wpa_eapol->keymic[1]);
digest_tmp[2] = byte_swap_32 (wpa_eapol->keymic[2]);
digest_tmp[3] = byte_swap_32 (wpa_eapol->keymic[3]);
memcpy (hccapx->keymic, digest_tmp, 16);
}
else
{
memcpy (hccapx->keymic, wpa_eapol->keymic, 16);
}
}
static int check_old_hccap (const char *hashfile)
{
FILE *fp = fopen (hashfile, "rb");
if (fp == NULL) return -1;
u32 signature;
const size_t nread = hc_fread (&signature, sizeof (u32), 1, fp);
fclose (fp);
if (nread != 1) return -1;
if (signature == HCCAPX_SIGNATURE) return 0;
return 1;
}
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 = "?a?a?a?a?a?a?a?a";
return mask;
}
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 u64 tmp_size = (const u64) sizeof (wpa_pbkdf2_tmp_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)
{
const u64 esalt_size = (const u64) sizeof (wpa_eapol_t);
return esalt_size;
}
u32 module_pw_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 pw_min = 8;
return pw_min;
}
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 u32 pw_max = 63;
return pw_max;
}
int module_hash_decode_outfile (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf, MAYBE_UNUSED hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
{
u32 *digest = (u32 *) digest_buf;
// here we have in line_hash_buf: hash:macap:macsta:essid:password
char *sep_pos = strrchr (line_buf, ':');
if (sep_pos == NULL) return (PARSER_HASH_ENCODING);
if ((line_buf + 32 + 1 + 12 + 1 + 12) != sep_pos) return (PARSER_HASH_LENGTH);
char *essid_pos = sep_pos + 1;
const int essid_len = strlen (essid_pos);
u8 tmp_buf[128] = { 0 };
int tmp_len = essid_len;
memcpy (tmp_buf, essid_pos, essid_len);
if (is_hexify (tmp_buf, tmp_len) == true)
{
tmp_len = exec_unhexify (tmp_buf, tmp_len, tmp_buf, sizeof (tmp_buf));
}
if (tmp_len > 32) return (PARSER_HASH_VALUE);
memcpy (salt->salt_buf, tmp_buf, tmp_len);
salt->salt_len = tmp_len;
salt->salt_iter = ROUNDS_WPA_PBKDF2 - 1;
digest[0] = hex_to_u32 ((const u8 *) &line_buf[ 0]);
digest[1] = hex_to_u32 ((const u8 *) &line_buf[ 8]);
digest[2] = hex_to_u32 ((const u8 *) &line_buf[16]);
digest[3] = hex_to_u32 ((const u8 *) &line_buf[24]);
digest[0] = byte_swap_32 (digest[0]);
digest[1] = byte_swap_32 (digest[1]);
digest[2] = byte_swap_32 (digest[2]);
digest[3] = byte_swap_32 (digest[3]);
return PARSER_OK;
}
int module_hash_encode_status (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 hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
{
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) esalt_buf;
const int line_len = snprintf (line_buf, line_size, "%s (AP:%02x:%02x:%02x:%02x:%02x:%02x STA:%02x:%02x:%02x:%02x:%02x:%02x)",
(char *) salt->salt_buf,
wpa_eapol->orig_mac_ap[0],
wpa_eapol->orig_mac_ap[1],
wpa_eapol->orig_mac_ap[2],
wpa_eapol->orig_mac_ap[3],
wpa_eapol->orig_mac_ap[4],
wpa_eapol->orig_mac_ap[5],
wpa_eapol->orig_mac_sta[0],
wpa_eapol->orig_mac_sta[1],
wpa_eapol->orig_mac_sta[2],
wpa_eapol->orig_mac_sta[3],
wpa_eapol->orig_mac_sta[4],
wpa_eapol->orig_mac_sta[5]);
return line_len;
}
int module_hash_init_selftest (MAYBE_UNUSED const hashconfig_t *hashconfig, hash_t *hash)
{
char *tmpdata = (char *) hcmalloc (sizeof (hccapx_t));
const size_t st_hash_len = strlen (hashconfig->st_hash);
for (size_t i = 0, j = 0; j < st_hash_len; i += 1, j += 2)
{
const u8 c = hex_to_u8 ((const u8 *) hashconfig->st_hash + j);
tmpdata[i] = c;
}
int parser_status = module_hash_decode (hashconfig, hash->digest, hash->salt, hash->esalt, hash->hash_info, tmpdata, sizeof (hccapx_t));
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) hash->esalt;
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 0;
wpa_eapol->nonce_error_corrections = 3;
hcfree (tmpdata);
return parser_status;
}
int module_hash_binary_save (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos, char **buf)
{
hccapx_t *hccapx = hcmalloc (sizeof (hccapx_t));
to_hccapx_t (hashes, hccapx, salt_pos, digest_pos);
*buf = (char *) hccapx;
return sizeof (hccapx_t);
}
int module_hash_binary_parse (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, hashes_t *hashes)
{
// hashes->hashlist_mode = HL_MODE_FILE; ???
hash_t *hashes_buf = hashes->hashes_buf;
int hashes_cnt = 0;
FILE *fp = fopen (hashes->hashfile, "rb");
if (fp == NULL) return -1;
char *in = (char *) hcmalloc (sizeof (hccapx_t));
while (!feof (fp))
{
const size_t nread = hc_fread (in, sizeof (hccapx_t), 1, fp);
if (nread == 0) break;
memset (hashes_buf[hashes_cnt].salt, 0, sizeof (salt_t));
memset (hashes_buf[hashes_cnt].esalt, 0, sizeof (wpa_eapol_t));
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) hashes_buf[hashes_cnt].esalt;
if (user_options->hccapx_message_pair_chgd == true)
{
wpa_eapol->message_pair_chgd = (int) user_options->hccapx_message_pair_chgd;
wpa_eapol->message_pair = (u8) user_options->hccapx_message_pair;
}
if (wpa_eapol->message_pair & (1 << 4))
{
// ap-less attack detected, nc not needed
wpa_eapol->nonce_error_corrections = 0;
}
else
{
if (wpa_eapol->message_pair & (1 << 7))
{
// replaycount not checked, nc needed
wpa_eapol->nonce_error_corrections = user_options->nonce_error_corrections;
}
else
{
// replaycount checked, nc not needed, but we allow user overwrites
if (user_options->nonce_error_corrections_chgd == true)
{
wpa_eapol->nonce_error_corrections = user_options->nonce_error_corrections;
}
else
{
wpa_eapol->nonce_error_corrections = 0;
}
}
}
// now some optimization related to replay counter endianess
// hcxtools has techniques to detect them
// since we can not guarantee to get our handshakes from hcxtools we enable both by default
// this means that we check both even if both are not set!
// however if one of them is set, we can assume that the endianess has been checked and the other one is not needed
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 1;
if (wpa_eapol->message_pair & (1 << 5))
{
wpa_eapol->detected_le = 1;
wpa_eapol->detected_be = 0;
}
else if (wpa_eapol->message_pair & (1 << 6))
{
wpa_eapol->detected_le = 0;
wpa_eapol->detected_be = 1;
}
hash_t *hash = &hashes_buf[hashes_cnt];
const int parser_status = module_hash_decode (hashconfig, hash->digest, hash->salt, hash->esalt, hash->hash_info, in, sizeof (hccapx_t));
if (parser_status != PARSER_OK) continue;
hashes_cnt++;
}
hcfree (in);
fclose (fp);
return hashes_cnt;
}
int module_hash_binary_count (MAYBE_UNUSED const hashes_t *hashes)
{
struct stat st;
if (stat (hashes->hashfile, &st) == -1) return -1;
return st.st_size / sizeof (hccapx_t);
}
u32 module_deep_comp_kernel (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos)
{
const u32 digests_offset = hashes->salts_buf[salt_pos].digests_offset;
wpa_eapol_t *wpa_eapols = (wpa_eapol_t *) hashes->esalts_buf;
wpa_eapol_t *wpa_eapol = &wpa_eapols[digests_offset + digest_pos];
if (wpa_eapol->keyver == 1)
{
return KERN_RUN_AUX1;
}
else if (wpa_eapol->keyver == 2)
{
return KERN_RUN_AUX2;
}
else if (wpa_eapol->keyver == 3)
{
return KERN_RUN_AUX3;
}
return 0;
}
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 hashinfo_t *hash_info, const char *line_buf, MAYBE_UNUSED const int line_len)
{
u32 *digest = (u32 *) digest_buf;
wpa_eapol_t *wpa_eapol = (wpa_eapol_t *) esalt_buf;
// the *wpa was partially initialized beforehand, we can not simply memset it to zero
hccapx_t in;
memcpy (&in, line_buf, sizeof (hccapx_t));
if (in.signature != HCCAPX_SIGNATURE) return (PARSER_HCCAPX_SIGNATURE);
if (in.version != HCCAPX_VERSION) return (PARSER_HCCAPX_VERSION);
if (in.eapol_len < 1 || in.eapol_len > 255) return (PARSER_HCCAPX_EAPOL_LEN);
memcpy (wpa_eapol->keymic, in.keymic, 16);
/*
http://www.one-net.eu/jsw/j_sec/m_ptype.html
The phrase "Pairwise key expansion"
Access Point Address (referred to as Authenticator Address AA)
Supplicant Address (referred to as Supplicant Address SA)
Access Point Nonce (referred to as Authenticator Anonce)
Wireless Device Nonce (referred to as Supplicant Nonce Snonce)
*/
u32 salt_len = in.essid_len;
if (salt_len > 32) return (PARSER_SALT_LENGTH);
memcpy (salt->salt_buf, in.essid, in.essid_len);
salt->salt_len = salt_len;
salt->salt_iter = ROUNDS_WPA_PBKDF2 - 1;
memcpy (wpa_eapol->essid, in.essid, in.essid_len);
wpa_eapol->essid_len = in.essid_len;
wpa_eapol->keyver = in.keyver;
if ((wpa_eapol->keyver != 1) && (wpa_eapol->keyver != 2) && (wpa_eapol->keyver != 3)) return (PARSER_SALT_VALUE);
u8 *pke_ptr = (u8 *) wpa_eapol->pke;
memset (pke_ptr, 0, 128);
if ((wpa_eapol->keyver == 1) || (wpa_eapol->keyver == 2))
{
memcpy (pke_ptr, "Pairwise key expansion", 23);
if (memcmp (in.mac_ap, in.mac_sta, 6) < 0)
{
memcpy (pke_ptr + 23, in.mac_ap, 6);
memcpy (pke_ptr + 29, in.mac_sta, 6);
}
else
{
memcpy (pke_ptr + 23, in.mac_sta, 6);
memcpy (pke_ptr + 29, in.mac_ap, 6);
}
wpa_eapol->nonce_compare = memcmp (in.nonce_ap, in.nonce_sta, 32);
if (wpa_eapol->nonce_compare < 0)
{
memcpy (pke_ptr + 35, in.nonce_ap, 32);
memcpy (pke_ptr + 67, in.nonce_sta, 32);
}
else
{
memcpy (pke_ptr + 35, in.nonce_sta, 32);
memcpy (pke_ptr + 67, in.nonce_ap, 32);
}
}
else if (wpa_eapol->keyver == 3)
{
pke_ptr[0] = 1;
pke_ptr[1] = 0;
memcpy (pke_ptr + 2, "Pairwise key expansion", 22);
if (memcmp (in.mac_ap, in.mac_sta, 6) < 0)
{
memcpy (pke_ptr + 24, in.mac_ap, 6);
memcpy (pke_ptr + 30, in.mac_sta, 6);
}
else
{
memcpy (pke_ptr + 24, in.mac_sta, 6);
memcpy (pke_ptr + 30, in.mac_ap, 6);
}
wpa_eapol->nonce_compare = memcmp (in.nonce_ap, in.nonce_sta, 32);
if (wpa_eapol->nonce_compare < 0)
{
memcpy (pke_ptr + 36, in.nonce_ap, 32);
memcpy (pke_ptr + 68, in.nonce_sta, 32);
}
else
{
memcpy (pke_ptr + 36, in.nonce_sta, 32);
memcpy (pke_ptr + 68, in.nonce_ap, 32);
}
pke_ptr[100] = 0x80;
pke_ptr[101] = 1;
}
for (int i = 0; i < 32; i++)
{
wpa_eapol->pke[i] = byte_swap_32 (wpa_eapol->pke[i]);
}
memcpy (wpa_eapol->orig_mac_ap, in.mac_ap, 6);
memcpy (wpa_eapol->orig_mac_sta, in.mac_sta, 6);
memcpy (wpa_eapol->orig_nonce_ap, in.nonce_ap, 32);
memcpy (wpa_eapol->orig_nonce_sta, in.nonce_sta, 32);
u8 message_pair_orig = in.message_pair;
in.message_pair &= 0x7f; // ignore the highest bit (it is used to indicate if the replay counters did match)
if (wpa_eapol->message_pair_chgd == true)
{
if (wpa_eapol->message_pair != in.message_pair) return (PARSER_HCCAPX_MESSAGE_PAIR);
}
wpa_eapol->message_pair = message_pair_orig;
wpa_eapol->eapol_len = in.eapol_len;
u8 *eapol_ptr = (u8 *) wpa_eapol->eapol;
memcpy (eapol_ptr, in.eapol, wpa_eapol->eapol_len);
memset (eapol_ptr + wpa_eapol->eapol_len, 0, (256 + 64) - wpa_eapol->eapol_len);
eapol_ptr[wpa_eapol->eapol_len] = 0x80;
if (wpa_eapol->keyver == 1)
{
// nothing to do
}
else if (wpa_eapol->keyver == 2)
{
wpa_eapol->keymic[0] = byte_swap_32 (wpa_eapol->keymic[0]);
wpa_eapol->keymic[1] = byte_swap_32 (wpa_eapol->keymic[1]);
wpa_eapol->keymic[2] = byte_swap_32 (wpa_eapol->keymic[2]);
wpa_eapol->keymic[3] = byte_swap_32 (wpa_eapol->keymic[3]);
for (int i = 0; i < 64; i++)
{
wpa_eapol->eapol[i] = byte_swap_32 (wpa_eapol->eapol[i]);
}
}
else if (wpa_eapol->keyver == 3)
{
// nothing to do
}
// Create a hash of the nonce as ESSID is not unique enough
// Not a regular MD5 but good enough
// We can also ignore cases where we should bzero the work buffer
u32 hash[4];
hash[0] = 0;
hash[1] = 1;
hash[2] = 2;
hash[3] = 3;
u32 block[16];
memset (block, 0, sizeof (block));
u8 *block_ptr = (u8 *) block;
for (int i = 0; i < 16; i++) block[i] = salt->salt_buf[i];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->pke[i + 0];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->pke[i + 16];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 0];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 16];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 32];
md5_64 (block, hash);
for (int i = 0; i < 16; i++) block[i] = wpa_eapol->eapol[i + 48];
md5_64 (block, hash);
for (int i = 0; i < 6; i++) block_ptr[i + 0] = wpa_eapol->orig_mac_ap[i];
for (int i = 0; i < 6; i++) block_ptr[i + 6] = wpa_eapol->orig_mac_sta[i];
md5_64 (block, hash);
for (int i = 0; i < 32; i++) block_ptr[i + 0] = wpa_eapol->orig_nonce_ap[i];
for (int i = 0; i < 32; i++) block_ptr[i + 32] = wpa_eapol->orig_nonce_sta[i];
md5_64 (block, hash);
block[0] = wpa_eapol->keymic[0];
block[1] = wpa_eapol->keymic[1];
block[2] = wpa_eapol->keymic[2];
block[3] = wpa_eapol->keymic[3];
md5_64 (block, hash);
wpa_eapol->hash[0] = hash[0];
wpa_eapol->hash[1] = hash[1];
wpa_eapol->hash[2] = hash[2];
wpa_eapol->hash[3] = hash[3];
// make all this stuff unique
digest[0] = wpa_eapol->hash[0];
digest[1] = wpa_eapol->hash[1];
digest[2] = wpa_eapol->hash[2];
digest[3] = wpa_eapol->hash[3];
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 hashinfo_t *hash_info, char *line_buf, MAYBE_UNUSED const int line_size)
{
const wpa_eapol_t *wpa_eapol = (const wpa_eapol_t *) esalt_buf;
int line_len = 0;
if (need_hexify (wpa_eapol->essid, wpa_eapol->essid_len, hashconfig->separator, 0) == true)
{
char tmp_buf[128];
int tmp_len = 0;
tmp_buf[tmp_len++] = '$';
tmp_buf[tmp_len++] = 'H';
tmp_buf[tmp_len++] = 'E';
tmp_buf[tmp_len++] = 'X';
tmp_buf[tmp_len++] = '[';
exec_hexify (wpa_eapol->essid, wpa_eapol->essid_len, (u8 *) tmp_buf + tmp_len);
tmp_len += wpa_eapol->essid_len * 2;
tmp_buf[tmp_len++] = ']';
tmp_buf[tmp_len++] = 0;
line_len = snprintf (line_buf, line_size, "%08x%08x%08x%08x:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%s",
wpa_eapol->hash[0],
wpa_eapol->hash[1],
wpa_eapol->hash[2],
wpa_eapol->hash[3],
wpa_eapol->orig_mac_ap[0],
wpa_eapol->orig_mac_ap[1],
wpa_eapol->orig_mac_ap[2],
wpa_eapol->orig_mac_ap[3],
wpa_eapol->orig_mac_ap[4],
wpa_eapol->orig_mac_ap[5],
wpa_eapol->orig_mac_sta[0],
wpa_eapol->orig_mac_sta[1],
wpa_eapol->orig_mac_sta[2],
wpa_eapol->orig_mac_sta[3],
wpa_eapol->orig_mac_sta[4],
wpa_eapol->orig_mac_sta[5],
tmp_buf);
}
else
{
line_len = snprintf (line_buf, line_size, "%08x%08x%08x%08x:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%s",
wpa_eapol->hash[0],
wpa_eapol->hash[1],
wpa_eapol->hash[2],
wpa_eapol->hash[3],
wpa_eapol->orig_mac_ap[0],
wpa_eapol->orig_mac_ap[1],
wpa_eapol->orig_mac_ap[2],
wpa_eapol->orig_mac_ap[3],
wpa_eapol->orig_mac_ap[4],
wpa_eapol->orig_mac_ap[5],
wpa_eapol->orig_mac_sta[0],
wpa_eapol->orig_mac_sta[1],
wpa_eapol->orig_mac_sta[2],
wpa_eapol->orig_mac_sta[3],
wpa_eapol->orig_mac_sta[4],
wpa_eapol->orig_mac_sta[5],
wpa_eapol->essid);
}
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_deep_comp_kernel;
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_forced_outfile_format = MODULE_DEFAULT;
module_ctx->module_hash_binary_count = module_hash_binary_count;
module_ctx->module_hash_binary_parse = module_hash_binary_parse;
module_ctx->module_hash_binary_save = module_hash_binary_save;
module_ctx->module_hash_binary_verify = MODULE_DEFAULT;
module_ctx->module_hash_decode_outfile = module_hash_decode_outfile;
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
module_ctx->module_hash_decode = module_hash_decode;
module_ctx->module_hash_encode_status = module_hash_encode_status;
module_ctx->module_hash_encode = module_hash_encode;
module_ctx->module_hash_init_selftest = module_hash_init_selftest;
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_hash_type = module_hash_type;
module_ctx->module_hlfmt_disable = 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_kernel_accel_max = MODULE_DEFAULT;
module_ctx->module_kernel_accel_min = MODULE_DEFAULT;
module_ctx->module_kernel_loops_max = MODULE_DEFAULT;
module_ctx->module_kernel_loops_min = MODULE_DEFAULT;
module_ctx->module_kernel_threads_max = MODULE_DEFAULT;
module_ctx->module_kernel_threads_min = MODULE_DEFAULT;
module_ctx->module_kern_type = module_kern_type;
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_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_pw_min;
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;
}

@ -302,25 +302,25 @@ const char *status_get_hash_target (const hashcat_ctx_t *hashcat_ctx)
const hashes_t *hashes = hashcat_ctx->hashes;
const module_ctx_t *module_ctx = hashcat_ctx->module_ctx;
if (module_ctx->module_hash_encode_status != MODULE_DEFAULT)
if (hashes->digests_cnt == 1)
{
char *tmp_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
if (module_ctx->module_hash_encode_status != MODULE_DEFAULT)
{
char *tmp_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
const int tmp_len = module_ctx->module_hash_encode_status (hashconfig, hashes->digests_buf, hashes->salts_buf, hashes->esalts_buf, hashes->hash_info[0], tmp_buf, HCBUFSIZ_LARGE);
const int tmp_len = module_ctx->module_hash_encode_status (hashconfig, hashes->digests_buf, hashes->salts_buf, hashes->esalts_buf, NULL, tmp_buf, HCBUFSIZ_LARGE);
char *tmp_buf2 = (char *) hcmalloc (tmp_len + 1);
char *tmp_buf2 = (char *) hcmalloc (tmp_len + 1);
memcpy (tmp_buf2, tmp_buf, tmp_len);
memcpy (tmp_buf2, tmp_buf, tmp_len);
free (tmp_buf);
tmp_buf2[tmp_len] = 0;
tmp_buf2[tmp_len] = 0;
free (tmp_buf);
return tmp_buf2;
}
else
{
if (hashes->digests_cnt == 1)
return tmp_buf2;
}
else
{
char *tmp_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
@ -336,10 +336,10 @@ const char *status_get_hash_target (const hashcat_ctx_t *hashcat_ctx)
return tmp_buf2;
}
else
{
return hashes->hashfile;
}
}
else
{
return hashes->hashfile;
}
}

@ -0,0 +1,500 @@
#!/usr/bin/env perl
##
## Author......: See docs/credits.txt
## License.....: MIT
##
use strict;
use warnings;
use Crypt::PBKDF2;
use Digest::CMAC;
use Digest::MD5 qw (md5);
use Digest::SHA qw (sha1 sha256);
use Digest::HMAC qw (hmac);
use MIME::Base64 qw (encode_base64);
sub module_constraints { [[8, 255], [0, 32], [8, 255], [0, 32], [-1, -1]] }
sub module_generate_hash
{
my $word = shift;
my $salt = shift;
my $bssid = random_bytes (6);
my $stmac = random_bytes (6);
my $snonce = random_bytes (32);
my $anonce = random_bytes (32);
my $keyver = random_number (1, 4); # 1, 2 or 3
# eapol:
# should be "validly" generated, but in theory could be anything for us also:
# $eapol = "\x00" x 121; # works too, but let's generate it correctly
my $eapol = gen_random_wpa_eapol ($keyver, $snonce);
my $eapol_len = length ($eapol);
# constants
my $iterations = 4096;
#
# START
#
# generate the Pairwise Master Key (PMK)
my $pbkdf2 = Crypt::PBKDF2->new
(
hash_class => 'HMACSHA1',
iterations => $iterations,
output_len => 32,
);
my $pmk = $pbkdf2->PBKDF2 ($salt, $word);
# Pairwise Transient Key (PTK) transformation
my $ptk = wpa_prf_512 ($keyver, $pmk, $stmac, $bssid, $snonce, $anonce);
# generate the Message Integrity Code (MIC)
my $mic = "";
if ($keyver == 1) # WPA1 => MD5
{
$mic = hmac ($eapol, $ptk, \&md5);
}
elsif ($keyver == 2) # WPA2 => SHA1
{
$mic = hmac ($eapol, $ptk, \&sha1);
}
elsif ($keyver == 3) # WPA2 => SHA256 + AES-CMAC
{
my $omac1 = Digest::CMAC->new ($ptk, 'Crypt::Rijndael');
$omac1->add ($eapol);
$mic = $omac1->digest;
}
$mic = substr ($mic, 0, 16);
#
# format the binary output
#
my $HCCAPX_VERSION = 4;
# signature
my $hash_buf = "HCPX";
# format version
$hash_buf .= pack ("L<", $HCCAPX_VERSION);
# authenticated
$hash_buf .= pack ("C", 0);
# essid length
my $essid_len = length ($salt);
$hash_buf .= pack ("C", $essid_len);
# essid (NULL-padded up to the first 32 bytes)
$hash_buf .= $salt;
$hash_buf .= "\x00" x (32 - $essid_len);
# key version
$hash_buf .= pack ("C", $keyver);
# key mic
$hash_buf .= $mic;
# access point MAC
$hash_buf .= $bssid;
# access point nonce
$hash_buf .= $snonce;
# client MAC
$hash_buf .= $stmac;
# client nonce
$hash_buf .= $anonce;
# eapol length
$hash_buf .= pack ("S<", $eapol_len);
# eapol
$hash_buf .= $eapol;
$hash_buf .= "\x00" x (256 - $eapol_len);
# base64 encode the output
my $hash = encode_base64 ($hash_buf, "");
return $hash;
}
sub module_verify_hash
{
print "ERROR: verify currently not supported for WPA-EAPOL-PBKDF2 (because of hashcat's output format)\n";
exit (1);
}
sub gen_random_wpa_eapol
{
my $keyver = shift;
my $snonce = shift;
my $ret = "";
# version
my $version = 1; # 802.1X-2001
$ret .= pack ("C*", $version);
my $type = 3; # means that this EAPOL frame is used to transfer key information
$ret .= pack ("C*", $type);
my $length; # length of remaining data
if ($keyver == 1)
{
$length = 119;
}
else
{
$length = 117;
}
$ret .= pack ("n*", $length);
my $descriptor_type;
if ($keyver == 1)
{
$descriptor_type = 254; # EAPOL WPA key
}
else
{
$descriptor_type = 1; # EAPOL RSN key
}
$ret .= pack ("C*", $descriptor_type);
# key_info is a bit vector:
# generated from these 13 bits: encrypted key data, request, error, secure, key mic, key ack, install, key index (2), key type, key descriptor (3)
my $key_info = 0;
$key_info |= 1 << 8; # set key MIC
$key_info |= 1 << 3; # set if it is a pairwise key
if ($keyver == 1)
{
$key_info |= 1 << 0; # RC4 Cipher, HMAC-MD5 MIC
}
else
{
$key_info |= 1 << 1; # AES Cipher, HMAC-SHA1 MIC
}
$ret .= pack ("n*", $key_info);
my $key_length;
if ($keyver == 1)
{
$key_length = 32;
}
else
{
$key_length = 0;
}
$ret .= pack ("n*", $key_length);
my $replay_counter = 1;
$ret .= pack ("Q>*", $replay_counter);
$ret .= $snonce;
my $key_iv = "\x00" x 16;
$ret .= $key_iv;
my $key_rsc = "\x00" x 8;
$ret .= $key_rsc;
my $key_id = "\x00" x 8;
$ret .= $key_id;
my $key_mic = "\x00" x 16;
$ret .= $key_mic;
my $key_data_len;
if ($keyver == 1)
{
$key_data_len = 24; # length of the key_data (== WPA info)
}
else
{
$key_data_len = 22; # length of the key_data (== RSN info)
}
$ret .= pack ("n*", $key_data_len);
my $key_data = "";
if ($keyver == 1)
{
# wpa info
my $wpa_info = "";
my $vendor_specific_data = "";
my $tag_number = 221; # means it is a vendor specific tag
$vendor_specific_data .= pack ("C*", $tag_number);
my $tag_len = 22; # length of the remaining "tag data"
$vendor_specific_data .= pack ("C*", $tag_len);
my $vendor_specific_oui = pack ("H*", "0050f2"); # microsoft
$vendor_specific_data .= $vendor_specific_oui;
my $vendor_specific_oui_type = 1; # WPA Information Element
$vendor_specific_data .= pack ("C*", $vendor_specific_oui_type);
my $vendor_specific_wpa_version = 1;
$vendor_specific_data .= pack ("v*", $vendor_specific_wpa_version);
# multicast
my $vendor_specific_multicast_oui = pack ("H*", "0050f2");
$vendor_specific_data .= $vendor_specific_multicast_oui;
my $vendor_specific_multicast_type = 2; # TKIP
$vendor_specific_data .= pack ("C*", $vendor_specific_multicast_type);
# unicast
my $vendor_specific_unicast_count = 1;
$vendor_specific_data .= pack ("v*", $vendor_specific_unicast_count);
my $vendor_specific_unicast_oui = pack ("H*", "0050f2");
$vendor_specific_data .= $vendor_specific_unicast_oui;
my $vendor_specific_unicast_type = 2; # TKIP
$vendor_specific_data .= pack ("C*", $vendor_specific_unicast_type);
# Auth Key Management (AKM)
my $auth_key_management_count = 1;
$vendor_specific_data .= pack ("v*", $auth_key_management_count);
my $auth_key_management_oui = pack ("H*", "0050f2");
$vendor_specific_data .= $auth_key_management_oui;
my $auth_key_management_type = 2; # Pre-Shared Key (PSK)
$vendor_specific_data .= pack ("C*", $auth_key_management_type);
$wpa_info = $vendor_specific_data;
$key_data = $wpa_info;
}
else
{
# rsn info
my $rsn_info = "";
my $tag_number = 48; # RSN info
$rsn_info .= pack ("C*", $tag_number);
my $tag_len = 20; # length of the remaining "tag_data"
$rsn_info .= pack ("C*", $tag_len);
my $rsn_version = 1;
$rsn_info .= pack ("v*", $rsn_version);
# group cipher suite
my $group_cipher_suite_oui = pack ("H*", "000fac"); # Ieee8021
$rsn_info .= $group_cipher_suite_oui;
my $group_cipher_suite_type = 4; # AES (CCM)
$rsn_info .= pack ("C*", $group_cipher_suite_type);
# pairwise cipher suite
my $pairwise_cipher_suite_count = 1;
$rsn_info .= pack ("v*", $pairwise_cipher_suite_count);
my $pairwise_cipher_suite_oui = pack ("H*", "000fac"); # Ieee8021
$rsn_info .= $pairwise_cipher_suite_oui;
my $pairwise_cipher_suite_type = 4; # AES (CCM)
$rsn_info .= pack ("C*", $pairwise_cipher_suite_type);
# Auth Key Management (AKM)
my $auth_key_management_count = 1;
$rsn_info .= pack ("v*", $auth_key_management_count);
my $auth_key_management_oui = pack ("H*", "000fac"); # Ieee8021
$rsn_info .= $auth_key_management_oui;
my $auth_key_management_type = 2; # Pre-Shared Key (PSK)
$rsn_info .= pack ("C*", $auth_key_management_type);
# RSN Capabilities
# bit vector of these 9 bits: peerkey enabled, management frame protection (MFP) capable, MFP required,
# RSN GTKSA Capabilities (2), RSN PTKSA Capabilities (2), no pairwise Capabilities, Pre-Auth Capabilities
my $rsn_capabilities = pack ("H*", "0000");
$rsn_info .= $rsn_capabilities;
$key_data = $rsn_info;
}
$ret .= $key_data;
return $ret;
}
sub wpa_prf_512
{
my $keyver = shift;
my $pmk = shift;
my $stmac = shift;
my $bssid = shift;
my $snonce = shift;
my $anonce = shift;
my $data = "Pairwise key expansion";
if (($keyver == 1) || ($keyver == 2))
{
$data .= "\x00";
}
#
# Min(AA, SPA) || Max(AA, SPA)
#
# compare if greater: Min()/Max() on the MACs (6 bytes)
if (memcmp ($stmac, $bssid, 6) < 0)
{
$data .= $stmac;
$data .= $bssid;
}
else
{
$data .= $bssid;
$data .= $stmac;
}
#
# Min(ANonce,SNonce) || Max(ANonce,SNonce)
#
# compare if greater: Min()/Max() on the nonces (32 bytes)
if (memcmp ($snonce, $anonce, 32) < 0)
{
$data .= $snonce;
$data .= $anonce;
}
else
{
$data .= $anonce;
$data .= $snonce;
}
my $prf_buf;
if (($keyver == 1) || ($keyver == 2))
{
$data .= "\x00";
$prf_buf = hmac ($data, $pmk, \&sha1);
}
else
{
my $data3 = "\x01\x00" . $data . "\x80\x01";
$prf_buf = hmac ($data3, $pmk, \&sha256);
}
$prf_buf = substr ($prf_buf, 0, 16);
return $prf_buf;
}
sub memcmp
{
my $str1 = shift;
my $str2 = shift;
my $len = shift;
my $len_str1 = length ($str1);
my $len_str2 = length ($str2);
if (($len > $len_str1) || ($len > $len_str2))
{
print "ERROR: memcmp () lengths wrong";
exit (1);
}
for (my $i = 0; $i < $len; $i++)
{
my $c_1 = ord (substr ($str1, $i, 1));
my $c_2 = ord (substr ($str2, $i, 1));
return -1 if ($c_1 < $c_2);
return 1 if ($c_1 > $c_2);
}
return 0;
}
1;
Loading…
Cancel
Save