Skip to content

Commit

Permalink
Refactored the injection process so that the maphack doesn't run insi…
Browse files Browse the repository at this point in the history
…de the loader lock.

The injection process is now two-fold:
1) Inject the dll as normal
2) Inject a function call to the new BH::Initialize method

This has 2 benefits:
1) The injected dll can now safely load dlls of its own
2) This appears to have led to a mild performance increase
  • Loading branch information
slayergod13 committed Jun 22, 2015
1 parent b436194 commit d945b06
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 19 deletions.
3 changes: 2 additions & 1 deletion BH.Injector/BH.Injector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,9 @@ int main(int argc, const char* argv[]) {
switch(nOpt)
{
case 0://Inject into all
for (vector<DiabloWindow*>::iterator window = Windows.begin(); window < Windows.end(); window++)
for (vector<DiabloWindow*>::iterator window = Windows.begin(); window < Windows.end(); window++){
(*window)->Inject();
}
break;
case 1://Unload from all
for (vector<DiabloWindow*>::iterator window = Windows.begin(); window < Windows.end(); window++)
Expand Down
1 change: 1 addition & 0 deletions BH.Injector/BH.Injector.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class DiabloWindow {
}
if (cInjector::InjectDLL(pHwnd, DLL_NAME)) {
wprintf(L"Injected BH into %s(HWND: %X)\n", szTitle, pHwnd);
cInjector::RunRemoteProc(pHwnd, DLL_NAME, "Initialize");
} else {
wprintf(L"Failed to inject %s into %s(HWND: %X)\n", DLL_NAME, szTitle, pHwnd);
}
Expand Down
96 changes: 96 additions & 0 deletions BH.Injector/cInjector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,102 @@ BOOL cInjector::InjectDLL(DWORD dwPid, wstring wDllName)
return FALSE;
}

HMODULE GetRemoteModuleAddress(DWORD dwPid, wstring wDllName){
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
HMODULE address;
unsigned int i;

// Get a handle to the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, dwPid);
if (NULL == hProcess)
return 0;

if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];

// Get the full path to the module's file.

if (GetModuleFileNameEx(hProcess, hMods[i], szModName,
sizeof(szModName) / sizeof(TCHAR)))
{
wstring modPath = szModName;
if (modPath.compare(modPath.length() - wDllName.length(), wDllName.length(), wDllName) == 0) {
address = hMods[i];
break;
}
}
}
}

CloseHandle(hProcess);
return address;
}

BOOL cInjector::RunRemoteProc(HWND hwnd, wstring wDllName, string wProcName){
DWORD dwPid;
GetWindowThreadProcessId(hwnd, &dwPid);
return cInjector::RunRemoteProc(dwPid, wDllName, wProcName);
}

BOOL cInjector::RunRemoteProc(DWORD dwPid, wstring wDllName, string wProcName){
if (!FindInjectedModule(dwPid)) {
return false;
}

HANDLE hThread;
HANDLE hProc;
HMODULE hMod;
LPVOID procAddress;

hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

if (hProc)
{
hMod = LoadLibrary(wDllName.c_str());

if (hMod)
{
procAddress = GetProcAddress(hMod, wProcName.c_str());

if (procAddress)
{
long PROC_OFFSET = (reinterpret_cast<long>(procAddress)-reinterpret_cast<long>(hMod));
long MODULE_BASE = reinterpret_cast<long>(GetRemoteModuleAddress(dwPid, wDllName));

hThread = CreateRemoteThread(hProc, NULL, NULL, reinterpret_cast<LPTHREAD_START_ROUTINE>((LPVOID)(MODULE_BASE + PROC_OFFSET)), NULL, NULL, NULL);
WaitForSingleObject(hThread, INFINITE);

FreeLibrary(hMod);
CloseHandle(hProc);
CloseHandle(hThread);
return true;
}
else {
printf("GetProcAddress() failed with error code %d\n", GetLastError());
}

FreeLibrary(hMod);
}
else {
printf("LoadLibrary() failed with error code %d\n", GetLastError());
}

CloseHandle(hProc);
}
else {
printf("OpenProcess() failed with error code %d\n", GetLastError());
}

return FALSE;
}

