Хеширование - это техника, используемая для создания фиксированного представления куска данных, называемого хеш-значением или хеш-кодом. Хеш-алгоритмы разработаны как односторонние функции, что означает, что вычислительно невозможно определить исходные входные данные, используя хеш-значение. Хеш-код обычно имеет более короткий размер и быстрее обрабатывается. При сравнении строк хеширование может использоваться для быстрого определения равенства двух строк, в сравнении с сравнением самих строк, особенно если строки длинные.
В контексте разработки вредоносных программ хеширование строк полезно для скрытия строк, используемых в реализации, так как строки могут использоваться как сигнатуры для обнаружения вредоносных бинарных файлов.
Хеширование строк
Давайте рассмотрим некоторые алгоритмы хеширования строк. Важно понимать, что результатом этих алгоритмов является число, выраженное в шестнадцатеричном формате, так как это более аккуратно и компактно.
В этой статье рассматриваются следующие алгоритмы хеширования строк:
Dbj2
JenkinsOneAtATime32Bit
LoseLose Rotr32
Существует гораздо больше алгоритмов хеширования строк, чем те, которые обсуждаются в этой сьтатье, и некоторые из них можно найти в репозитории
Рекомендую присмотреться к этому репозиторию, там очень много полезных модулей на С++ для разработки малвари и пентестинга.)
Dbj2
Dbj2 - это простой и быстрый алгоритм хеширования, в основном используемый для генерации хеш-значений для строк, но также применимый к другим типам данных. Он работает, итерируясь по символам во входной строке и используя каждый символ для обновления текущего хеш-значения согласно определенному алгоритму, который продемонстрирован в следующем фрагменте.
hash = ((hash << 5) + hash) + c
hash - это текущее хеш-значение, c - текущий символ во входной строке, и << - оператор битового сдвига влево.
Результирующее хеш-значение - это положительное целое число, уникальное для входной строки. Известно, что Djb2 производит хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация Djb2, представленная ниже, взята из репозитория VX-API на GitHub.
JenkinsOneAtATime32Bit
Алгоритм JenkinsOneAtATime32Bit работает, итерируясь по символам во входной строке и инкрементально обновляя текущее хеш-значение в соответствии с значением каждого символа. Алгоритм обновления хеш-значения продемонстрирован в следующем фрагменте.
hash += c; hash += (hash << 10); hash ^= (hash >> 6); hash - текущее хеш-значение, а c - текущий символ во входной строке.
Результирующее хеш-значение - это 32-битное целое число, уникальное для входной строки. Известно, что алгоритм JenkinsOneAtATime32Bit производит относительно хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация JenkinsOneAtATime32Bit, представленная ниже, взята из репозитория VX-API на GitHub.
Rotr32
Алгоритм хеширования строк Rotr32 использует итерируемые символы во входной строке для суммирования их ASCII-значений, а затем применяет битовое вращение к текущему значению хеша. Входное значение и счет (счет равен INITIAL_SEED) используются для выполнения сдвига вправо на это значение, затем применяется операция ИЛИ с исходным значением, сдвинутым влево на отрицание счета.
Результирующее хеш-значение - это 32-битное целое число, уникальное для входной строки. Известно, что Rotr32 производит относительно хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация Rotr32, представленная ниже, взята из репозитория VX-API на GitHub.
Стек строки
В языках программирования C/C++ строку можно представить как массив символов, разделяя символы друг от друга, что помогает избегать обнаружения на основе строк. Например, строку "hello world" можно представить следующим образом.
Поиск строки "hello world" с использованием бинарного редактора HxD ничего не вернет.
Однако стека строки недостаточно, чтобы скрыть строку от некоторых отладчиков и инструментов обратной разработки, так как они могут содержать плагины для их обнаружения.
Рекомендуется также шифровать строки, если они используется в программе.)
В контексте разработки вредоносных программ хеширование строк полезно для скрытия строк, используемых в реализации, так как строки могут использоваться как сигнатуры для обнаружения вредоносных бинарных файлов.
Хеширование строк
Давайте рассмотрим некоторые алгоритмы хеширования строк. Важно понимать, что результатом этих алгоритмов является число, выраженное в шестнадцатеричном формате, так как это более аккуратно и компактно.
В этой статье рассматриваются следующие алгоритмы хеширования строк:
Dbj2
JenkinsOneAtATime32Bit
LoseLose Rotr32
Существует гораздо больше алгоритмов хеширования строк, чем те, которые обсуждаются в этой сьтатье, и некоторые из них можно найти в репозитории
Вы должны зарегистрироваться, чтобы увидеть внешние ссылки
Рекомендую присмотреться к этому репозиторию, там очень много полезных модулей на С++ для разработки малвари и пентестинга.)
Dbj2
Dbj2 - это простой и быстрый алгоритм хеширования, в основном используемый для генерации хеш-значений для строк, но также применимый к другим типам данных. Он работает, итерируясь по символам во входной строке и используя каждый символ для обновления текущего хеш-значения согласно определенному алгоритму, который продемонстрирован в следующем фрагменте.
hash = ((hash << 5) + hash) + c
hash - это текущее хеш-значение, c - текущий символ во входной строке, и << - оператор битового сдвига влево.
Результирующее хеш-значение - это положительное целое число, уникальное для входной строки. Известно, что Djb2 производит хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация Djb2, представленная ниже, взята из репозитория VX-API на GitHub.
C:
#define INITIAL_HASH 3731 // добавлено для рандомизации хеширования
#define INITIAL_SEED 7 // генерация хешей Djb2 из строк ASCII
DWORD HashStringDjb2A(_In_ PCHAR String)
{
ULONG Hash = INITIAL_HASH;
INT c;
while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
// генерация хешей Djb2 из строк в широких символах
DWORD HashStringDjb2W(_In_ PWCHAR String)
{
ULONG Hash = INITIAL_HASH;
INT c;
while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
JenkinsOneAtATime32Bit
Алгоритм JenkinsOneAtATime32Bit работает, итерируясь по символам во входной строке и инкрементально обновляя текущее хеш-значение в соответствии с значением каждого символа. Алгоритм обновления хеш-значения продемонстрирован в следующем фрагменте.
hash += c; hash += (hash << 10); hash ^= (hash >> 6); hash - текущее хеш-значение, а c - текущий символ во входной строке.
Результирующее хеш-значение - это 32-битное целое число, уникальное для входной строки. Известно, что алгоритм JenkinsOneAtATime32Bit производит относительно хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация JenkinsOneAtATime32Bit, представленная ниже, взята из репозитория VX-API на GitHub.
C:
#define INITIAL_SEED 7 // Генерация хешей JenkinsOneAtATime32Bit из строк ASCII
UINT32 HashStringJenkinsOneAtATime32BitA(_In_ PCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenA(String);
while (Index != Length)
{
Hash += String[Index++];
Hash += Hash << INITIAL_SEED;
Hash ^= Hash >> 6;
}
Hash += Hash << 3;
Hash ^= Hash >> 11;
Hash += Hash << 15;
return Hash;
}
// Генерация хешей JenkinsOneAtATime32Bit из строк в широких символах
UINT32 HashStringJenkinsOneAtATime32BitW(_In_ PWCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenW(String);
while (Index != Length)
{
Hash += String[Index++];
Hash += Hash << INITIAL_SEED;
Hash ^= Hash >> 6;
}
Hash += Hash << 3;
Hash ^= Hash >> 11;
Hash += Hash << 15;
return Hash;
}
Rotr32
Алгоритм хеширования строк Rotr32 использует итерируемые символы во входной строке для суммирования их ASCII-значений, а затем применяет битовое вращение к текущему значению хеша. Входное значение и счет (счет равен INITIAL_SEED) используются для выполнения сдвига вправо на это значение, затем применяется операция ИЛИ с исходным значением, сдвинутым влево на отрицание счета.
Результирующее хеш-значение - это 32-битное целое число, уникальное для входной строки. Известно, что Rotr32 производит относительно хорошее распределение хеш-значений, что приводит к низкой вероятности коллизий между разными строками и их соответствующими хеш-значениями.
Реализация Rotr32, представленная ниже, взята из репозитория VX-API на GitHub.
C:
#define INITIAL_SEED 5 // Вспомогательная функция, которая применяет битовое вращение
UINT32 HashStringRotr32Sub(UINT32 Value, UINT Count)
{
DWORD Mask = (CHAR_BIT * sizeof(Value) - 1);
Count &= Mask;
#pragma warning( push )
#pragma warning( disable : 4146)
return (Value >> Count) | (Value << ((-Count) & Mask));
#pragma warning( pop )
}
// Генерация хешей Rotr32 из строк ASCII
INT HashStringRotr32A(_In_ PCHAR String)
{
INT Value = 0;
for (INT Index = 0; Index < lstrlenA(String); Index++)
Value = String[Index] + HashStringRotr32Sub(Value, INITIAL_SEED);
return Value;
}
// Генерация хешей Rotr32 из строк в широких символах
INT HashStringRotr32W(_In_ PWCHAR String)
{
INT Value = 0;
for (INT Index = 0; Index < lstrlenW(String); Index++)
Value = String[Index] + HashStringRotr32Sub(Value, INITIAL_SEED);
return Value;
}
Стек строки
В языках программирования C/C++ строку можно представить как массив символов, разделяя символы друг от друга, что помогает избегать обнаружения на основе строк. Например, строку "hello world" можно представить следующим образом.
C:
char string[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0' };
Поиск строки "hello world" с использованием бинарного редактора HxD ничего не вернет.
Однако стека строки недостаточно, чтобы скрыть строку от некоторых отладчиков и инструментов обратной разработки, так как они могут содержать плагины для их обнаружения.
Рекомендуется также шифровать строки, если они используется в программе.)