Веселые хеши. Реализуем технику API Hashing, чтобы обдурить антивирус - «Новости» » Самоучитель CSS
Меню
Наши новости
Учебник CSS

Невозможно отучить людей изучать самые ненужные предметы.

Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3

Надо знать обо всем понемножку, но все о немногом.

Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы

Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)

Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода

Самоучитель CSS

Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5

Новости

Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости

Справочник CSS

Справочник от А до Я
HTML, CSS, JavaScript

Афоризмы

Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы

Видео Уроки


Наш опрос



Наши новости

      
      
  • 24 марта 2016, 16:20
15-10-2023, 09:18
Веселые хеши. Реализуем технику API Hashing, чтобы обдурить антивирус - «Новости»
Рейтинг:
Категория: Новости

прош­лой статье я рас­смот­рел вари­анты сок­рытия IAT путем получе­ния адре­сов фун­кции и их вызова «нап­рямую» через LoadLibrary() и GetProcAddress(), но проб­лема в том, что сами стро­ки, содер­жащие име­на фун­кций, никак не спря­таны. Поэто­му любой ува­жающий себя анти­вирус­ный про­дукт все рав­но смо­жет понять, что мы задума­ли.
Веселые хеши. Реализуем технику API Hashing, чтобы обдурить антивирус - «Новости»
Ни­какой скрыт­ности
Всем понят­но, что вызыва­ется

Что­бы пре­дот­вра­тить это, доб­рые хакеры при­дума­ли тех­нику API Hashing, с которой сей­час и поз­накомим­ся.


Читайте также - Virtual private server (VPS) is a service that makes available a ready-to-use virtual server fully configured and managed by experts for use. The reason behind the high popularity of this service is the fact that not everyone today can afford to buy high-quality server hardware, which is quite expensive - vps usa.

Простейший API Hashing


Рань­ше мы получа­ли адрес нуж­ной фун­кции через кас­томный GetProcAddress(). Вот как это выг­лядит.


FARPROC myGetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
 PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
 PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + dosHeader->e_lfanew);
 PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hModule +
 ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
 DWORD* addressOfFunctions = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfFunctions);
 WORD* addressOfNameOrdinals = (WORD*)((BYTE*)hModule + exportDirectory->AddressOfNameOrdinals);
 DWORD* addressOfNames = (DWORD*)((BYTE*)hModule + exportDirectory->AddressOfNames);
 for (DWORD i = 0; i < exportDirectory->NumberOfNames; ++i) {
if (strcmp(lpProcName, (const char*)hModule + addressOfNames[i]) == 0) {
return (FARPROC)((BYTE*)hModule + addressOfFunctions[addressOfNameOrdinals[i]]);
}
 }
 return NULL;
}

API Hashing зак­люча­ется в том, что мы вмес­то име­ни фун­кции (lpProcName) будем переда­вать хеш от нее. Фак­тичес­ки изме­нит­ся лишь сле­дующая стро­ка.


if (strcmp(lpProcName, (const char*)hModule + addressOfNames[i]) == 0)

И ста­нет вот такой:


if (strcmp(lpProcName, HASH((const char*)hModule + addressOfNames[i])) == 0)

Ана­логич­ным обра­зом все про­исхо­дит и с GetModuleHandle().


Но что это вооб­ще за хеш, отку­да его взять? Хеш генери­рует­ся с помощью кон­крет­ного алго­рит­ма хеширо­вания, можешь выб­рать любой на свой вкус. При­веду нес­коль­ко при­меров.


 

Выбор алгоритма


Итак, берем алго­ритм Djb2. Это очень быс­трый алго­ритм хеширо­вания.


hash = ((hash << 5) + hash) + c


  • hash — текущее зна­чение хеша;


  • << — сдвиг впра­во;


  • c — текущее зна­чение сим­вола в стро­ке.


Вот фун­кция, которая поз­воля­ет хеширо­вать стро­ку.


#include <Windows.h>
#include <iostream>

#define INITIAL_HASH 3731 // Для рандомизации
#define INITIAL_SEED 7

// ASCII
DWORD HashStringDjb2A(_In_ PCHAR String)
{
 ULONG Hash = INITIAL_HASH;
 INT c;
 while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
 return Hash;
}

// Unicode
DWORD HashStringDjb2W(_In_ PWCHAR String)
{
 ULONG Hash = INITIAL_HASH;
 INT c;

 while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
 return Hash;
}

int main() {
 LPWSTR str = (LPWSTR)L"HelloWorld";
 std::cout << HashStringDjb2W(str);
 return 0;
}

Те­перь давай поп­робу­ем алго­ритм JenkinsOneAtATime32Bit. Он переби­рает сим­волы вход­ной стро­ки и пос­тепен­но обновля­ет хеш‑зна­чение в соот­ветс­твии с каж­дым получен­ным сим­волом.


