UGP/Visual Studio Projects/LibeayPatch/LibeayPatch/Hook.cpp

183 lines
6.1 KiB
C++

/*
* Shamelessly stolen from:
* https://github.com/adamhlt/IAT-Hooking/tree/main
*/
#include "Hook.h"
#include <TlHelp32.h>
#include <Psapi.h>
#include <Shlwapi.h>
/**
* Function who retrieve the base address of the main module of the current process.
* \return : the base address if it's successfull else nullptr
*/
LPVOID IAT::GetCurrentProcessModule()
{
char lpCurrentModuleName[MAX_PATH];
char lpImageName[MAX_PATH];
GetProcessImageFileNameA(GetCurrentProcess(), lpImageName, MAX_PATH);
MODULEENTRY32 ModuleList{};
ModuleList.dwSize = sizeof(ModuleList);
const HANDLE hProcList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0);
if (hProcList == INVALID_HANDLE_VALUE)
return nullptr;
if (!Module32First(hProcList, &ModuleList))
return nullptr;
wcstombs_s(nullptr, lpCurrentModuleName, ModuleList.szModule, MAX_PATH);
lpCurrentModuleName[MAX_PATH - 1] = '\0';
if (strstr(lpImageName, lpCurrentModuleName) != nullptr)
return ModuleList.hModule;
while (Module32Next(hProcList, &ModuleList))
{
wcstombs_s(nullptr, lpCurrentModuleName, ModuleList.szModule, MAX_PATH);
lpCurrentModuleName[MAX_PATH - 1] = '\0';
if (strstr(lpImageName, lpCurrentModuleName) != nullptr)
return ModuleList.hModule;
}
return nullptr;
}
/**
* Function to hook functions in the IAT of a specified module.
* \param lpModuleName : name of the module wich contains the function you want to hook.
* \param lpFunctionName : name of the function you want to hook.
* \param lpFunction : pointer of the new function.
* \param lpTargetModuleName : name of the module you want to target.
* \return : the pointer of the original function or nullptr if it failed.
*/
LPVOID IAT::Hook(LPCSTR lpModuleName, LPCSTR lpFunctionName, const LPVOID lpFunction, LPCSTR lpTargetModuleName)
{
const HANDLE hModule = GetModuleHandleA(lpTargetModuleName);
const auto lpImageDOSHeader = (PIMAGE_DOS_HEADER)(hModule);
if (lpImageDOSHeader == nullptr)
return nullptr;
const auto lpImageNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpImageDOSHeader + lpImageDOSHeader->e_lfanew);
const IMAGE_DATA_DIRECTORY ImportDataDirectory = lpImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
auto lpImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)hModule + ImportDataDirectory.VirtualAddress);
while (lpImageImportDescriptor->Characteristics != 0)
{
const auto lpCurrentModuleName = (LPSTR)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->Name);
if (_stricmp(lpCurrentModuleName, lpModuleName) != 0)
{
lpImageImportDescriptor++;
continue;
}
auto lpImageOrgThunkData = (PIMAGE_THUNK_DATA)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->OriginalFirstThunk);
auto lpImageThunkData = (PIMAGE_THUNK_DATA)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->FirstThunk);
while (lpImageOrgThunkData->u1.AddressOfData != 0)
{
const auto lpImportData = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)lpImageDOSHeader + lpImageOrgThunkData->u1.AddressOfData);
if (strcmp(lpFunctionName, (char*)lpImportData->Name) == 0)
{
DWORD dwJunk = 0;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(lpImageThunkData, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect))
return nullptr;
const auto lpOrgFunction = (LPVOID)lpImageThunkData->u1.Function;
#if defined _M_IX86
lpImageThunkData->u1.Function = (DWORD_PTR)lpFunction;
#elif defined _M_X64
lpImageThunkData->u1.Function = (DWORD_PTR)lpFunction;
#endif
if (VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwJunk))
return lpOrgFunction;
}
lpImageThunkData++;
lpImageOrgThunkData++;
}
lpImageImportDescriptor++;
}
return nullptr;
}
/**
* Function to hook functions in the IAT of a the main module of the process.
* \param lpModuleName : name of the module wich contains the function.
* \param lpFunctionName : name of the function you want to hook.
* \param lpFunction : pointer of the new function.
* \return : the pointer of the original function or nullptr if it failed.
*/
LPVOID IAT::Hook(LPCSTR lpModuleName, LPCSTR lpFunctionName, const LPVOID lpFunction)
{
const LPVOID hModule = GetCurrentProcessModule();
const auto lpImageDOSHeader = (PIMAGE_DOS_HEADER)(hModule);
if (lpImageDOSHeader == nullptr)
return nullptr;
const auto lpImageNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpImageDOSHeader + lpImageDOSHeader->e_lfanew);
const IMAGE_DATA_DIRECTORY ImportDataDirectory = lpImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
auto lpImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)hModule + ImportDataDirectory.VirtualAddress);
while (lpImageImportDescriptor->Characteristics != 0)
{
const auto lpCurrentModuleName = (LPSTR)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->Name);
if (_stricmp(lpCurrentModuleName, lpModuleName) != 0)
{
lpImageImportDescriptor++;
continue;
}
auto lpImageOrgThunkData = (PIMAGE_THUNK_DATA)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->OriginalFirstThunk);
auto lpImageThunkData = (PIMAGE_THUNK_DATA)((DWORD_PTR)lpImageDOSHeader + lpImageImportDescriptor->FirstThunk);
while (lpImageOrgThunkData->u1.AddressOfData != 0)
{
const auto lpImportData = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)lpImageDOSHeader + lpImageOrgThunkData->u1.AddressOfData);
if (strcmp(lpFunctionName, (char*)lpImportData->Name) == 0)
{
DWORD dwJunk = 0;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(lpImageThunkData, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
if (!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect))
return nullptr;
const auto lpOrgFunction = (LPVOID)lpImageThunkData->u1.Function;
#if defined _M_IX86
lpImageThunkData->u1.Function = (DWORD_PTR)lpFunction;
#elif defined _M_X64
lpImageThunkData->u1.Function = (DWORD_PTR)lpFunction;
#endif
if (VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &dwJunk))
return lpOrgFunction;
}
lpImageThunkData++;
lpImageOrgThunkData++;
}
lpImageImportDescriptor++;
}
return nullptr;
}