mirror of
https://github.com/hashcat/hashcat.git
synced 2024-11-26 09:58:16 +00:00
With this commit, all hash_mode depending branches from core files are converted into hooks which can be registered on a module level
This commit is contained in:
parent
86819c070f
commit
0ae955c5ba
@ -17,245 +17,6 @@ static const u32 MODULE_VERSION_MINIMUM = 520;
|
|||||||
|
|
||||||
static const int MODULE_HASH_MODES_MAXIMUM = 100000;
|
static const int MODULE_HASH_MODES_MAXIMUM = 100000;
|
||||||
|
|
||||||
/**
|
|
||||||
* zero hashes shutcut
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const char LM_MASKED_PLAIN[] = "[notfound]";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* migrate stuff
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct keyboard_layout_mapping
|
|
||||||
{
|
|
||||||
u32 src_char;
|
|
||||||
int src_len;
|
|
||||||
u32 dst_char;
|
|
||||||
int dst_len;
|
|
||||||
|
|
||||||
} keyboard_layout_mapping_t;
|
|
||||||
|
|
||||||
typedef struct tc
|
|
||||||
{
|
|
||||||
u32 salt_buf[32];
|
|
||||||
u32 data_buf[112];
|
|
||||||
u32 keyfile_buf[16];
|
|
||||||
u32 signature;
|
|
||||||
|
|
||||||
keyboard_layout_mapping_t keyboard_layout_mapping_buf[256];
|
|
||||||
int keyboard_layout_mapping_cnt;
|
|
||||||
|
|
||||||
} tc_t;
|
|
||||||
|
|
||||||
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 seven_zip_hook
|
|
||||||
{
|
|
||||||
u32 ukey[8];
|
|
||||||
|
|
||||||
u32 hook_success;
|
|
||||||
|
|
||||||
} seven_zip_hook_t;
|
|
||||||
|
|
||||||
typedef struct seven_zip_hook_salt
|
|
||||||
{
|
|
||||||
u32 iv_buf[4];
|
|
||||||
u32 iv_len;
|
|
||||||
|
|
||||||
u32 salt_buf[4];
|
|
||||||
u32 salt_len;
|
|
||||||
|
|
||||||
u32 crc;
|
|
||||||
u32 crc_len;
|
|
||||||
|
|
||||||
u8 data_type;
|
|
||||||
|
|
||||||
u32 data_buf[81882];
|
|
||||||
u32 data_len;
|
|
||||||
|
|
||||||
u32 unpack_size;
|
|
||||||
|
|
||||||
char coder_attributes[5 + 1];
|
|
||||||
u8 coder_attributes_len;
|
|
||||||
|
|
||||||
int aes_len; // pre-computed length of the maximal (subset of) data we need for AES-CBC
|
|
||||||
|
|
||||||
} seven_zip_hook_salt_t;
|
|
||||||
|
|
||||||
int check_old_hccap (const char *hashfile);
|
|
||||||
|
|
||||||
|
|
||||||
int luks_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig, const int keyslot_idx);
|
|
||||||
|
|
||||||
static const u32 KERN_TYPE_TOTP_HMACSHA1 = 18100;
|
|
||||||
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA1_AES = 14611;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA1_SERPENT = 14612;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA1_TWOFISH = 14613;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA256_AES = 14621;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA256_SERPENT = 14622;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA256_TWOFISH = 14623;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA512_AES = 14631;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA512_SERPENT = 14632;
|
|
||||||
static const u32 KERN_TYPE_LUKS_SHA512_TWOFISH = 14633;
|
|
||||||
static const u32 KERN_TYPE_LUKS_RIPEMD160_AES = 14641;
|
|
||||||
static const u32 KERN_TYPE_LUKS_RIPEMD160_SERPENT = 14642;
|
|
||||||
static const u32 KERN_TYPE_LUKS_RIPEMD160_TWOFISH = 14643;
|
|
||||||
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_AES = 14651;
|
|
||||||
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_SERPENT = 14652;
|
|
||||||
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH = 14653;
|
|
||||||
|
|
||||||
// original headers from luks.h
|
|
||||||
|
|
||||||
#define LUKS_CIPHERNAME_L 32
|
|
||||||
#define LUKS_CIPHERMODE_L 32
|
|
||||||
#define LUKS_HASHSPEC_L 32
|
|
||||||
#define LUKS_DIGESTSIZE 20 // since SHA1
|
|
||||||
#define LUKS_HMACSIZE 32
|
|
||||||
#define LUKS_SALTSIZE 32
|
|
||||||
#define LUKS_NUMKEYS 8
|
|
||||||
// Minimal number of iterations
|
|
||||||
#define LUKS_MKD_ITERATIONS_MIN 1000
|
|
||||||
#define LUKS_SLOT_ITERATIONS_MIN 1000
|
|
||||||
#define LUKS_KEY_DISABLED_OLD 0
|
|
||||||
#define LUKS_KEY_ENABLED_OLD 0xCAFE
|
|
||||||
#define LUKS_KEY_DISABLED 0x0000DEAD
|
|
||||||
#define LUKS_KEY_ENABLED 0x00AC71F3
|
|
||||||
#define LUKS_STRIPES 4000
|
|
||||||
// partition header starts with magic
|
|
||||||
#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
|
|
||||||
#define LUKS_MAGIC_L 6
|
|
||||||
/* Actually we need only 37, but we don't want struct autoaligning to kick in */
|
|
||||||
#define UUID_STRING_L 40
|
|
||||||
/* Offset to keyslot area [in bytes] */
|
|
||||||
#define LUKS_ALIGN_KEYSLOTS 4096
|
|
||||||
|
|
||||||
struct luks_phdr {
|
|
||||||
char magic[LUKS_MAGIC_L];
|
|
||||||
uint16_t version;
|
|
||||||
char cipherName[LUKS_CIPHERNAME_L];
|
|
||||||
char cipherMode[LUKS_CIPHERMODE_L];
|
|
||||||
char hashSpec[LUKS_HASHSPEC_L];
|
|
||||||
uint32_t payloadOffset;
|
|
||||||
uint32_t keyBytes;
|
|
||||||
char mkDigest[LUKS_DIGESTSIZE];
|
|
||||||
char mkDigestSalt[LUKS_SALTSIZE];
|
|
||||||
uint32_t mkDigestIterations;
|
|
||||||
char uuid[UUID_STRING_L];
|
|
||||||
struct {
|
|
||||||
uint32_t active;
|
|
||||||
/* parameters used for password processing */
|
|
||||||
uint32_t passwordIterations;
|
|
||||||
char passwordSalt[LUKS_SALTSIZE];
|
|
||||||
/* parameters used for AF store/load */
|
|
||||||
uint32_t keyMaterialOffset;
|
|
||||||
uint32_t stripes;
|
|
||||||
} keyblock[LUKS_NUMKEYS];
|
|
||||||
/* Align it to 512 sector size */
|
|
||||||
char _padding[432];
|
|
||||||
};
|
|
||||||
|
|
||||||
// not from original headers start with hc_
|
|
||||||
|
|
||||||
typedef enum hc_luks_hash_type
|
|
||||||
{
|
|
||||||
HC_LUKS_HASH_TYPE_SHA1 = 1,
|
|
||||||
HC_LUKS_HASH_TYPE_SHA256 = 2,
|
|
||||||
HC_LUKS_HASH_TYPE_SHA512 = 3,
|
|
||||||
HC_LUKS_HASH_TYPE_RIPEMD160 = 4,
|
|
||||||
HC_LUKS_HASH_TYPE_WHIRLPOOL = 5,
|
|
||||||
|
|
||||||
} hc_luks_hash_type_t;
|
|
||||||
|
|
||||||
typedef enum hc_luks_key_size
|
|
||||||
{
|
|
||||||
HC_LUKS_KEY_SIZE_128 = 128,
|
|
||||||
HC_LUKS_KEY_SIZE_256 = 256,
|
|
||||||
HC_LUKS_KEY_SIZE_512 = 512,
|
|
||||||
|
|
||||||
} hc_luks_key_size_t;
|
|
||||||
|
|
||||||
typedef enum hc_luks_cipher_type
|
|
||||||
{
|
|
||||||
HC_LUKS_CIPHER_TYPE_AES = 1,
|
|
||||||
HC_LUKS_CIPHER_TYPE_SERPENT = 2,
|
|
||||||
HC_LUKS_CIPHER_TYPE_TWOFISH = 3,
|
|
||||||
|
|
||||||
} hc_luks_cipher_type_t;
|
|
||||||
|
|
||||||
typedef enum hc_luks_cipher_mode
|
|
||||||
{
|
|
||||||
HC_LUKS_CIPHER_MODE_CBC_ESSIV = 1,
|
|
||||||
HC_LUKS_CIPHER_MODE_CBC_PLAIN = 2,
|
|
||||||
HC_LUKS_CIPHER_MODE_XTS_PLAIN = 3,
|
|
||||||
|
|
||||||
} hc_luks_cipher_mode_t;
|
|
||||||
|
|
||||||
typedef struct luks
|
|
||||||
{
|
|
||||||
int hash_type; // hc_luks_hash_type_t
|
|
||||||
int key_size; // hc_luks_key_size_t
|
|
||||||
int cipher_type; // hc_luks_cipher_type_t
|
|
||||||
int cipher_mode; // hc_luks_cipher_mode_t
|
|
||||||
|
|
||||||
u32 ct_buf[128];
|
|
||||||
|
|
||||||
u32 af_src_buf[((HC_LUKS_KEY_SIZE_512 / 8) * LUKS_STRIPES) / 4];
|
|
||||||
|
|
||||||
} luks_t;
|
|
||||||
|
|
||||||
typedef enum kernel_workload
|
typedef enum kernel_workload
|
||||||
{
|
{
|
||||||
KERNEL_ACCEL_MIN = 1,
|
KERNEL_ACCEL_MIN = 1,
|
||||||
@ -277,6 +38,8 @@ const char *stroptitype (const u32 opti_type);
|
|||||||
int ascii_digest (const hashconfig_t *hashconfig, const hashes_t *hashes, const module_ctx_t *module_ctx, char *out_buf, const int out_size, const u32 salt_pos, const u32 digest_pos);
|
int ascii_digest (const hashconfig_t *hashconfig, const hashes_t *hashes, const module_ctx_t *module_ctx, char *out_buf, const int out_size, const u32 salt_pos, const u32 digest_pos);
|
||||||
|
|
||||||
bool initialize_keyboard_layout_mapping (hashcat_ctx_t *hashcat_ctx, const char *filename, keyboard_layout_mapping_t *keyboard_layout_mapping, int *keyboard_layout_mapping_cnt);
|
bool initialize_keyboard_layout_mapping (hashcat_ctx_t *hashcat_ctx, const char *filename, keyboard_layout_mapping_t *keyboard_layout_mapping, int *keyboard_layout_mapping_cnt);
|
||||||
|
int find_keyboard_layout_map (const u32 search, const int search_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt);
|
||||||
|
int execute_keyboard_layout_mapping (u32 plain_buf[64], const int plain_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt);
|
||||||
|
|
||||||
int hashconfig_init (hashcat_ctx_t *hashcat_ctx);
|
int hashconfig_init (hashcat_ctx_t *hashcat_ctx);
|
||||||
void hashconfig_destroy (hashcat_ctx_t *hashcat_ctx);
|
void hashconfig_destroy (hashcat_ctx_t *hashcat_ctx);
|
||||||
|
@ -9,6 +9,58 @@ static const float MIN_SUFFICIENT_ENTROPY_FILE = 7.0f;
|
|||||||
* algo specific
|
* 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
|
typedef struct itunes_backup
|
||||||
{
|
{
|
||||||
@ -1379,7 +1431,7 @@ int win8phone_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_bu
|
|||||||
int opencart_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int opencart_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
int plaintext_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int plaintext_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
int sha1cx_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int sha1cx_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
|
int luks_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig, const int keyslot_idx);
|
||||||
int itunes_backup_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int itunes_backup_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
int skip32_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int skip32_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
int fortigate_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int fortigate_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
@ -1404,10 +1456,175 @@ int ansible_vault_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_bu
|
|||||||
int totp_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int totp_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
int apfs_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
int apfs_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hook functions
|
* migrate stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tc
|
||||||
|
{
|
||||||
|
u32 salt_buf[32];
|
||||||
|
u32 data_buf[112];
|
||||||
|
u32 keyfile_buf[16];
|
||||||
|
u32 signature;
|
||||||
|
|
||||||
|
keyboard_layout_mapping_t keyboard_layout_mapping_buf[256];
|
||||||
|
int keyboard_layout_mapping_cnt;
|
||||||
|
|
||||||
|
} tc_t;
|
||||||
|
|
||||||
|
typedef struct seven_zip_hook
|
||||||
|
{
|
||||||
|
u32 ukey[8];
|
||||||
|
|
||||||
|
u32 hook_success;
|
||||||
|
|
||||||
|
} seven_zip_hook_t;
|
||||||
|
|
||||||
|
typedef struct seven_zip_hook_salt
|
||||||
|
{
|
||||||
|
u32 iv_buf[4];
|
||||||
|
u32 iv_len;
|
||||||
|
|
||||||
|
u32 salt_buf[4];
|
||||||
|
u32 salt_len;
|
||||||
|
|
||||||
|
u32 crc;
|
||||||
|
u32 crc_len;
|
||||||
|
|
||||||
|
u8 data_type;
|
||||||
|
|
||||||
|
u32 data_buf[81882];
|
||||||
|
u32 data_len;
|
||||||
|
|
||||||
|
u32 unpack_size;
|
||||||
|
|
||||||
|
char coder_attributes[5 + 1];
|
||||||
|
u8 coder_attributes_len;
|
||||||
|
|
||||||
|
int aes_len; // pre-computed length of the maximal (subset of) data we need for AES-CBC
|
||||||
|
|
||||||
|
} seven_zip_hook_salt_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const u32 KERN_TYPE_TOTP_HMACSHA1 = 18100;
|
||||||
|
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA1_AES = 14611;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA1_SERPENT = 14612;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA1_TWOFISH = 14613;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA256_AES = 14621;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA256_SERPENT = 14622;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA256_TWOFISH = 14623;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA512_AES = 14631;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA512_SERPENT = 14632;
|
||||||
|
static const u32 KERN_TYPE_LUKS_SHA512_TWOFISH = 14633;
|
||||||
|
static const u32 KERN_TYPE_LUKS_RIPEMD160_AES = 14641;
|
||||||
|
static const u32 KERN_TYPE_LUKS_RIPEMD160_SERPENT = 14642;
|
||||||
|
static const u32 KERN_TYPE_LUKS_RIPEMD160_TWOFISH = 14643;
|
||||||
|
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_AES = 14651;
|
||||||
|
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_SERPENT = 14652;
|
||||||
|
static const u32 KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH = 14653;
|
||||||
|
|
||||||
|
// original headers from luks.h
|
||||||
|
|
||||||
|
#define LUKS_CIPHERNAME_L 32
|
||||||
|
#define LUKS_CIPHERMODE_L 32
|
||||||
|
#define LUKS_HASHSPEC_L 32
|
||||||
|
#define LUKS_DIGESTSIZE 20 // since SHA1
|
||||||
|
#define LUKS_HMACSIZE 32
|
||||||
|
#define LUKS_SALTSIZE 32
|
||||||
|
#define LUKS_NUMKEYS 8
|
||||||
|
// Minimal number of iterations
|
||||||
|
#define LUKS_MKD_ITERATIONS_MIN 1000
|
||||||
|
#define LUKS_SLOT_ITERATIONS_MIN 1000
|
||||||
|
#define LUKS_KEY_DISABLED_OLD 0
|
||||||
|
#define LUKS_KEY_ENABLED_OLD 0xCAFE
|
||||||
|
#define LUKS_KEY_DISABLED 0x0000DEAD
|
||||||
|
#define LUKS_KEY_ENABLED 0x00AC71F3
|
||||||
|
#define LUKS_STRIPES 4000
|
||||||
|
// partition header starts with magic
|
||||||
|
#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
|
||||||
|
#define LUKS_MAGIC_L 6
|
||||||
|
/* Actually we need only 37, but we don't want struct autoaligning to kick in */
|
||||||
|
#define UUID_STRING_L 40
|
||||||
|
/* Offset to keyslot area [in bytes] */
|
||||||
|
#define LUKS_ALIGN_KEYSLOTS 4096
|
||||||
|
|
||||||
|
struct luks_phdr {
|
||||||
|
char magic[LUKS_MAGIC_L];
|
||||||
|
uint16_t version;
|
||||||
|
char cipherName[LUKS_CIPHERNAME_L];
|
||||||
|
char cipherMode[LUKS_CIPHERMODE_L];
|
||||||
|
char hashSpec[LUKS_HASHSPEC_L];
|
||||||
|
uint32_t payloadOffset;
|
||||||
|
uint32_t keyBytes;
|
||||||
|
char mkDigest[LUKS_DIGESTSIZE];
|
||||||
|
char mkDigestSalt[LUKS_SALTSIZE];
|
||||||
|
uint32_t mkDigestIterations;
|
||||||
|
char uuid[UUID_STRING_L];
|
||||||
|
struct {
|
||||||
|
uint32_t active;
|
||||||
|
/* parameters used for password processing */
|
||||||
|
uint32_t passwordIterations;
|
||||||
|
char passwordSalt[LUKS_SALTSIZE];
|
||||||
|
/* parameters used for AF store/load */
|
||||||
|
uint32_t keyMaterialOffset;
|
||||||
|
uint32_t stripes;
|
||||||
|
} keyblock[LUKS_NUMKEYS];
|
||||||
|
/* Align it to 512 sector size */
|
||||||
|
char _padding[432];
|
||||||
|
};
|
||||||
|
|
||||||
|
// not from original headers start with hc_
|
||||||
|
|
||||||
|
typedef enum hc_luks_hash_type
|
||||||
|
{
|
||||||
|
HC_LUKS_HASH_TYPE_SHA1 = 1,
|
||||||
|
HC_LUKS_HASH_TYPE_SHA256 = 2,
|
||||||
|
HC_LUKS_HASH_TYPE_SHA512 = 3,
|
||||||
|
HC_LUKS_HASH_TYPE_RIPEMD160 = 4,
|
||||||
|
HC_LUKS_HASH_TYPE_WHIRLPOOL = 5,
|
||||||
|
|
||||||
|
} hc_luks_hash_type_t;
|
||||||
|
|
||||||
|
typedef enum hc_luks_key_size
|
||||||
|
{
|
||||||
|
HC_LUKS_KEY_SIZE_128 = 128,
|
||||||
|
HC_LUKS_KEY_SIZE_256 = 256,
|
||||||
|
HC_LUKS_KEY_SIZE_512 = 512,
|
||||||
|
|
||||||
|
} hc_luks_key_size_t;
|
||||||
|
|
||||||
|
typedef enum hc_luks_cipher_type
|
||||||
|
{
|
||||||
|
HC_LUKS_CIPHER_TYPE_AES = 1,
|
||||||
|
HC_LUKS_CIPHER_TYPE_SERPENT = 2,
|
||||||
|
HC_LUKS_CIPHER_TYPE_TWOFISH = 3,
|
||||||
|
|
||||||
|
} hc_luks_cipher_type_t;
|
||||||
|
|
||||||
|
typedef enum hc_luks_cipher_mode
|
||||||
|
{
|
||||||
|
HC_LUKS_CIPHER_MODE_CBC_ESSIV = 1,
|
||||||
|
HC_LUKS_CIPHER_MODE_CBC_PLAIN = 2,
|
||||||
|
HC_LUKS_CIPHER_MODE_XTS_PLAIN = 3,
|
||||||
|
|
||||||
|
} hc_luks_cipher_mode_t;
|
||||||
|
|
||||||
|
typedef struct luks
|
||||||
|
{
|
||||||
|
int hash_type; // hc_luks_hash_type_t
|
||||||
|
int key_size; // hc_luks_key_size_t
|
||||||
|
int cipher_type; // hc_luks_cipher_type_t
|
||||||
|
int cipher_mode; // hc_luks_cipher_mode_t
|
||||||
|
|
||||||
|
u32 ct_buf[128];
|
||||||
|
|
||||||
|
u32 af_src_buf[((HC_LUKS_KEY_SIZE_512 / 8) * LUKS_STRIPES) / 4];
|
||||||
|
|
||||||
|
} luks_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ u64 module_tmp_size (MAYBE_UNUSED const hashconfig_t *ha
|
|||||||
bool module_unstable_warning (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra);
|
bool module_unstable_warning (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra);
|
||||||
bool module_warmup_disable (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra);
|
bool module_warmup_disable (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra);
|
||||||
|
|
||||||
|
int module_hash_binary_count (MAYBE_UNUSED const hashes_t *hashes);
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
bool module_hash_binary_verify (MAYBE_UNUSED const hashes_t *hashes);
|
||||||
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, const char *line_buf, MAYBE_UNUSED const int line_len);
|
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, const char *line_buf, MAYBE_UNUSED const int line_len);
|
||||||
int module_hash_decode_zero_hash (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf);
|
int module_hash_decode_zero_hash (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED void *digest_buf, MAYBE_UNUSED salt_t *salt, MAYBE_UNUSED void *esalt_buf);
|
||||||
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, const char *line_buf, MAYBE_UNUSED const int line_len);
|
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, const char *line_buf, MAYBE_UNUSED const int line_len);
|
||||||
@ -59,7 +63,6 @@ int module_hash_encode (MAYBE_UNUSED const hashconfig_t *ha
|
|||||||
u64 module_extra_buffer_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, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param);
|
u64 module_extra_buffer_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, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param);
|
||||||
char *module_jit_build_options (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 hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param);
|
char *module_jit_build_options (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 hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param);
|
||||||
u32 module_deep_comp_kernel (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos);
|
u32 module_deep_comp_kernel (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos);
|
||||||
int module_hash_save_binary (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos, const char **buf);
|
|
||||||
int module_hash_init_selftest (MAYBE_UNUSED const hashconfig_t *hashconfig, hash_t *hash);
|
int module_hash_init_selftest (MAYBE_UNUSED const hashconfig_t *hashconfig, hash_t *hash);
|
||||||
|
|
||||||
void module_hook12 (hc_device_param_t *device_param, void *hook_salts_buf, const u32 salt_pos, const u64 pws_cnt);
|
void module_hook12 (hc_device_param_t *device_param, void *hook_salts_buf, const u32 salt_pos, const u64 pws_cnt);
|
||||||
|
@ -2298,6 +2298,10 @@ typedef struct module_ctx
|
|||||||
bool (*module_unstable_warning) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *);
|
bool (*module_unstable_warning) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *);
|
||||||
bool (*module_warmup_disable) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *);
|
bool (*module_warmup_disable) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *);
|
||||||
|
|
||||||
|
int (*module_hash_binary_count) (const hashes_t *);
|
||||||
|
int (*module_hash_binary_parse) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *, hashes_t *);
|
||||||
|
int (*module_hash_binary_save) (const hashes_t *, const u32, const u32, char **);
|
||||||
|
bool (*module_hash_binary_verify) (const hashes_t *);
|
||||||
int (*module_hash_decode_outfile) (const hashconfig_t *, void *, salt_t *, void *, const char *, const int);
|
int (*module_hash_decode_outfile) (const hashconfig_t *, void *, salt_t *, void *, const char *, const int);
|
||||||
int (*module_hash_decode_zero_hash) (const hashconfig_t *, void *, salt_t *, void *);
|
int (*module_hash_decode_zero_hash) (const hashconfig_t *, void *, salt_t *, void *);
|
||||||
int (*module_hash_decode) (const hashconfig_t *, void *, salt_t *, void *, const char *, const int);
|
int (*module_hash_decode) (const hashconfig_t *, void *, salt_t *, void *, const char *, const int);
|
||||||
@ -2307,7 +2311,6 @@ typedef struct module_ctx
|
|||||||
u64 (*module_extra_buffer_size) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *, const hashes_t *, const hc_device_param_t *);
|
u64 (*module_extra_buffer_size) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *, const hashes_t *, const hc_device_param_t *);
|
||||||
char *(*module_jit_build_options) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *, const hashes_t *, const hc_device_param_t *);
|
char *(*module_jit_build_options) (const hashconfig_t *, const user_options_t *, const user_options_extra_t *, const hashes_t *, const hc_device_param_t *);
|
||||||
u32 (*module_deep_comp_kernel) (const hashes_t *, const u32, const u32);
|
u32 (*module_deep_comp_kernel) (const hashes_t *, const u32, const u32);
|
||||||
int (*module_hash_save_binary) (const hashes_t *, const u32, const u32, char **);
|
|
||||||
int (*module_hash_init_selftest) (const hashconfig_t *, hash_t *);
|
int (*module_hash_init_selftest) (const hashconfig_t *, hash_t *);
|
||||||
|
|
||||||
void (*module_hook12) (hc_device_param_t *, const void *, const u32, const u64);
|
void (*module_hook12) (hc_device_param_t *, const void *, const u32, const u64);
|
||||||
@ -2492,3 +2495,12 @@ typedef enum hash_category
|
|||||||
HASH_CATEGORY_PLAIN = 19,
|
HASH_CATEGORY_PLAIN = 19,
|
||||||
|
|
||||||
} hash_category_t;
|
} hash_category_t;
|
||||||
|
|
||||||
|
typedef struct keyboard_layout_mapping
|
||||||
|
{
|
||||||
|
u32 src_char;
|
||||||
|
int src_len;
|
||||||
|
u32 dst_char;
|
||||||
|
int dst_len;
|
||||||
|
|
||||||
|
} keyboard_layout_mapping_t;
|
||||||
|
@ -131,6 +131,10 @@ void module_init (module_ctx_t *module_ctx)
|
|||||||
module_ctx->module_esalt_size = MODULE_DEFAULT;
|
module_ctx->module_esalt_size = MODULE_DEFAULT;
|
||||||
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
|
module_ctx->module_extra_buffer_size = MODULE_DEFAULT;
|
||||||
module_ctx->module_forced_outfile_format = 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_binary_verify = MODULE_DEFAULT;
|
||||||
module_ctx->module_hash_decode_outfile = MODULE_DEFAULT;
|
module_ctx->module_hash_decode_outfile = MODULE_DEFAULT;
|
||||||
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
|
module_ctx->module_hash_decode_zero_hash = MODULE_DEFAULT;
|
||||||
module_ctx->module_hash_decode = module_hash_decode;
|
module_ctx->module_hash_decode = module_hash_decode;
|
||||||
@ -140,7 +144,6 @@ void module_init (module_ctx_t *module_ctx)
|
|||||||
module_ctx->module_hash_mode = MODULE_DEFAULT;
|
module_ctx->module_hash_mode = MODULE_DEFAULT;
|
||||||
module_ctx->module_hash_category = module_hash_category;
|
module_ctx->module_hash_category = module_hash_category;
|
||||||
module_ctx->module_hash_name = module_hash_name;
|
module_ctx->module_hash_name = module_hash_name;
|
||||||
module_ctx->module_hash_save_binary = MODULE_DEFAULT;
|
|
||||||
module_ctx->module_hash_type = module_hash_type;
|
module_ctx->module_hash_type = module_hash_type;
|
||||||
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
|
module_ctx->module_hlfmt_disable = MODULE_DEFAULT;
|
||||||
module_ctx->module_hook12 = MODULE_DEFAULT;
|
module_ctx->module_hook12 = MODULE_DEFAULT;
|
||||||
|
366
src/hashes.c
366
src/hashes.c
@ -32,138 +32,6 @@
|
|||||||
#include "brain.h"
|
#include "brain.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// get rid of this!
|
|
||||||
static int hashconfig_general_defaults (hashcat_ctx_t *hashcat_ctx)
|
|
||||||
{
|
|
||||||
hashconfig_t *hashconfig = hashcat_ctx->hashconfig;
|
|
||||||
user_options_t *user_options = hashcat_ctx->user_options;
|
|
||||||
|
|
||||||
// truecrypt and veracrypt only
|
|
||||||
if (((hashconfig->hash_mode >= 6200) && (hashconfig->hash_mode <= 6299))
|
|
||||||
|| ((hashconfig->hash_mode >= 13700) && (hashconfig->hash_mode == 13799)))
|
|
||||||
{
|
|
||||||
hashes_t *hashes = hashcat_ctx->hashes;
|
|
||||||
|
|
||||||
tc_t *tc = (tc_t *) hashes->esalts_buf;
|
|
||||||
|
|
||||||
char *optional_param1 = NULL;
|
|
||||||
|
|
||||||
if (user_options->truecrypt_keyfiles) optional_param1 = user_options->truecrypt_keyfiles;
|
|
||||||
if (user_options->veracrypt_keyfiles) optional_param1 = user_options->veracrypt_keyfiles;
|
|
||||||
|
|
||||||
if (optional_param1)
|
|
||||||
{
|
|
||||||
char *tcvc_keyfiles = optional_param1;
|
|
||||||
|
|
||||||
char *keyfiles = hcstrdup (tcvc_keyfiles);
|
|
||||||
|
|
||||||
if (keyfiles == NULL) return -1;
|
|
||||||
|
|
||||||
char *saveptr = NULL;
|
|
||||||
|
|
||||||
char *keyfile = strtok_r (keyfiles, ",", &saveptr);
|
|
||||||
|
|
||||||
if (keyfile == NULL)
|
|
||||||
{
|
|
||||||
free (keyfiles);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
const int rc_crc32 = cpu_crc32 (hashcat_ctx, keyfile, (u8 *) tc->keyfile_buf);
|
|
||||||
|
|
||||||
if (rc_crc32 == -1)
|
|
||||||
{
|
|
||||||
free (keyfiles);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while ((keyfile = strtok_r ((char *) NULL, ",", &saveptr)) != NULL);
|
|
||||||
|
|
||||||
free (keyfiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// truecrypt and veracrypt boot only
|
|
||||||
if (hashconfig->opts_type & OPTS_TYPE_KEYBOARD_MAPPING)
|
|
||||||
{
|
|
||||||
if (user_options->keyboard_layout_mapping)
|
|
||||||
{
|
|
||||||
const bool rc = initialize_keyboard_layout_mapping (hashcat_ctx, user_options->keyboard_layout_mapping, tc->keyboard_layout_mapping_buf, &tc->keyboard_layout_mapping_cnt);
|
|
||||||
|
|
||||||
if (rc == false) return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// veracrypt only
|
|
||||||
if ((hashconfig->hash_mode >= 13700) && (hashconfig->hash_mode == 13799))
|
|
||||||
{
|
|
||||||
if (user_options->veracrypt_pim)
|
|
||||||
{
|
|
||||||
// we can access salt directly here because in VC it's always just one salt not many
|
|
||||||
|
|
||||||
hashes_t *hashes = hashcat_ctx->hashes;
|
|
||||||
|
|
||||||
salt_t *salts_buf = hashes->salts_buf;
|
|
||||||
|
|
||||||
salt_t *salt = &salts_buf[0];
|
|
||||||
|
|
||||||
switch (hashconfig->hash_mode)
|
|
||||||
{
|
|
||||||
case 13711: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13712: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13713: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13721: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13722: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13723: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13731: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13732: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13733: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13741: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13742: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13743: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13751: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13752: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13753: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13761: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13762: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13763: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
|
||||||
break;
|
|
||||||
case 13771: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13772: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
case 13773: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
salt->salt_iter -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sort_by_string (const void *p1, const void *p2)
|
int sort_by_string (const void *p1, const void *p2)
|
||||||
{
|
{
|
||||||
const char *s1 = (const char *) p1;
|
const char *s1 = (const char *) p1;
|
||||||
@ -320,11 +188,11 @@ int save_hash (hashcat_ctx_t *hashcat_ctx)
|
|||||||
|
|
||||||
if (hashes->digests_shown[idx] == 1) continue;
|
if (hashes->digests_shown[idx] == 1) continue;
|
||||||
|
|
||||||
if (module_ctx->module_hash_save_binary != MODULE_DEFAULT)
|
if (module_ctx->module_hash_binary_save != MODULE_DEFAULT)
|
||||||
{
|
{
|
||||||
char *binary_buf = NULL;
|
char *binary_buf = NULL;
|
||||||
|
|
||||||
const int binary_len = module_ctx->module_hash_save_binary (hashes, salt_pos, digest_pos, &binary_buf);
|
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);
|
hc_fwrite (binary_buf, binary_len, 1, fp);
|
||||||
}
|
}
|
||||||
@ -682,7 +550,9 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
{
|
{
|
||||||
if (hashlist_mode == HL_MODE_ARG)
|
if (hashlist_mode == HL_MODE_ARG)
|
||||||
{
|
{
|
||||||
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
|
// binary files are listed here as a result of a hack
|
||||||
|
|
||||||
|
if (hashconfig->opts_type & OPTS_TYPE_BINARY_HASHFILE)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
@ -693,34 +563,35 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 392 = old hccap_t size
|
if (module_ctx->module_hash_binary_verify != MODULE_DEFAULT)
|
||||||
|
|
||||||
if ((st.st_size % 392) == 0)
|
|
||||||
{
|
{
|
||||||
const int rc = check_old_hccap (hashes->hashfile);
|
const bool rc_verify = module_ctx->module_hash_binary_verify (hashes);
|
||||||
|
|
||||||
if (rc == 1)
|
if (rc_verify == false)
|
||||||
{
|
{
|
||||||
event_log_error (hashcat_ctx, "%s: Old hccap format detected! You need to update: https://hashcat.net/q/hccapx", hashes->hashfile);
|
event_log_error (hashcat_ctx, "%s: %s", hashes->hashfile, strerror (errno));
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hashes_avail = st.st_size / sizeof (hccapx_t);
|
if (module_ctx->module_hash_binary_count != MODULE_DEFAULT)
|
||||||
}
|
|
||||||
else if (hashconfig->hash_mode == 14600)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (stat (hashes->hashfile, &st) == -1)
|
|
||||||
{
|
{
|
||||||
event_log_error (hashcat_ctx, "%s: %s", hashes->hashfile, strerror (errno));
|
const int binary_count = module_ctx->module_hash_binary_count (hashes);
|
||||||
|
|
||||||
return -1;
|
if (binary_count == -1)
|
||||||
|
{
|
||||||
|
event_log_error (hashcat_ctx, "%s: %s", hashes->hashfile, strerror (errno));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashes_avail = binary_count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hashes_avail = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashes_avail = LUKS_NUMKEYS;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -774,7 +645,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
hashes_avail = 1;
|
hashes_avail = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashconfig->hash_mode == 3000) hashes_avail *= 2;
|
if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT) hashes_avail *= 2;
|
||||||
|
|
||||||
hashes->hashlist_format = hashlist_format;
|
hashes->hashlist_format = hashlist_format;
|
||||||
|
|
||||||
@ -829,7 +700,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
|
|
||||||
if (hashconfig->hook_salt_size > 0)
|
if (hashconfig->hook_salt_size > 0)
|
||||||
{
|
{
|
||||||
hook_salts_buf = (seven_zip_hook_salt_t *) hccalloc (hashes_avail, hashconfig->hook_salt_size);
|
hook_salts_buf = hccalloc (hashes_avail, hashconfig->hook_salt_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -952,128 +823,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
|
|
||||||
int parser_status = PARSER_OK;
|
int parser_status = PARSER_OK;
|
||||||
|
|
||||||
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
|
if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)
|
||||||
{
|
|
||||||
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 (hashes_avail == hashes_cnt)
|
|
||||||
{
|
|
||||||
event_log_warning (hashcat_ctx, "Hashfile '%s': File changed during runtime. Skipping new data.", hash_buf);
|
|
||||||
|
|
||||||
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 ((user_options->hash_mode == 2500) || (user_options->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)
|
|
||||||
{
|
|
||||||
event_log_warning (hashcat_ctx, "Hashfile '%s': %s", hash_buf, strparser (parser_status));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes_cnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
hcfree (in);
|
|
||||||
|
|
||||||
fclose (fp);
|
|
||||||
}
|
|
||||||
else if (hashconfig->hash_mode == 3000)
|
|
||||||
{
|
{
|
||||||
if (hash_len == 32)
|
if (hash_len == 32)
|
||||||
{
|
{
|
||||||
@ -1130,40 +880,35 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hashconfig->hash_mode == 14600)
|
|
||||||
{
|
|
||||||
hashes->hashlist_mode = HL_MODE_FILE;
|
|
||||||
|
|
||||||
for (int keyslot_idx = 0; keyslot_idx < LUKS_NUMKEYS; keyslot_idx++)
|
|
||||||
{
|
|
||||||
parser_status = luks_parse_hash ((u8 *) hash_buf, (const int) hash_len, &hashes_buf[hashes_cnt], hashconfig, keyslot_idx);
|
|
||||||
|
|
||||||
if (parser_status != PARSER_OK)
|
|
||||||
{
|
|
||||||
if (parser_status != PARSER_LUKS_KEY_DISABLED)
|
|
||||||
{
|
|
||||||
event_log_warning (hashcat_ctx, "Hashfile '%s': %s", hash_buf, strparser (parser_status));
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashes_cnt++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hash_t *hash = &hashes_buf[hashes_cnt];
|
if (module_ctx->module_hash_binary_parse)
|
||||||
|
|
||||||
parser_status = module_ctx->module_hash_decode (hashconfig, hash->digest, hash->salt, hash->esalt, hash_buf, hash_len);
|
|
||||||
|
|
||||||
if (parser_status == PARSER_OK)
|
|
||||||
{
|
{
|
||||||
hashes_cnt++;
|
const int hashes_parsed = module_ctx->module_hash_binary_parse (hashconfig, user_options, user_options_extra, hashes);
|
||||||
|
|
||||||
|
if (hashes_parsed > 0)
|
||||||
|
{
|
||||||
|
hashes_cnt = hashes_parsed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event_log_warning (hashcat_ctx, "Hashfile '%s': %s", hashes->hashfile, strerror (errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status));
|
hash_t *hash = &hashes_buf[hashes_cnt];
|
||||||
|
|
||||||
|
parser_status = module_ctx->module_hash_decode (hashconfig, hash->digest, hash->salt, hash->esalt, hash_buf, hash_len);
|
||||||
|
|
||||||
|
if (parser_status == PARSER_OK)
|
||||||
|
{
|
||||||
|
hashes_cnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event_log_warning (hashcat_ctx, "Hash '%s': %s", input_buf, strparser (parser_status));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1230,8 +975,10 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
|
|
||||||
u32 hashes_per_user = 1;
|
u32 hashes_per_user = 1;
|
||||||
|
|
||||||
if (hashconfig->hash_mode == 3000) // the following conditions should be true if (hashlist_format == HLFMT_PWDUMP)
|
if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)
|
||||||
{
|
{
|
||||||
|
// the following conditions should be true if (hashlist_format == HLFMT_PWDUMP)
|
||||||
|
|
||||||
if (hash_len == 32)
|
if (hash_len == 32)
|
||||||
{
|
{
|
||||||
hashes_per_user = 2;
|
hashes_per_user = 2;
|
||||||
@ -1281,7 +1028,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
memset (hashes_buf[hashes_cnt].hook_salt, 0, hashconfig->hook_salt_size);
|
memset (hashes_buf[hashes_cnt].hook_salt, 0, hashconfig->hook_salt_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashconfig->hash_mode == 3000)
|
if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)
|
||||||
{
|
{
|
||||||
if (hash_len == 32)
|
if (hash_len == 32)
|
||||||
{
|
{
|
||||||
@ -1431,7 +1178,7 @@ int hashes_init_stage1 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
EVENT (EVENT_HASHLIST_SORT_HASH_POST);
|
EVENT (EVENT_HASHLIST_SORT_HASH_POST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashconfig->hash_mode == 3000)
|
if (hashconfig->opts_type & OPTS_TYPE_HASH_SPLIT)
|
||||||
{
|
{
|
||||||
// update split split_neighbor after sorting
|
// update split split_neighbor after sorting
|
||||||
// see https://github.com/hashcat/hashcat/issues/1034 for good examples for testing
|
// see https://github.com/hashcat/hashcat/issues/1034 for good examples for testing
|
||||||
@ -1762,9 +1509,10 @@ int hashes_init_stage4 (hashcat_ctx_t *hashcat_ctx)
|
|||||||
hashes_t *hashes = hashcat_ctx->hashes;
|
hashes_t *hashes = hashcat_ctx->hashes;
|
||||||
user_options_t *user_options = hashcat_ctx->user_options;
|
user_options_t *user_options = hashcat_ctx->user_options;
|
||||||
|
|
||||||
const int rc_defaults = hashconfig_general_defaults (hashcat_ctx);
|
// this is a good phase for setting keyfile and keyboard mapping
|
||||||
|
//const int rc_defaults = hashconfig_general_defaults (hashcat_ctx);
|
||||||
|
|
||||||
if (rc_defaults == -1) return -1;
|
//if (rc_defaults == -1) return -1;
|
||||||
|
|
||||||
if (hashes->salts_cnt == 1)
|
if (hashes->salts_cnt == 1)
|
||||||
hashconfig->opti_type |= OPTI_TYPE_SINGLE_SALT;
|
hashconfig->opti_type |= OPTI_TYPE_SINGLE_SALT;
|
||||||
|
659
src/interface.c
659
src/interface.c
@ -159,6 +159,193 @@ bool initialize_keyboard_layout_mapping (hashcat_ctx_t *hashcat_ctx, const char
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int find_keyboard_layout_map (const u32 search, const int search_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
||||||
|
{
|
||||||
|
for (int idx = 0; idx < keyboard_layout_mapping_cnt; idx++)
|
||||||
|
{
|
||||||
|
const u32 src_char = s_keyboard_layout_mapping[idx].src_char;
|
||||||
|
const int src_len = s_keyboard_layout_mapping[idx].src_len;
|
||||||
|
|
||||||
|
if (src_len == search_len)
|
||||||
|
{
|
||||||
|
const u32 mask = 0xffffffff >> ((4 - search_len) * 8);
|
||||||
|
|
||||||
|
if ((src_char & mask) == (search & mask)) return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int execute_keyboard_layout_mapping (u32 plain_buf[64], const int plain_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
||||||
|
{
|
||||||
|
u32 out_buf[16] = { 0 };
|
||||||
|
|
||||||
|
u8 *out_ptr = (u8 *) out_buf;
|
||||||
|
|
||||||
|
int out_len = 0;
|
||||||
|
|
||||||
|
u8 *plain_ptr = (u8 *) plain_buf;
|
||||||
|
|
||||||
|
int plain_pos = 0;
|
||||||
|
|
||||||
|
while (plain_pos < plain_len)
|
||||||
|
{
|
||||||
|
u32 src0 = 0;
|
||||||
|
u32 src1 = 0;
|
||||||
|
u32 src2 = 0;
|
||||||
|
u32 src3 = 0;
|
||||||
|
|
||||||
|
const int rem = MIN (plain_len - plain_pos, 4);
|
||||||
|
|
||||||
|
if (rem > 0) src0 = plain_ptr[plain_pos + 0];
|
||||||
|
if (rem > 1) src1 = plain_ptr[plain_pos + 1];
|
||||||
|
if (rem > 2) src2 = plain_ptr[plain_pos + 2];
|
||||||
|
if (rem > 3) src3 = plain_ptr[plain_pos + 3];
|
||||||
|
|
||||||
|
const u32 src = (src0 << 0)
|
||||||
|
| (src1 << 8)
|
||||||
|
| (src2 << 16)
|
||||||
|
| (src3 << 24);
|
||||||
|
|
||||||
|
int src_len;
|
||||||
|
|
||||||
|
for (src_len = rem; src_len > 0; src_len--)
|
||||||
|
{
|
||||||
|
const int idx = find_keyboard_layout_map (src, src_len, s_keyboard_layout_mapping, keyboard_layout_mapping_cnt);
|
||||||
|
|
||||||
|
if (idx == -1) continue;
|
||||||
|
|
||||||
|
u32 dst_char = s_keyboard_layout_mapping[idx].dst_char;
|
||||||
|
int dst_len = s_keyboard_layout_mapping[idx].dst_len;
|
||||||
|
|
||||||
|
switch (dst_len)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
||||||
|
out_ptr[out_len++] = (dst_char >> 24) & 0xff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
plain_pos += src_len;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not matched, keep original
|
||||||
|
|
||||||
|
if (src_len == 0)
|
||||||
|
{
|
||||||
|
out_ptr[out_len] = plain_ptr[plain_pos];
|
||||||
|
|
||||||
|
out_len++;
|
||||||
|
|
||||||
|
plain_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plain_buf[ 0] = out_buf[ 0];
|
||||||
|
plain_buf[ 1] = out_buf[ 1];
|
||||||
|
plain_buf[ 2] = out_buf[ 2];
|
||||||
|
plain_buf[ 3] = out_buf[ 3];
|
||||||
|
plain_buf[ 4] = out_buf[ 4];
|
||||||
|
plain_buf[ 5] = out_buf[ 5];
|
||||||
|
plain_buf[ 6] = out_buf[ 6];
|
||||||
|
plain_buf[ 7] = out_buf[ 7];
|
||||||
|
plain_buf[ 8] = out_buf[ 8];
|
||||||
|
plain_buf[ 9] = out_buf[ 9];
|
||||||
|
plain_buf[10] = out_buf[10];
|
||||||
|
plain_buf[11] = out_buf[11];
|
||||||
|
plain_buf[12] = out_buf[12];
|
||||||
|
plain_buf[13] = out_buf[13];
|
||||||
|
plain_buf[14] = out_buf[14];
|
||||||
|
plain_buf[15] = out_buf[15];
|
||||||
|
|
||||||
|
return out_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* output
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *strhashcategory (const u32 hash_category)
|
||||||
|
{
|
||||||
|
switch (hash_category)
|
||||||
|
{
|
||||||
|
case HASH_CATEGORY_UNDEFINED: return HASH_CATEGORY_UNDEFINED_STR;
|
||||||
|
case HASH_CATEGORY_RAW_HASH: return HASH_CATEGORY_RAW_HASH_STR;
|
||||||
|
case HASH_CATEGORY_RAW_HASH_SALTED: return HASH_CATEGORY_RAW_HASH_SALTED_STR;
|
||||||
|
case HASH_CATEGORY_RAW_HASH_AUTHENTICATED: return HASH_CATEGORY_RAW_HASH_AUTHENTICATED_STR;
|
||||||
|
case HASH_CATEGORY_RAW_CIPHER_KPA: return HASH_CATEGORY_RAW_CIPHER_KPA_STR;
|
||||||
|
case HASH_CATEGORY_GENERIC_KDF: return HASH_CATEGORY_GENERIC_KDF_STR;
|
||||||
|
case HASH_CATEGORY_NETWORK_PROTOCOL: return HASH_CATEGORY_NETWORK_PROTOCOL_STR;
|
||||||
|
case HASH_CATEGORY_FORUM_SOFTWARE: return HASH_CATEGORY_FORUM_SOFTWARE_STR;
|
||||||
|
case HASH_CATEGORY_DATABASE_SERVER: return HASH_CATEGORY_DATABASE_SERVER_STR;
|
||||||
|
case HASH_CATEGORY_NETWORK_SERVER: return HASH_CATEGORY_NETWORK_SERVER_STR;
|
||||||
|
case HASH_CATEGORY_RAW_CHECKSUM: return HASH_CATEGORY_RAW_CHECKSUM_STR;
|
||||||
|
case HASH_CATEGORY_OS: return HASH_CATEGORY_OS_STR;
|
||||||
|
case HASH_CATEGORY_EAS: return HASH_CATEGORY_EAS_STR;
|
||||||
|
case HASH_CATEGORY_ARCHIVE: return HASH_CATEGORY_ARCHIVE_STR;
|
||||||
|
case HASH_CATEGORY_BACKUP: return HASH_CATEGORY_BACKUP_STR;
|
||||||
|
case HASH_CATEGORY_FDE: return HASH_CATEGORY_FDE_STR;
|
||||||
|
case HASH_CATEGORY_DOCUMENTS: return HASH_CATEGORY_DOCUMENTS_STR;
|
||||||
|
case HASH_CATEGORY_PASSWORD_MANAGER: return HASH_CATEGORY_PASSWORD_MANAGER_STR;
|
||||||
|
case HASH_CATEGORY_OTP: return HASH_CATEGORY_OTP_STR;
|
||||||
|
case HASH_CATEGORY_PLAIN: return HASH_CATEGORY_PLAIN_STR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *stroptitype (const u32 opti_type)
|
||||||
|
{
|
||||||
|
switch (opti_type)
|
||||||
|
{
|
||||||
|
case OPTI_TYPE_OPTIMIZED_KERNEL: return OPTI_STR_OPTIMIZED_KERNEL;
|
||||||
|
case OPTI_TYPE_ZERO_BYTE: return OPTI_STR_ZERO_BYTE;
|
||||||
|
case OPTI_TYPE_PRECOMPUTE_INIT: return OPTI_STR_PRECOMPUTE_INIT;
|
||||||
|
case OPTI_TYPE_PRECOMPUTE_MERKLE: return OPTI_STR_PRECOMPUTE_MERKLE;
|
||||||
|
case OPTI_TYPE_PRECOMPUTE_PERMUT: return OPTI_STR_PRECOMPUTE_PERMUT;
|
||||||
|
case OPTI_TYPE_MEET_IN_MIDDLE: return OPTI_STR_MEET_IN_MIDDLE;
|
||||||
|
case OPTI_TYPE_EARLY_SKIP: return OPTI_STR_EARLY_SKIP;
|
||||||
|
case OPTI_TYPE_NOT_SALTED: return OPTI_STR_NOT_SALTED;
|
||||||
|
case OPTI_TYPE_NOT_ITERATED: return OPTI_STR_NOT_ITERATED;
|
||||||
|
case OPTI_TYPE_PREPENDED_SALT: return OPTI_STR_PREPENDED_SALT;
|
||||||
|
case OPTI_TYPE_APPENDED_SALT: return OPTI_STR_APPENDED_SALT;
|
||||||
|
case OPTI_TYPE_SINGLE_HASH: return OPTI_STR_SINGLE_HASH;
|
||||||
|
case OPTI_TYPE_SINGLE_SALT: return OPTI_STR_SINGLE_SALT;
|
||||||
|
case OPTI_TYPE_BRUTE_FORCE: return OPTI_STR_BRUTE_FORCE;
|
||||||
|
case OPTI_TYPE_RAW_HASH: return OPTI_STR_RAW_HASH;
|
||||||
|
case OPTI_TYPE_SLOW_HASH_SIMD_INIT: return OPTI_STR_SLOW_HASH_SIMD_INIT;
|
||||||
|
case OPTI_TYPE_SLOW_HASH_SIMD_LOOP: return OPTI_STR_SLOW_HASH_SIMD_LOOP;
|
||||||
|
case OPTI_TYPE_SLOW_HASH_SIMD_COMP: return OPTI_STR_SLOW_HASH_SIMD_COMP;
|
||||||
|
case OPTI_TYPE_USES_BITS_8: return OPTI_STR_USES_BITS_8;
|
||||||
|
case OPTI_TYPE_USES_BITS_16: return OPTI_STR_USES_BITS_16;
|
||||||
|
case OPTI_TYPE_USES_BITS_32: return OPTI_STR_USES_BITS_32;
|
||||||
|
case OPTI_TYPE_USES_BITS_64: return OPTI_STR_USES_BITS_64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parsing
|
||||||
|
*/
|
||||||
|
|
||||||
static bool parse_and_store_generic_salt (u8 *out_buf, int *out_len, const u8 *in_buf, const int in_len, MAYBE_UNUSED hashconfig_t *hashconfig)
|
static bool parse_and_store_generic_salt (u8 *out_buf, int *out_len, const u8 *in_buf, const int in_len, MAYBE_UNUSED hashconfig_t *hashconfig)
|
||||||
{
|
{
|
||||||
u32 tmp_u32[(64 * 2) + 1] = { 0 };
|
u32 tmp_u32[(64 * 2) + 1] = { 0 };
|
||||||
@ -275,70 +462,6 @@ static bool parse_and_store_generic_salt (u8 *out_buf, int *out_len, const u8 *i
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* output
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *strhashcategory (const u32 hash_category)
|
|
||||||
{
|
|
||||||
switch (hash_category)
|
|
||||||
{
|
|
||||||
case HASH_CATEGORY_UNDEFINED: return HASH_CATEGORY_UNDEFINED_STR;
|
|
||||||
case HASH_CATEGORY_RAW_HASH: return HASH_CATEGORY_RAW_HASH_STR;
|
|
||||||
case HASH_CATEGORY_RAW_HASH_SALTED: return HASH_CATEGORY_RAW_HASH_SALTED_STR;
|
|
||||||
case HASH_CATEGORY_RAW_HASH_AUTHENTICATED: return HASH_CATEGORY_RAW_HASH_AUTHENTICATED_STR;
|
|
||||||
case HASH_CATEGORY_RAW_CIPHER_KPA: return HASH_CATEGORY_RAW_CIPHER_KPA_STR;
|
|
||||||
case HASH_CATEGORY_GENERIC_KDF: return HASH_CATEGORY_GENERIC_KDF_STR;
|
|
||||||
case HASH_CATEGORY_NETWORK_PROTOCOL: return HASH_CATEGORY_NETWORK_PROTOCOL_STR;
|
|
||||||
case HASH_CATEGORY_FORUM_SOFTWARE: return HASH_CATEGORY_FORUM_SOFTWARE_STR;
|
|
||||||
case HASH_CATEGORY_DATABASE_SERVER: return HASH_CATEGORY_DATABASE_SERVER_STR;
|
|
||||||
case HASH_CATEGORY_NETWORK_SERVER: return HASH_CATEGORY_NETWORK_SERVER_STR;
|
|
||||||
case HASH_CATEGORY_RAW_CHECKSUM: return HASH_CATEGORY_RAW_CHECKSUM_STR;
|
|
||||||
case HASH_CATEGORY_OS: return HASH_CATEGORY_OS_STR;
|
|
||||||
case HASH_CATEGORY_EAS: return HASH_CATEGORY_EAS_STR;
|
|
||||||
case HASH_CATEGORY_ARCHIVE: return HASH_CATEGORY_ARCHIVE_STR;
|
|
||||||
case HASH_CATEGORY_BACKUP: return HASH_CATEGORY_BACKUP_STR;
|
|
||||||
case HASH_CATEGORY_FDE: return HASH_CATEGORY_FDE_STR;
|
|
||||||
case HASH_CATEGORY_DOCUMENTS: return HASH_CATEGORY_DOCUMENTS_STR;
|
|
||||||
case HASH_CATEGORY_PASSWORD_MANAGER: return HASH_CATEGORY_PASSWORD_MANAGER_STR;
|
|
||||||
case HASH_CATEGORY_OTP: return HASH_CATEGORY_OTP_STR;
|
|
||||||
case HASH_CATEGORY_PLAIN: return HASH_CATEGORY_PLAIN_STR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *stroptitype (const u32 opti_type)
|
|
||||||
{
|
|
||||||
switch (opti_type)
|
|
||||||
{
|
|
||||||
case OPTI_TYPE_OPTIMIZED_KERNEL: return OPTI_STR_OPTIMIZED_KERNEL;
|
|
||||||
case OPTI_TYPE_ZERO_BYTE: return OPTI_STR_ZERO_BYTE;
|
|
||||||
case OPTI_TYPE_PRECOMPUTE_INIT: return OPTI_STR_PRECOMPUTE_INIT;
|
|
||||||
case OPTI_TYPE_PRECOMPUTE_MERKLE: return OPTI_STR_PRECOMPUTE_MERKLE;
|
|
||||||
case OPTI_TYPE_PRECOMPUTE_PERMUT: return OPTI_STR_PRECOMPUTE_PERMUT;
|
|
||||||
case OPTI_TYPE_MEET_IN_MIDDLE: return OPTI_STR_MEET_IN_MIDDLE;
|
|
||||||
case OPTI_TYPE_EARLY_SKIP: return OPTI_STR_EARLY_SKIP;
|
|
||||||
case OPTI_TYPE_NOT_SALTED: return OPTI_STR_NOT_SALTED;
|
|
||||||
case OPTI_TYPE_NOT_ITERATED: return OPTI_STR_NOT_ITERATED;
|
|
||||||
case OPTI_TYPE_PREPENDED_SALT: return OPTI_STR_PREPENDED_SALT;
|
|
||||||
case OPTI_TYPE_APPENDED_SALT: return OPTI_STR_APPENDED_SALT;
|
|
||||||
case OPTI_TYPE_SINGLE_HASH: return OPTI_STR_SINGLE_HASH;
|
|
||||||
case OPTI_TYPE_SINGLE_SALT: return OPTI_STR_SINGLE_SALT;
|
|
||||||
case OPTI_TYPE_BRUTE_FORCE: return OPTI_STR_BRUTE_FORCE;
|
|
||||||
case OPTI_TYPE_RAW_HASH: return OPTI_STR_RAW_HASH;
|
|
||||||
case OPTI_TYPE_SLOW_HASH_SIMD_INIT: return OPTI_STR_SLOW_HASH_SIMD_INIT;
|
|
||||||
case OPTI_TYPE_SLOW_HASH_SIMD_LOOP: return OPTI_STR_SLOW_HASH_SIMD_LOOP;
|
|
||||||
case OPTI_TYPE_SLOW_HASH_SIMD_COMP: return OPTI_STR_SLOW_HASH_SIMD_COMP;
|
|
||||||
case OPTI_TYPE_USES_BITS_8: return OPTI_STR_USES_BITS_8;
|
|
||||||
case OPTI_TYPE_USES_BITS_16: return OPTI_STR_USES_BITS_16;
|
|
||||||
case OPTI_TYPE_USES_BITS_32: return OPTI_STR_USES_BITS_32;
|
|
||||||
case OPTI_TYPE_USES_BITS_64: return OPTI_STR_USES_BITS_64;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ascii_digest (const hashconfig_t *hashconfig, const hashes_t *hashes, const module_ctx_t *module_ctx, char *out_buf, const int out_size, const u32 salt_pos, const u32 digest_pos)
|
int ascii_digest (const hashconfig_t *hashconfig, const hashes_t *hashes, const module_ctx_t *module_ctx, char *out_buf, const int out_size, const u32 salt_pos, const u32 digest_pos)
|
||||||
{
|
{
|
||||||
void *digests_buf = hashes->digests_buf;
|
void *digests_buf = hashes->digests_buf;
|
||||||
@ -1375,417 +1498,9 @@ bool default_potfile_disable (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE
|
|||||||
return potfile_disable;
|
return potfile_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool default_unstable_warning (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra)
|
bool default_unstable_warning (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 unstable_warning = false;
|
const bool unstable_warning = false;
|
||||||
|
|
||||||
return unstable_warning;
|
return unstable_warning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// migrate
|
|
||||||
|
|
||||||
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 luks_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig, const int keyslot_idx)
|
|
||||||
{
|
|
||||||
u32 *digest = (u32 *) hash_buf->digest;
|
|
||||||
|
|
||||||
salt_t *salt = hash_buf->salt;
|
|
||||||
|
|
||||||
luks_t *luks = (luks_t *) hash_buf->esalt;
|
|
||||||
|
|
||||||
if (input_len == 0) return (PARSER_HASH_LENGTH);
|
|
||||||
|
|
||||||
FILE *fp = fopen ((const char *) input_buf, "rb");
|
|
||||||
|
|
||||||
if (fp == NULL) return (PARSER_HASH_FILE);
|
|
||||||
|
|
||||||
struct luks_phdr hdr;
|
|
||||||
|
|
||||||
const size_t nread = hc_fread (&hdr, sizeof (hdr), 1, fp);
|
|
||||||
|
|
||||||
if (nread != 1)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_FILE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy digest which we're not using ;)
|
|
||||||
|
|
||||||
u32 *mkDigest_ptr = (u32 *) hdr.mkDigest;
|
|
||||||
|
|
||||||
digest[0] = mkDigest_ptr[0];
|
|
||||||
digest[1] = mkDigest_ptr[1];
|
|
||||||
digest[2] = mkDigest_ptr[2];
|
|
||||||
digest[3] = mkDigest_ptr[3];
|
|
||||||
digest[4] = mkDigest_ptr[4];
|
|
||||||
digest[5] = 0;
|
|
||||||
digest[6] = 0;
|
|
||||||
digest[7] = 0;
|
|
||||||
|
|
||||||
// verify the content
|
|
||||||
|
|
||||||
char luks_magic[6] = LUKS_MAGIC;
|
|
||||||
|
|
||||||
if (memcmp (hdr.magic, luks_magic, LUKS_MAGIC_L) != 0)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_MAGIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byte_swap_16 (hdr.version) != 1)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (hdr.cipherName, "aes") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_type = HC_LUKS_CIPHER_TYPE_AES;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherName, "serpent") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_type = HC_LUKS_CIPHER_TYPE_SERPENT;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherName, "twofish") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_type = HC_LUKS_CIPHER_TYPE_TWOFISH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_CIPHER_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (hdr.cipherMode, "cbc-essiv:sha256") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_ESSIV;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherMode, "cbc-plain") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_PLAIN;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherMode, "cbc-plain64") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_PLAIN;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherMode, "xts-plain") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_mode = HC_LUKS_CIPHER_MODE_XTS_PLAIN;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.cipherMode, "xts-plain64") == 0)
|
|
||||||
{
|
|
||||||
luks->cipher_mode = HC_LUKS_CIPHER_MODE_XTS_PLAIN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_CIPHER_MODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp (hdr.hashSpec, "sha1") == 0)
|
|
||||||
{
|
|
||||||
luks->hash_type = HC_LUKS_HASH_TYPE_SHA1;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.hashSpec, "sha256") == 0)
|
|
||||||
{
|
|
||||||
luks->hash_type = HC_LUKS_HASH_TYPE_SHA256;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.hashSpec, "sha512") == 0)
|
|
||||||
{
|
|
||||||
luks->hash_type = HC_LUKS_HASH_TYPE_SHA512;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.hashSpec, "ripemd160") == 0)
|
|
||||||
{
|
|
||||||
luks->hash_type = HC_LUKS_HASH_TYPE_RIPEMD160;
|
|
||||||
}
|
|
||||||
else if (strcmp (hdr.hashSpec, "whirlpool") == 0)
|
|
||||||
{
|
|
||||||
luks->hash_type = HC_LUKS_HASH_TYPE_WHIRLPOOL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_HASH_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 keyBytes = byte_swap_32 (hdr.keyBytes);
|
|
||||||
|
|
||||||
if (keyBytes == 16)
|
|
||||||
{
|
|
||||||
luks->key_size = HC_LUKS_KEY_SIZE_128;
|
|
||||||
}
|
|
||||||
else if (keyBytes == 32)
|
|
||||||
{
|
|
||||||
luks->key_size = HC_LUKS_KEY_SIZE_256;
|
|
||||||
}
|
|
||||||
else if (keyBytes == 64)
|
|
||||||
{
|
|
||||||
luks->key_size = HC_LUKS_KEY_SIZE_512;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_KEY_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the correct kernel based on hash and cipher
|
|
||||||
|
|
||||||
// we need to do this kind of check, otherwise an eventual matching hash from the potfile overwrites the kern_type with an eventual invalid one
|
|
||||||
|
|
||||||
if (hashconfig->kern_type == (u32) -1)
|
|
||||||
{
|
|
||||||
if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_AES;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_SERPENT;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_TWOFISH;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_AES;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_SERPENT;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_TWOFISH;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_AES;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_SERPENT;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_TWOFISH;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_AES;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_SERPENT;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_TWOFISH;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_AES;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_SERPENT;
|
|
||||||
}
|
|
||||||
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_HASH_CIPHER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
|
||||||
{
|
|
||||||
// OK
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_HASH_CIPHER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify the selected keyslot informations
|
|
||||||
|
|
||||||
const u32 active = byte_swap_32 (hdr.keyblock[keyslot_idx].active);
|
|
||||||
const u32 stripes = byte_swap_32 (hdr.keyblock[keyslot_idx].stripes);
|
|
||||||
|
|
||||||
if (active != LUKS_KEY_ENABLED)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_KEY_DISABLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stripes != LUKS_STRIPES)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_KEY_STRIPES);
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure the salt (not esalt)
|
|
||||||
|
|
||||||
u32 *passwordSalt_ptr = (u32 *) hdr.keyblock[keyslot_idx].passwordSalt;
|
|
||||||
|
|
||||||
salt->salt_buf[0] = passwordSalt_ptr[0];
|
|
||||||
salt->salt_buf[1] = passwordSalt_ptr[1];
|
|
||||||
salt->salt_buf[2] = passwordSalt_ptr[2];
|
|
||||||
salt->salt_buf[3] = passwordSalt_ptr[3];
|
|
||||||
salt->salt_buf[4] = passwordSalt_ptr[4];
|
|
||||||
salt->salt_buf[5] = passwordSalt_ptr[5];
|
|
||||||
salt->salt_buf[6] = passwordSalt_ptr[6];
|
|
||||||
salt->salt_buf[7] = passwordSalt_ptr[7];
|
|
||||||
|
|
||||||
salt->salt_len = LUKS_SALTSIZE;
|
|
||||||
|
|
||||||
const u32 passwordIterations = byte_swap_32 (hdr.keyblock[keyslot_idx].passwordIterations);
|
|
||||||
|
|
||||||
salt->salt_iter = passwordIterations - 1;
|
|
||||||
|
|
||||||
// Load AF data for this keyslot into esalt
|
|
||||||
|
|
||||||
const u32 keyMaterialOffset = byte_swap_32 (hdr.keyblock[keyslot_idx].keyMaterialOffset);
|
|
||||||
|
|
||||||
const int rc_seek1 = fseeko (fp, keyMaterialOffset * 512, SEEK_SET);
|
|
||||||
|
|
||||||
if (rc_seek1 == -1)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_FILE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t nread2 = hc_fread (luks->af_src_buf, keyBytes, stripes, fp);
|
|
||||||
|
|
||||||
if (nread2 != stripes)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_FILE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// finally, copy some encrypted payload data for entropy check
|
|
||||||
|
|
||||||
const u32 payloadOffset = byte_swap_32 (hdr.payloadOffset);
|
|
||||||
|
|
||||||
const int rc_seek2 = fseeko (fp, payloadOffset * 512, SEEK_SET);
|
|
||||||
|
|
||||||
if (rc_seek2 == -1)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_FILE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t nread3 = hc_fread (luks->ct_buf, sizeof (u32), 128, fp);
|
|
||||||
|
|
||||||
if (nread3 != 128)
|
|
||||||
{
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_LUKS_FILE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// that should be it, close the fp
|
|
||||||
|
|
||||||
fclose (fp);
|
|
||||||
|
|
||||||
return (PARSER_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -2697,6 +2697,392 @@ static void drupal7_encode (const u8 digest[64], u8 buf[43])
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int luks_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig, const int keyslot_idx)
|
||||||
|
{
|
||||||
|
u32 *digest = (u32 *) hash_buf->digest;
|
||||||
|
|
||||||
|
salt_t *salt = hash_buf->salt;
|
||||||
|
|
||||||
|
luks_t *luks = (luks_t *) hash_buf->esalt;
|
||||||
|
|
||||||
|
if (input_len == 0) return (PARSER_HASH_LENGTH);
|
||||||
|
|
||||||
|
FILE *fp = fopen ((const char *) input_buf, "rb");
|
||||||
|
|
||||||
|
if (fp == NULL) return (PARSER_HASH_FILE);
|
||||||
|
|
||||||
|
struct luks_phdr hdr;
|
||||||
|
|
||||||
|
const size_t nread = hc_fread (&hdr, sizeof (hdr), 1, fp);
|
||||||
|
|
||||||
|
if (nread != 1)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_FILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy digest which we're not using ;)
|
||||||
|
|
||||||
|
u32 *mkDigest_ptr = (u32 *) hdr.mkDigest;
|
||||||
|
|
||||||
|
digest[0] = mkDigest_ptr[0];
|
||||||
|
digest[1] = mkDigest_ptr[1];
|
||||||
|
digest[2] = mkDigest_ptr[2];
|
||||||
|
digest[3] = mkDigest_ptr[3];
|
||||||
|
digest[4] = mkDigest_ptr[4];
|
||||||
|
digest[5] = 0;
|
||||||
|
digest[6] = 0;
|
||||||
|
digest[7] = 0;
|
||||||
|
|
||||||
|
// verify the content
|
||||||
|
|
||||||
|
char luks_magic[6] = LUKS_MAGIC;
|
||||||
|
|
||||||
|
if (memcmp (hdr.magic, luks_magic, LUKS_MAGIC_L) != 0)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byte_swap_16 (hdr.version) != 1)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (hdr.cipherName, "aes") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_type = HC_LUKS_CIPHER_TYPE_AES;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherName, "serpent") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_type = HC_LUKS_CIPHER_TYPE_SERPENT;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherName, "twofish") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_type = HC_LUKS_CIPHER_TYPE_TWOFISH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_CIPHER_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (hdr.cipherMode, "cbc-essiv:sha256") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_ESSIV;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherMode, "cbc-plain") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_PLAIN;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherMode, "cbc-plain64") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_mode = HC_LUKS_CIPHER_MODE_CBC_PLAIN;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherMode, "xts-plain") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_mode = HC_LUKS_CIPHER_MODE_XTS_PLAIN;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.cipherMode, "xts-plain64") == 0)
|
||||||
|
{
|
||||||
|
luks->cipher_mode = HC_LUKS_CIPHER_MODE_XTS_PLAIN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_CIPHER_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (hdr.hashSpec, "sha1") == 0)
|
||||||
|
{
|
||||||
|
luks->hash_type = HC_LUKS_HASH_TYPE_SHA1;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.hashSpec, "sha256") == 0)
|
||||||
|
{
|
||||||
|
luks->hash_type = HC_LUKS_HASH_TYPE_SHA256;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.hashSpec, "sha512") == 0)
|
||||||
|
{
|
||||||
|
luks->hash_type = HC_LUKS_HASH_TYPE_SHA512;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.hashSpec, "ripemd160") == 0)
|
||||||
|
{
|
||||||
|
luks->hash_type = HC_LUKS_HASH_TYPE_RIPEMD160;
|
||||||
|
}
|
||||||
|
else if (strcmp (hdr.hashSpec, "whirlpool") == 0)
|
||||||
|
{
|
||||||
|
luks->hash_type = HC_LUKS_HASH_TYPE_WHIRLPOOL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_HASH_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 keyBytes = byte_swap_32 (hdr.keyBytes);
|
||||||
|
|
||||||
|
if (keyBytes == 16)
|
||||||
|
{
|
||||||
|
luks->key_size = HC_LUKS_KEY_SIZE_128;
|
||||||
|
}
|
||||||
|
else if (keyBytes == 32)
|
||||||
|
{
|
||||||
|
luks->key_size = HC_LUKS_KEY_SIZE_256;
|
||||||
|
}
|
||||||
|
else if (keyBytes == 64)
|
||||||
|
{
|
||||||
|
luks->key_size = HC_LUKS_KEY_SIZE_512;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_KEY_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the correct kernel based on hash and cipher
|
||||||
|
|
||||||
|
// we need to do this kind of check, otherwise an eventual matching hash from the potfile overwrites the kern_type with an eventual invalid one
|
||||||
|
|
||||||
|
if (hashconfig->kern_type == (u32) -1)
|
||||||
|
{
|
||||||
|
if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_AES;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_SERPENT;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA1_TWOFISH;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_AES;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_SERPENT;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA256_TWOFISH;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_AES;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_SERPENT;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_SHA512_TWOFISH;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_AES;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_SERPENT;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_RIPEMD160_TWOFISH;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_AES;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_SERPENT;
|
||||||
|
}
|
||||||
|
else if ((luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
hashconfig->kern_type = KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_HASH_CIPHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA1_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA1) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA256_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA256) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_SHA512_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_SHA512) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_RIPEMD160_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_RIPEMD160) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_AES) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_AES))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_SERPENT) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_SERPENT))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else if ((hashconfig->kern_type == KERN_TYPE_LUKS_WHIRLPOOL_TWOFISH) && (luks->hash_type == HC_LUKS_HASH_TYPE_WHIRLPOOL) && (luks->cipher_type == HC_LUKS_CIPHER_TYPE_TWOFISH))
|
||||||
|
{
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_HASH_CIPHER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify the selected keyslot informations
|
||||||
|
|
||||||
|
const u32 active = byte_swap_32 (hdr.keyblock[keyslot_idx].active);
|
||||||
|
const u32 stripes = byte_swap_32 (hdr.keyblock[keyslot_idx].stripes);
|
||||||
|
|
||||||
|
if (active != LUKS_KEY_ENABLED)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_KEY_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stripes != LUKS_STRIPES)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_KEY_STRIPES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure the salt (not esalt)
|
||||||
|
|
||||||
|
u32 *passwordSalt_ptr = (u32 *) hdr.keyblock[keyslot_idx].passwordSalt;
|
||||||
|
|
||||||
|
salt->salt_buf[0] = passwordSalt_ptr[0];
|
||||||
|
salt->salt_buf[1] = passwordSalt_ptr[1];
|
||||||
|
salt->salt_buf[2] = passwordSalt_ptr[2];
|
||||||
|
salt->salt_buf[3] = passwordSalt_ptr[3];
|
||||||
|
salt->salt_buf[4] = passwordSalt_ptr[4];
|
||||||
|
salt->salt_buf[5] = passwordSalt_ptr[5];
|
||||||
|
salt->salt_buf[6] = passwordSalt_ptr[6];
|
||||||
|
salt->salt_buf[7] = passwordSalt_ptr[7];
|
||||||
|
|
||||||
|
salt->salt_len = LUKS_SALTSIZE;
|
||||||
|
|
||||||
|
const u32 passwordIterations = byte_swap_32 (hdr.keyblock[keyslot_idx].passwordIterations);
|
||||||
|
|
||||||
|
salt->salt_iter = passwordIterations - 1;
|
||||||
|
|
||||||
|
// Load AF data for this keyslot into esalt
|
||||||
|
|
||||||
|
const u32 keyMaterialOffset = byte_swap_32 (hdr.keyblock[keyslot_idx].keyMaterialOffset);
|
||||||
|
|
||||||
|
const int rc_seek1 = fseeko (fp, keyMaterialOffset * 512, SEEK_SET);
|
||||||
|
|
||||||
|
if (rc_seek1 == -1)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_FILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t nread2 = hc_fread (luks->af_src_buf, keyBytes, stripes, fp);
|
||||||
|
|
||||||
|
if (nread2 != stripes)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_FILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, copy some encrypted payload data for entropy check
|
||||||
|
|
||||||
|
const u32 payloadOffset = byte_swap_32 (hdr.payloadOffset);
|
||||||
|
|
||||||
|
const int rc_seek2 = fseeko (fp, payloadOffset * 512, SEEK_SET);
|
||||||
|
|
||||||
|
if (rc_seek2 == -1)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_FILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t nread3 = hc_fread (luks->ct_buf, sizeof (u32), 128, fp);
|
||||||
|
|
||||||
|
if (nread3 != 128)
|
||||||
|
{
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_LUKS_FILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// that should be it, close the fp
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return (PARSER_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int bcrypt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig)
|
int bcrypt_parse_hash (u8 *input_buf, u32 input_len, hash_t *hash_buf, MAYBE_UNUSED hashconfig_t *hashconfig)
|
||||||
{
|
{
|
||||||
u32 *digest = (u32 *) hash_buf->digest;
|
u32 *digest = (u32 *) hash_buf->digest;
|
||||||
@ -28860,6 +29246,17 @@ bool potfile_keep_all_hashes
|
|||||||
|
|
||||||
int build_plain_postprocess (const u32 *src_buf, MAYBE_UNUSED const size_t src_sz, const int src_len, u32 *dst_buf, MAYBE_UNUSED const size_t dst_sz)
|
int build_plain_postprocess (const u32 *src_buf, MAYBE_UNUSED const size_t src_sz, const int src_len, u32 *dst_buf, MAYBE_UNUSED const size_t dst_sz)
|
||||||
{
|
{
|
||||||
|
// truecrypt and veracrypt boot only:
|
||||||
|
// we do some kernel internal substituations, so we need to do that here as well, if it cracks
|
||||||
|
|
||||||
|
if (hashconfig->opts_type & OPTS_TYPE_KEYBOARD_MAPPING)
|
||||||
|
{
|
||||||
|
tc_t *tc = (tc_t *) hashes->esalts_buf;
|
||||||
|
|
||||||
|
return execute_keyboard_layout_mapping (plain_buf, plain_len, tc->keyboard_layout_mapping_buf, tc->keyboard_layout_mapping_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TOTP should be base32 encoded
|
// TOTP should be base32 encoded
|
||||||
if (hashconfig->hash_mode == 18100)
|
if (hashconfig->hash_mode == 18100)
|
||||||
{
|
{
|
||||||
@ -29369,78 +29766,11 @@ int module_hash_init_selftest (MAYBE_UNUSED const hashconfig_t *hashconfig, hash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int module_hash_save_binary (MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const u32 salt_pos, MAYBE_UNUSED const u32 digest_pos, const char **buf)
|
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)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void to_hccapx_t (hashcat_ctx_t *hashcat_ctx, hccapx_t *hccapx, const u32 salt_pos, const u32 digest_pos);
|
|
||||||
|
|
||||||
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
|
if ((hashconfig->hash_mode == 2500) || (hashconfig->hash_mode == 2501))
|
||||||
{
|
{
|
||||||
@ -29450,5 +29780,403 @@ void to_hccapx_t (hashcat_ctx_t *hashcat_ctx, hccapx_t *hccapx, const u32 salt_p
|
|||||||
|
|
||||||
hc_fwrite (&hccapx, sizeof (hccapx_t), 1, fp);
|
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 ((user_options->hash_mode == 2500) || (user_options->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;
|
||||||
|
|
||||||
|
for (int keyslot_idx = 0; keyslot_idx < LUKS_NUMKEYS; keyslot_idx++)
|
||||||
|
{
|
||||||
|
parser_status = luks_parse_hash ((u8 *) hash_buf, (const int) hash_len, &hashes_buf[hashes_cnt], hashconfig, keyslot_idx);
|
||||||
|
|
||||||
|
if (parser_status != PARSER_OK)
|
||||||
|
{
|
||||||
|
if (parser_status != PARSER_LUKS_KEY_DISABLED) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashes_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashes_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int hashconfig_general_defaults (hashcat_ctx_t *hashcat_ctx)
|
||||||
|
{
|
||||||
|
hashconfig_t *hashconfig = hashcat_ctx->hashconfig;
|
||||||
|
user_options_t *user_options = hashcat_ctx->user_options;
|
||||||
|
|
||||||
|
// truecrypt and veracrypt only
|
||||||
|
if (((hashconfig->hash_mode >= 6200) && (hashconfig->hash_mode <= 6299))
|
||||||
|
|| ((hashconfig->hash_mode >= 13700) && (hashconfig->hash_mode == 13799)))
|
||||||
|
{
|
||||||
|
hashes_t *hashes = hashcat_ctx->hashes;
|
||||||
|
|
||||||
|
tc_t *tc = (tc_t *) hashes->esalts_buf;
|
||||||
|
|
||||||
|
char *optional_param1 = NULL;
|
||||||
|
|
||||||
|
if (user_options->truecrypt_keyfiles) optional_param1 = user_options->truecrypt_keyfiles;
|
||||||
|
if (user_options->veracrypt_keyfiles) optional_param1 = user_options->veracrypt_keyfiles;
|
||||||
|
|
||||||
|
if (optional_param1)
|
||||||
|
{
|
||||||
|
char *tcvc_keyfiles = optional_param1;
|
||||||
|
|
||||||
|
char *keyfiles = hcstrdup (tcvc_keyfiles);
|
||||||
|
|
||||||
|
if (keyfiles == NULL) return -1;
|
||||||
|
|
||||||
|
char *saveptr = NULL;
|
||||||
|
|
||||||
|
char *keyfile = strtok_r (keyfiles, ",", &saveptr);
|
||||||
|
|
||||||
|
if (keyfile == NULL)
|
||||||
|
{
|
||||||
|
free (keyfiles);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const int rc_crc32 = cpu_crc32 (hashcat_ctx, keyfile, (u8 *) tc->keyfile_buf);
|
||||||
|
|
||||||
|
if (rc_crc32 == -1)
|
||||||
|
{
|
||||||
|
free (keyfiles);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while ((keyfile = strtok_r ((char *) NULL, ",", &saveptr)) != NULL);
|
||||||
|
|
||||||
|
free (keyfiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// truecrypt and veracrypt boot only
|
||||||
|
if (hashconfig->opts_type & OPTS_TYPE_KEYBOARD_MAPPING)
|
||||||
|
{
|
||||||
|
if (user_options->keyboard_layout_mapping)
|
||||||
|
{
|
||||||
|
const bool rc = initialize_keyboard_layout_mapping (hashcat_ctx, user_options->keyboard_layout_mapping, tc->keyboard_layout_mapping_buf, &tc->keyboard_layout_mapping_cnt);
|
||||||
|
|
||||||
|
if (rc == false) return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// veracrypt only
|
||||||
|
if ((hashconfig->hash_mode >= 13700) && (hashconfig->hash_mode == 13799))
|
||||||
|
{
|
||||||
|
if (user_options->veracrypt_pim)
|
||||||
|
{
|
||||||
|
// we can access salt directly here because in VC it's always just one salt not many
|
||||||
|
|
||||||
|
hashes_t *hashes = hashcat_ctx->hashes;
|
||||||
|
|
||||||
|
salt_t *salts_buf = hashes->salts_buf;
|
||||||
|
|
||||||
|
salt_t *salt = &salts_buf[0];
|
||||||
|
|
||||||
|
switch (hashconfig->hash_mode)
|
||||||
|
{
|
||||||
|
case 13711: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13712: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13713: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13721: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13722: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13723: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13731: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13732: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13733: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13741: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13742: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13743: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13751: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13752: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13753: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13761: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13762: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13763: salt->salt_iter = user_options->veracrypt_pim * 2048;
|
||||||
|
break;
|
||||||
|
case 13771: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13772: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
case 13773: salt->salt_iter = 15000 + (user_options->veracrypt_pim * 1000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
salt->salt_iter -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
129
src/outfile.c
129
src/outfile.c
@ -19,125 +19,6 @@
|
|||||||
#include "outfile.h"
|
#include "outfile.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
|
|
||||||
static int find_keyboard_layout_map (const u32 search, const int search_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
|
||||||
{
|
|
||||||
for (int idx = 0; idx < keyboard_layout_mapping_cnt; idx++)
|
|
||||||
{
|
|
||||||
const u32 src_char = s_keyboard_layout_mapping[idx].src_char;
|
|
||||||
const int src_len = s_keyboard_layout_mapping[idx].src_len;
|
|
||||||
|
|
||||||
if (src_len == search_len)
|
|
||||||
{
|
|
||||||
const u32 mask = 0xffffffff >> ((4 - search_len) * 8);
|
|
||||||
|
|
||||||
if ((src_char & mask) == (search & mask)) return idx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int execute_keyboard_layout_mapping (u32 plain_buf[64], const int plain_len, keyboard_layout_mapping_t *s_keyboard_layout_mapping, const int keyboard_layout_mapping_cnt)
|
|
||||||
{
|
|
||||||
u32 out_buf[16] = { 0 };
|
|
||||||
|
|
||||||
u8 *out_ptr = (u8 *) out_buf;
|
|
||||||
|
|
||||||
int out_len = 0;
|
|
||||||
|
|
||||||
u8 *plain_ptr = (u8 *) plain_buf;
|
|
||||||
|
|
||||||
int plain_pos = 0;
|
|
||||||
|
|
||||||
while (plain_pos < plain_len)
|
|
||||||
{
|
|
||||||
u32 src0 = 0;
|
|
||||||
u32 src1 = 0;
|
|
||||||
u32 src2 = 0;
|
|
||||||
u32 src3 = 0;
|
|
||||||
|
|
||||||
const int rem = MIN (plain_len - plain_pos, 4);
|
|
||||||
|
|
||||||
if (rem > 0) src0 = plain_ptr[plain_pos + 0];
|
|
||||||
if (rem > 1) src1 = plain_ptr[plain_pos + 1];
|
|
||||||
if (rem > 2) src2 = plain_ptr[plain_pos + 2];
|
|
||||||
if (rem > 3) src3 = plain_ptr[plain_pos + 3];
|
|
||||||
|
|
||||||
const u32 src = (src0 << 0)
|
|
||||||
| (src1 << 8)
|
|
||||||
| (src2 << 16)
|
|
||||||
| (src3 << 24);
|
|
||||||
|
|
||||||
int src_len;
|
|
||||||
|
|
||||||
for (src_len = rem; src_len > 0; src_len--)
|
|
||||||
{
|
|
||||||
const int idx = find_keyboard_layout_map (src, src_len, s_keyboard_layout_mapping, keyboard_layout_mapping_cnt);
|
|
||||||
|
|
||||||
if (idx == -1) continue;
|
|
||||||
|
|
||||||
u32 dst_char = s_keyboard_layout_mapping[idx].dst_char;
|
|
||||||
int dst_len = s_keyboard_layout_mapping[idx].dst_len;
|
|
||||||
|
|
||||||
switch (dst_len)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
out_ptr[out_len++] = (dst_char >> 0) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 8) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 16) & 0xff;
|
|
||||||
out_ptr[out_len++] = (dst_char >> 24) & 0xff;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
plain_pos += src_len;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not matched, keep original
|
|
||||||
|
|
||||||
if (src_len == 0)
|
|
||||||
{
|
|
||||||
out_ptr[out_len] = plain_ptr[plain_pos];
|
|
||||||
|
|
||||||
out_len++;
|
|
||||||
|
|
||||||
plain_pos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plain_buf[ 0] = out_buf[ 0];
|
|
||||||
plain_buf[ 1] = out_buf[ 1];
|
|
||||||
plain_buf[ 2] = out_buf[ 2];
|
|
||||||
plain_buf[ 3] = out_buf[ 3];
|
|
||||||
plain_buf[ 4] = out_buf[ 4];
|
|
||||||
plain_buf[ 5] = out_buf[ 5];
|
|
||||||
plain_buf[ 6] = out_buf[ 6];
|
|
||||||
plain_buf[ 7] = out_buf[ 7];
|
|
||||||
plain_buf[ 8] = out_buf[ 8];
|
|
||||||
plain_buf[ 9] = out_buf[ 9];
|
|
||||||
plain_buf[10] = out_buf[10];
|
|
||||||
plain_buf[11] = out_buf[11];
|
|
||||||
plain_buf[12] = out_buf[12];
|
|
||||||
plain_buf[13] = out_buf[13];
|
|
||||||
plain_buf[14] = out_buf[14];
|
|
||||||
plain_buf[15] = out_buf[15];
|
|
||||||
|
|
||||||
return out_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int build_plain (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain, u32 *plain_buf, int *out_len)
|
int build_plain (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, plain_t *plain, u32 *plain_buf, int *out_len)
|
||||||
{
|
{
|
||||||
const combinator_ctx_t *combinator_ctx = hashcat_ctx->combinator_ctx;
|
const combinator_ctx_t *combinator_ctx = hashcat_ctx->combinator_ctx;
|
||||||
@ -361,16 +242,6 @@ int build_plain (hashcat_ctx_t *hashcat_ctx, hc_device_param_t *device_param, pl
|
|||||||
|
|
||||||
if (plain_len > pw_max) plain_len = MIN (plain_len, pw_max);
|
if (plain_len > pw_max) plain_len = MIN (plain_len, pw_max);
|
||||||
|
|
||||||
// truecrypt and veracrypt boot only:
|
|
||||||
// we do some kernel internal substituations, so we need to do that here as well, if it cracks
|
|
||||||
|
|
||||||
if (hashconfig->opts_type & OPTS_TYPE_KEYBOARD_MAPPING)
|
|
||||||
{
|
|
||||||
tc_t *tc = (tc_t *) hashes->esalts_buf;
|
|
||||||
|
|
||||||
plain_len = execute_keyboard_layout_mapping (plain_buf, plain_len, tc->keyboard_layout_mapping_buf, tc->keyboard_layout_mapping_cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
plain_ptr[plain_len] = 0;
|
plain_ptr[plain_len] = 0;
|
||||||
|
|
||||||
*out_len = plain_len;
|
*out_len = plain_len;
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
|
static const char MASKED_PLAIN[] = "[notfound]";
|
||||||
|
|
||||||
// get rid of this later
|
// get rid of this later
|
||||||
int sort_by_hash (const void *v1, const void *v2, void *v3);
|
int sort_by_hash (const void *v1, const void *v2, void *v3);
|
||||||
int sort_by_hash_no_salt (const void *v1, const void *v2, void *v3);
|
int sort_by_hash_no_salt (const void *v1, const void *v2, void *v3);
|
||||||
@ -703,9 +705,9 @@ int potfile_handle_show (hashcat_ctx_t *hashcat_ctx)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy (mixed_buf + mixed_len, LM_MASKED_PLAIN, strlen (LM_MASKED_PLAIN));
|
memcpy (mixed_buf + mixed_len, MASKED_PLAIN, strlen (MASKED_PLAIN));
|
||||||
|
|
||||||
mixed_len += strlen (LM_MASKED_PLAIN);
|
mixed_len += strlen (MASKED_PLAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash2)
|
if (hash2)
|
||||||
@ -718,9 +720,9 @@ int potfile_handle_show (hashcat_ctx_t *hashcat_ctx)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy (mixed_buf + mixed_len, LM_MASKED_PLAIN, strlen (LM_MASKED_PLAIN));
|
memcpy (mixed_buf + mixed_len, MASKED_PLAIN, strlen (MASKED_PLAIN));
|
||||||
|
|
||||||
mixed_len += strlen (LM_MASKED_PLAIN);
|
mixed_len += strlen (MASKED_PLAIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user