hash += (hash << 10);hash ^= (hash 6);


  • hash — текущее зна­чение хеша;


  • c — текущее зна­чение сим­вола в стро­ке.


Код с фун­кци­ей.


#include <iostream>#define INITIAL_SEED
7// ASCIIUINT32 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;}// UnicodeUINT32 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;}int main() {
LPWSTR str = (LPWSTR)L"HelloWorld";
std::cout << HashStringJenkinsOneAtATime32BitW(str);
return 0;}

Не уто­мил­ся? Давай пос­мотрим еще один при­мер. В каком‑то про­екте, чуть ли не в Hell’s Gate, я встре­чал алго­ритм LoseLose. Он вычис­ляет хеш‑зна­чение вход­ной стро­ки, переби­рая каж­дый сим­вол в ней и сум­мируя зна­чения ASCII каж­дого сим­вола.


hash = 0;
hash += c; // Для каждого символа в строке

Хеш‑зна­чение, получен­ное в резуль­тате алго­рит­ма LoseLose, пред­став­ляет собой целое чис­ло, уни­каль­ное для вход­ной стро­ки. Но все рав­но есть веро­ятность кол­лизии. Что­бы решить эту проб­лему, фор­мула алго­рит­ма была обновле­на, как показа­но ниже.


hash = 0;
hash += c;
hash *= c + 2;

Вот при­мер фун­кции, которая генери­рует подоб­ный хеш.


#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 2

// ASCII
DWORD HashStringLoseLoseA(_In_ PCHAR String)
{
 ULONG Hash = 0;
 INT c;
 while (c = *String++) {
Hash += c;
Hash *= c + INITIAL_SEED;
 }
 return Hash;
}

// Unicode
DWORD HashStringLoseLoseW(_In_ PWCHAR String)
{
 ULONG Hash = 0;
 INT c;
 while (c = *String++) {
Hash += c;
Hash *= c + INITIAL_SEED;
 }
 return Hash;
}
int main() {
 LPWSTR str = (LPWSTR)L"HelloWorld";
 std::cout << HashStringLoseLoseW(str);
 return 0;
}

И, думаю, пос­ледний вари­ант — Rotr32().


#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 5
UINT32 HashStringRotr32SubA(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 )
}

INT HashStringRotr32A(_In_ LPCSTR String)
{
 INT Value = 0;
 for (INT Index = 0; Index < strlen(String); Index++)
Value = String[Index] + HashStringRotr32SubA(Value, 7);
 return Value;
}

UINT32 HashStringRotr32SubW(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 )
}

INT HashStringRotr32W(_In_ LPCWSTR String)
{
 INT Value = 0;
 for (INT Index = 0; Index < wcslen(String); Index++)
Value = String[Index] + HashStringRotr32SubW(Value, 7);
 return Value;
}

int main() {
 LPWSTR str = (LPWSTR)L"HelloWorld";
 std::cout << HashStringRotr32W(str);

 return 0;
}

Для API Hashing ты прос­то ини­циали­зиру­ешь стро­ку с име­нем фун­кции, а затем загоня­ешь в любой из опи­сан­ных выше алго­рит­мов. Пос­ле получе­ния хеша ты дол­жен добавить его в свою прог­рамму и, исполь­зуя кас­томный GetProcAddress(), искать адрес нуж­ной фун­кции.


Пе­рехо­дим к демонс­тра­ции.


 

Пример

Цитирование статьи, картинки - фото скриншот - Rambler News Service.
Иллюстрация к статье - Яндекс. Картинки.
Есть вопросы. Напишите нам.
Общие правила  поведения на сайте.

прош­лой статье я рас­смот­рел вари­анты сок­рытия IAT путем получе­ния адре­сов фун­кции и их вызова «нап­рямую» через LoadLibrary() и GetProcAddress(), но проб­лема в том, что сами стро­ки, содер­жащие име­на фун­кций, никак не спря­таны. Поэто­му любой ува­жающий себя анти­вирус­ный про­дукт все рав­но смо­жет понять, что мы задума­ли. Ни­какой скрыт­ности Всем понят­но, что вызыва­етсяЧто­бы пре­дот­вра­тить это, доб­рые хакеры при­дума­ли тех­нику API Hashing, с которой сей­час и поз­накомим­ся. Читайте также - Virtual private server (VPS) is a service that makes available a ready-to-use virtual server fully configured and managed by experts for use. The reason behind the high popularity of this service is the fact that not everyone today can afford to buy high-quality server hardware, which is quite expensive - vps usa. Простейший API Hashing Рань­ше мы получа­ли адрес нуж­ной фун­кции через кас­томный GetProcAddress(). Вот как это выг­лядит. FARPROC myGetProcAddress ( HMODULE hModule , LPCSTR lpProcName ) _
Просмотров: 407
Комментариев: 0:   15-10-2023, 09:18
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

 
Еще новости по теме:



Другие новости по теме: