#include
#include
#include
#include
#include "ReloadLibrary.h"
template
bool writeMem(size_t address, T value)
{
*(T*)(address) = value;
return true;
}
template
T* pointMem(size_t address)
{
return (T*)address;
}
template
T readMem(size_t address)
{
return *(T*)address;
}
template
DWORD protectMem(size_t address, DWORD protection)
{
DWORD oldProtection;
VirtualProtect((LPVOID)address, sizeof(T), protection, &oldProtection);
return oldProtection;
}
bool getTemporaryFileName(std::wstring& output)
{
output = L"";
wchar_t tempPath[MAX_PATH + 1];
if (GetTempPath(sizeof(tempPath) / sizeof(wchar_t), &tempPath[0]) == 0)
return false;
wchar_t tempFile[MAX_PATH + 1];
if (GetTempFileName(tempPath, L"cln", 0, tempFile) == 0)
return false;
output = tempFile;
return true;
}
void copyFile(const std::wstring& source, const std::wstring& dest)
{
std::ifstream src(source, std::ios::binary);
std::ofstream dst(dest, std::ios::binary);
dst << src.rdbuf();
}
bool fileExists(const std::wstring& name) {
std::ifstream f(name.c_str());
return f.good();
}
HMODULE cloneLibrary(const char* libraryName)
{
// get the full path to the target module
auto targetMod = GetModuleHandleA(libraryName);
wchar_t targetName[MAX_PATH + 1];
if (GetModuleFileNameW(targetMod, targetName, sizeof(targetName) / sizeof(wchar_t)) == 0)
return nullptr;
// make a copy of it in the temp directory
std::wstring newdllname;
if (!getTemporaryFileName(newdllname))
return nullptr;
copyFile(targetName, newdllname);
if (!fileExists(newdllname))
return nullptr;
// load and ret
return LoadLibraryW(newdllname.c_str());
}
size_t ReloadLibrary(const char* libraryName, void* _mod)
{
auto mod = (size_t)(_mod);
if (!mod)
mod = (size_t)GetModuleHandle(NULL);
// locate PE
auto dosHeader = pointMem(mod);
if (dosHeader->e_magic != 0x5A4D)
return 0;
auto optionalHeader = pointMem(mod + dosHeader->e_lfanew + 24);
if (optionalHeader->Magic != 0x10B)
return 0;
if (optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0 ||
optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
return 0;
// scan imports for the target library and clone it
HMODULE clone = nullptr;
auto importDescriptor = pointMem(mod + optionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (importDescriptor->FirstThunk)
{
auto importLibraryName = pointMem(mod + importDescriptor->Name);
if (!_stricmp(libraryName, importLibraryName))
{
clone = cloneLibrary(libraryName);
break;
}
else
importDescriptor++;
}
if (!clone || !importDescriptor || !importDescriptor->FirstThunk)
return 0;
size_t n = 0;
size_t replaced = 0;
auto thunkData = pointMem(mod + importDescriptor->OriginalFirstThunk);
while (thunkData->u1.Function)
{
auto importFunctionName = pointMem(mod + thunkData->u1.AddressOfData + 2);
auto address = (size_t)pointMem(mod + importDescriptor->FirstThunk + (n * sizeof(DWORD)));
auto newFunction = GetProcAddress(clone, importFunctionName);
if (newFunction)
{
auto old = protectMem(address, PAGE_EXECUTE_READWRITE);
writeMem(address, newFunction);
protectMem(address, old);
replaced++;
}
n++;
thunkData++;
}
return replaced;
}