mirror of
https://github.com/hashcat/hashcat.git
synced 2025-07-20 21:48:19 +00:00

The original sort_by_src_len() function returned 0 even when a > b,
violating the C standard requirements for qsort() comparison functions.
Specifically, it broke antisymmetry and transitivity, which can result
in undefined behavior.
In some versions of glibc, this leads not only to incorrect sorting but
also potential memory corruption[1].
Fix the issue by returning -1 when a > b, restoring compliance with the
standard.
Link: https://www.qualys.com/2024/01/30/qsort.txt [1]
Fixes: 8eb2558a7
("Add -m 6211 module and moved some code around")
212 lines
5.2 KiB
C
212 lines
5.2 KiB
C
/**
|
|
* Author......: See docs/credits.txt
|
|
* License.....: MIT
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "types.h"
|
|
#include "memory.h"
|
|
#include "filehandling.h"
|
|
#include "shared.h"
|
|
#include "keyboard_layout.h"
|
|
|
|
static int sort_by_src_len (const void *p1, const void *p2)
|
|
{
|
|
const keyboard_layout_mapping_t *k1 = (const keyboard_layout_mapping_t *) p1;
|
|
const keyboard_layout_mapping_t *k2 = (const keyboard_layout_mapping_t *) p2;
|
|
|
|
if (k1->src_len < k2->src_len) return 1;
|
|
if (k1->src_len > k2->src_len) return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool initialize_keyboard_layout_mapping (const char *filename, keyboard_layout_mapping_t *keyboard_layout_mapping, int *keyboard_layout_mapping_cnt)
|
|
{
|
|
HCFILE fp;
|
|
|
|
if (hc_fopen (&fp, filename, "r") == false) return false;
|
|
|
|
char *line_buf = (char *) hcmalloc (HCBUFSIZ_LARGE);
|
|
|
|
int maps_cnt = 0;
|
|
|
|
while (!hc_feof (&fp))
|
|
{
|
|
const size_t line_len = fgetl (&fp, line_buf, HCBUFSIZ_LARGE);
|
|
|
|
if (line_len == 0) continue;
|
|
|
|
hc_token_t token;
|
|
|
|
token.token_cnt = 2;
|
|
|
|
token.len_min[0] = 1;
|
|
token.len_max[0] = 4;
|
|
token.sep[0] = 0x09;
|
|
token.attr[0] = TOKEN_ATTR_VERIFY_LENGTH;
|
|
|
|
token.len_min[1] = 0;
|
|
token.len_max[1] = 4;
|
|
token.sep[1] = 0x09;
|
|
token.attr[1] = TOKEN_ATTR_VERIFY_LENGTH;
|
|
|
|
if (input_tokenizer ((const u8 *) line_buf, (const int) line_len, &token) != PARSER_OK)
|
|
{
|
|
hc_fclose (&fp);
|
|
|
|
hcfree (line_buf);
|
|
|
|
return false;
|
|
}
|
|
|
|
memcpy (&keyboard_layout_mapping[maps_cnt].src_char, token.buf[0], token.len[0]);
|
|
memcpy (&keyboard_layout_mapping[maps_cnt].dst_char, token.buf[1], token.len[1]);
|
|
|
|
keyboard_layout_mapping[maps_cnt].src_len = token.len[0];
|
|
keyboard_layout_mapping[maps_cnt].dst_len = token.len[1];
|
|
|
|
if (maps_cnt == 256)
|
|
{
|
|
hc_fclose (&fp);
|
|
|
|
hcfree (line_buf);
|
|
|
|
return false;
|
|
}
|
|
|
|
maps_cnt++;
|
|
}
|
|
|
|
*keyboard_layout_mapping_cnt = maps_cnt;
|
|
|
|
hc_fclose (&fp);
|
|
|
|
hcfree (line_buf);
|
|
|
|
// we need to sort this by length to ensure the largest blocks come first in mapping
|
|
|
|
qsort (keyboard_layout_mapping, maps_cnt, sizeof (keyboard_layout_mapping_t), sort_by_src_len);
|
|
|
|
return true;
|
|
}
|
|
|
|
int find_keyboard_layout_map (const u32 search, const int search_len, const 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, const 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;
|
|
}
|