Skip to content

Commit

Permalink
DllMain: hook games memset IAT to let us load in earlier
Browse files Browse the repository at this point in the history
  • Loading branch information
emoose committed Nov 7, 2023
1 parent 8eb7171 commit 3dc37b1
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 6 deletions.
34 changes: 28 additions & 6 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,7 +1110,7 @@ void Miscellaneous()
}
}

DWORD __stdcall Main(void*)
void Main()
{
Logging();
ReadConfig();
Expand All @@ -1122,7 +1122,27 @@ DWORD __stdcall Main(void*)
AspectFOVFix();
HUDFix();
Miscellaneous();
return true; // end thread
}

std::mutex memsetHookMutex;
bool memsetHookCalled = false;
void* (__cdecl* memset_Fn)(void* Dst, int Val, size_t Size);
void* __cdecl memset_Hook(void* Dst, int Val, size_t Size)
{
// memset is one of the first imports called by game (not the very first though, since ASI loader still has those hooked during our DllMain...)
std::lock_guard lock(memsetHookMutex);
if(!memsetHookCalled)
{
memsetHookCalled = true;

// First we'll unhook the IAT for this function as early as we can
Memory::HookIAT(baseModule, "VCRUNTIME140.dll", memset_Hook, memset_Fn);

// Apply our fixes before game has a chance to run
Main();
}

return memset_Fn(Dst, Val, Size);
}

BOOL APIENTRY DllMain( HMODULE hModule,
Expand All @@ -1134,11 +1154,13 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{
case DLL_PROCESS_ATTACH:
{
HANDLE mainHandle = CreateThread(NULL, 0, Main, 0, NULL, 0);

if (mainHandle)
// Hook IAT of one of the imports game calls early on, so we can run our code in the same thread as the game before it has a chance to do anything
// This will only hook the main game modules usage of memset, other modules calling it won't be affected
HMODULE vcruntime140 = GetModuleHandleA("VCRUNTIME140.dll");
if (vcruntime140)
{
CloseHandle(mainHandle);
memset_Fn = decltype(memset_Fn)(GetProcAddress(vcruntime140, "memset"));
Memory::HookIAT(baseModule, "VCRUNTIME140.dll", memset_Fn, memset_Hook);
}
}
case DLL_THREAD_ATTACH:
Expand Down
37 changes: 37 additions & 0 deletions src/helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,41 @@ namespace Memory
{
return (address + 4 + *reinterpret_cast<std::int32_t*>(address));
}

BOOL HookIAT(HMODULE callerModule, char const* targetModule, const void* targetFunction, void* detourFunction)
{
auto* base = (uint8_t*)callerModule;
const auto* dos_header = (IMAGE_DOS_HEADER*)base;
const auto nt_headers = (IMAGE_NT_HEADERS*)(base + dos_header->e_lfanew);
const auto* imports = (IMAGE_IMPORT_DESCRIPTOR*)(base + nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

for (int i = 0; imports[i].Characteristics; i++)
{
const char* name = (const char*)(base + imports[i].Name);
if (lstrcmpiA(name, targetModule) != 0)
continue;

void** thunk = (void**)(base + imports[i].FirstThunk);

for (; *thunk; thunk++)
{
const void* import = *thunk;

if (import != targetFunction)
continue;

DWORD oldState;
if (!VirtualProtect(thunk, sizeof(void*), PAGE_READWRITE, &oldState))
return FALSE;

*thunk = detourFunction;

VirtualProtect(thunk, sizeof(void*), oldState, &oldState);

return TRUE;
}
}

return FALSE;
}
}
1 change: 1 addition & 0 deletions src/stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string>
#include <iostream>
#include <inttypes.h>
#include <mutex>

#include "external/loguru/loguru.hpp"
#include "external/inipp/inipp/inipp.h"
Expand Down

0 comments on commit 3dc37b1

Please sign in to comment.