BOOL cInjector::UnloadDLL(HWND hwnd, HMODULE hDll) {
DWORD dwPid;
GetWindowThreadProcessId(hwnd, &dwPid);
Expand Down
3 changes: 3 additions & 0 deletions BH.Injector/cInjector.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class cInjector
static INT InjectToProcessByDLL(wstring wProcessDll, wstring wDllName);
static INT InjectToProcess(wstring wProcName, wstring wDllName);

static BOOL RunRemoteProc(DWORD dwPid, wstring wDllName, string wProcName);
static BOOL RunRemoteProc(HWND hwnd, wstring wDllName, string wProcName);

static HMODULE GetRemoteDll(DWORD dwPid, wstring wDllName);
static HMODULE GetRemoteDll(HWND hwnd, wstring wDllName);
};
Expand Down
9 changes: 7 additions & 2 deletions BH.sln
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BH", "BH\BH.vcxproj", "{E549AF63-EF8D-4054-A95B-9C4AE6F51029}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BH.Injector", "BH.Injector\BH.Injector.vcxproj", "{0C10FFDA-E6F8-4180-BF7D-8A423A171748}"
ProjectSection(ProjectDependencies) = postProject
{E549AF63-EF8D-4054-A95B-9C4AE6F51029} = {E549AF63-EF8D-4054-A95B-9C4AE6F51029}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
41 changes: 25 additions & 16 deletions BH/BH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ModuleManager* BH::moduleManager;
Config* BH::config;
Drawing::UI* BH::settingsUI;
Drawing::StatsDisplay* BH::statsDisplay;
bool BH::initialized;
bool BH::cGuardLoaded;
WNDPROC BH::OldWNDPROC;
map<string, Toggle>* BH::MiscToggles;
Expand Down Expand Up @@ -54,13 +55,21 @@ bool BH::Startup(HINSTANCE instance, VOID* reserved) {
cGuardLoaded = false;
}


initialized = false;

return true;
}

void BH::Initialize(char* installDir)
{
moduleManager = new ModuleManager();
config = new Config("BH.cfg");
config->Parse();

if(D2GFX_GetHwnd()) {
BH::OldWNDPROC = (WNDPROC)GetWindowLong(D2GFX_GetHwnd(),GWL_WNDPROC);
SetWindowLong(D2GFX_GetHwnd(),GWL_WNDPROC,(LONG)GameWindowEvent);
if (D2GFX_GetHwnd()) {
BH::OldWNDPROC = (WNDPROC)GetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC);
SetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC, (LONG)GameWindowEvent);
}

settingsUI = new Drawing::UI("Settings", 350, 200);
Expand Down Expand Up @@ -100,25 +109,25 @@ bool BH::Startup(HINSTANCE instance, VOID* reserved) {
// loading/installation finishes.
CreateThread(0, 0, GameThread, 0, 0, 0);

return true;
initialized = true;
}

bool BH::Shutdown() {
if (initialized){
moduleManager->UnloadModules();

moduleManager->UnloadModules();
delete moduleManager;
delete settingsUI;
delete statsDisplay;

delete moduleManager;
delete settingsUI;
delete statsDisplay;
SetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC, (LONG)BH::OldWNDPROC);
for (int n = 0; n < (sizeof(patches) / sizeof(Patch*)); n++) {
delete patches[n];
}

SetWindowLong(D2GFX_GetHwnd(),GWL_WNDPROC,(LONG)BH::OldWNDPROC);
for (int n = 0; n < (sizeof(patches) / sizeof(Patch*)); n++) {
delete patches[n];
oogDraw->Remove();
delete config;
}

oogDraw->Remove();

delete config;


return true;
}
2 changes: 2 additions & 0 deletions BH/BH.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ namespace BH {
extern map<string, Toggle>* MiscToggles;
extern map<string, Toggle>* MiscToggles2;
extern bool cGuardLoaded;
extern bool initialized;
extern Patch* oogDraw;

extern bool Startup(HINSTANCE instance, VOID* reserved);
extern "C" __declspec(dllexport) void Initialize(char* installDir);
extern bool Shutdown();
};
4 changes: 4 additions & 0 deletions BH/BH.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;StormLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
Expand All @@ -88,6 +90,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;StormLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>Exports.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Packaging|Win32'">
Expand All @@ -102,6 +105,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>kernel32.lib;shlwapi.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>Exports.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down

0 comments on commit d945b06

Please sign in to comment.