Категория > Новости > Молчи и скрывайся. Прячем IAT от антивируса - «Новости»
Молчи и скрывайся. Прячем IAT от антивируса - «Новости»7-09-2023, 00:02. Автор: Тамара |
Parsing PE File Headers with C++ (ired.team) PE (Portable Executable): На странных берегах («Хабрахабр») PE-формат. Часть 1 — Базовая информация (kaimi.io) Теперь нырнем в пучины интернета и поищем кастомную реализацию
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;
}
Функция достаточно проста: принимает базовый адрес загрузки библиотеки, а также имя функции, адрес которой надо получить. Работает так, как нам и нужно, — путем парсинга EAT. Помнишь, мы отключили CRT? Поэтому использование функции
int custom_strcmp(const char* str1, const char* str2) {
while (*str1 || *str2) {
if (*str1 < *str2) {
return -1;
}
else if (*str1 > *str2) {
return 1;
}
str1++;
str2++;
}
return 0;
}
Разобравшись, как и что делать, получаем следующий код.
#include <Windows.h>
#include <winternl.h>
typedef int (WINAPI* MessageBoxWFunc)(
HWND hWnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType
);
int custom_strcmp(const char* str1, const char* str2) {
while (*str1 || *str2) {
if (*str1 < *str2) {
return -1;
}
else if (*str1 > *str2) {
return 1;
}
str1++;
str2++;
}
return 0;
}
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 (custom_strcmp(lpProcName, (const char*)hModule + addressOfNames[i]) == 0) {
return (FARPROC)((BYTE*)hModule + addressOfFunctions[addressOfNameOrdinals[i]]);
}
}
return NULL;
}
int main() {
HMODULE user32Module = LoadLibrary(L"user32.dll");
MessageBoxWFunc MessageBoxWPtr = (MessageBoxWFunc)(myGetProcAddress(user32Module, "MessageBoxW"));
MessageBoxWPtr(NULL, L"HI", L"HI", MB_OK);
return 0;
}
Компилируем, запускаем. Видим, что остался лишь один импорт. Лишь один импорт Чем же заменить Последовательность вызовов при загрузке DLL Перейти обратно к новости |