Категория > Новости > Молчи и скрывайся. Прячем 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 Перейти обратно к новости |