Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.

Commit 7756b4e

Browse files
committed
Brute force sl.interposer.dll paths during early load. Universal builds now support all games without an anticheat.
1 parent 0607900 commit 7756b4e

File tree

3 files changed

+87
-59
lines changed

3 files changed

+87
-59
lines changed

source/wrapper_generic/Util.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
namespace Util
4+
{
5+
template<size_t Size>
6+
const wchar_t *GetModulePath(wchar_t (&Buffer)[Size], bool DirectoryOnly, HMODULE ModuleHandle)
7+
{
8+
memset(Buffer, 0, Size * sizeof(wchar_t));
9+
10+
if (!ModuleHandle)
11+
{
12+
if (!GetModuleHandleExW(
13+
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
14+
reinterpret_cast<LPCWSTR>(&GetModulePath<Size>),
15+
&ModuleHandle))
16+
return nullptr;
17+
}
18+
19+
const auto len = GetModuleFileNameW(ModuleHandle, Buffer, Size - 1);
20+
21+
if (len <= 0)
22+
return nullptr;
23+
24+
for (auto i = static_cast<ptrdiff_t>(len) - 1; i > 0; i--)
25+
{
26+
if (Buffer[i] == L'\\' || Buffer[i] == L'/')
27+
{
28+
if (DirectoryOnly)
29+
Buffer[i + 1] = 0; // Chop off the file name leaving only the directory
30+
else
31+
return &Buffer[i + 1]; // Split the name out
32+
33+
break;
34+
}
35+
}
36+
37+
return Buffer;
38+
}
39+
}

source/wrapper_generic/dllmain.cpp

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "Hooking/Hooks.h"
2+
#include "Util.h"
23

34
//
45
// sl.interposer.dll loads sl.common.dll
@@ -20,27 +21,8 @@ bool PatchImportsForModule(const wchar_t *Path, HMODULE ModuleHandle);
2021
void *LoadImplementationDll()
2122
{
2223
// Use the same directory as the current DLL
23-
wchar_t path[2048] = {};
24-
HMODULE thisModuleHandle = nullptr;
25-
26-
if (GetModuleHandleExW(
27-
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
28-
reinterpret_cast<LPCWSTR>(&LoadImplementationDll),
29-
&thisModuleHandle))
30-
{
31-
if (GetModuleFileNameW(thisModuleHandle, path, ARRAYSIZE(path)))
32-
{
33-
// Chop off the file name
34-
for (auto i = static_cast<ptrdiff_t>(wcslen(path)) - 1; i > 0; i--)
35-
{
36-
if (path[i] == L'\\' || path[i] == L'/')
37-
{
38-
path[i + 1] = 0;
39-
break;
40-
}
41-
}
42-
}
43-
}
24+
wchar_t path[2048];
25+
Util::GetModulePath(path, true, nullptr);
4426

4527
// Do not cache a handle to the implementation DLL. It might be unloaded and reloaded.
4628
wcscat_s(path, RelplacementImplementationDll);
@@ -132,22 +114,22 @@ bool PatchImportsForModule(const wchar_t *Path, HMODULE ModuleHandle)
132114
if (!Path || !ModuleHandle)
133115
return false;
134116

135-
std::wstring_view libFileName(Path);
136-
137117
const bool isMatch = std::any_of(
138118
TargetLibrariesToHook.begin(),
139119
TargetLibrariesToHook.end(),
140-
[&](const wchar_t *Target)
120+
[path = std::wstring_view(Path)](const wchar_t *Target)
141121
{
142-
return libFileName.ends_with(Target);
122+
return path.ends_with(Target);
143123
});
144124

145125
if (!isMatch || !ModuleRequiresPatching(ModuleHandle))
146126
return false;
147127

128+
#if 0
148129
OutputDebugStringW(L"Patching imports for a new module: ");
149130
OutputDebugStringW(Path);
150131
OutputDebugStringW(L"...\n");
132+
#endif
151133

152134
Hooks::RedirectImport(ModuleHandle, "KERNEL32.dll", "LoadLibraryW", &HookedLoadLibraryW, nullptr);
153135
Hooks::RedirectImport(ModuleHandle, "KERNEL32.dll", "LoadLibraryExW", &HookedLoadLibraryExW, nullptr);
@@ -169,17 +151,44 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
169151
TargetLibrariesToHook.push_back(TargetEGSServicesDll);
170152
LoadLibraryW(TargetEGSServicesDll);
171153

172-
if (!LoadLibraryW(L"sl.interposer.dll"))
154+
//
155+
// Aggressive hooking tries to force SL's interposer to load early. It's not always present
156+
// in the local directory. A bit of guesswork is required.
157+
//
158+
// "Dying Light 2\ ph\work\bin\x64\DyingLightGame_x64_rwdi.exe"
159+
// "Returnal\ Returnal\ Binaries\Win64\Returnal-Win64-Shipping.exe"
160+
// "Hogwarts Legacy\ Phoenix\ Binaries\Win64\HogwartsLegacy.exe"
161+
// "SW Jedi Survivor\ SwGame\ Binaries\Win64\JediSurvivor.exe"
162+
// "Atomic Heart\ AtomicHeart\ Binaries\Win64\AtomicHeart-Win64-Shipping.exe
163+
// "MMS\ MidnightSuns\ Binaries\Win64\MidnightSuns-Win64-Shipping.exe"
164+
//
165+
// "Dying Light 2\ ph\work\bin\x64\sl.interposer.dll"
166+
// "Returnal\ Engine\Plugins\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
167+
// "Hogwarts Legacy\ Engine\Plugins\Runtime\Nvidia\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
168+
// "SW Jedi Survivor\ Engine\Plugins\Runtime\Nvidia\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
169+
// "Atomic Heart\ Engine\Plugins\Runtime\Nvidia\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
170+
// "MMS\ Engine\Plugins\Runtime\Nvidia\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
171+
//
172+
constinit static const wchar_t *bruteInterposerPaths[] = {
173+
L"sl.interposer.dll",
174+
L"..\\..\\..\\Engine\\Plugins\\Streamline\\Binaries\\ThirdParty\\Win64\\sl.interposer.dll",
175+
L"..\\..\\..\\Engine\\Plugins\\Runtime\\Nvidia\\Streamline\\Binaries\\ThirdParty\\Win64\\sl.interposer.dll",
176+
};
177+
178+
if (!LoadLibraryW(bruteInterposerPaths[0]))
173179
{
174-
// "Returnal\Returnal\Binaries\Win64\Returnal-Win64-Shipping.exe"
175-
// "Returnal\Engine\Plugins\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
176-
//
177-
// "Hogwarts Legacy\Phoenix\Binaries\Win64\HogwartsLegacy.exe"
178-
// "Hogwarts Legacy\Engine\Plugins\Runtime\Nvidia\Streamline\Binaries\ThirdParty\Win64\sl.interposer.dll"
179-
//
180-
// Insanity. A dedicated configuration file is going to be required at this rate. HL is okay but
181-
// Returnal needs some help.
182-
LoadLibraryW(L"..\\..\\..\\Engine\\Plugins\\Streamline\\Binaries\\ThirdParty\\Win64\\sl.interposer.dll");
180+
wchar_t path[2048];
181+
182+
for (auto interposer : bruteInterposerPaths)
183+
{
184+
if (!Util::GetModulePath(path, true, GetModuleHandleW(nullptr)))
185+
break;
186+
187+
wcscat_s(path, interposer);
188+
189+
if (LoadLibraryW(path))
190+
break;
191+
}
183192
}
184193
}
185194

source/wrapper_generic/proxies.cpp

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include "Util.h"
2+
13
void *CustomLibraryResolverCallback();
24

35
#define DLL_PROXY_EXPORT_LISTING_FILE "ExportListing.inc" // List of exported functions
@@ -10,7 +12,6 @@ extern bool EnableAggressiveHooking;
1012

1113
void *TryResolveSystemLibrary(const wchar_t *RealLibraryName)
1214
{
13-
// Build the full system32 path
1415
wchar_t fullSystemPath[2048] = {};
1516

1617
if (GetSystemDirectoryW(fullSystemPath, ARRAYSIZE(fullSystemPath) - 1) <= 0)
@@ -68,29 +69,8 @@ void *CustomLibraryResolverCallback()
6869
if (!moduleHandle)
6970
{
7071
// Grab the file name and extension of this dll
71-
wchar_t temp[2048] = {};
72-
const auto targetLibraryName = [&]() -> const wchar_t *
73-
{
74-
HMODULE thisModuleHandle = nullptr;
75-
76-
if (!GetModuleHandleExW(
77-
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
78-
reinterpret_cast<LPCWSTR>(&CustomLibraryResolverCallback),
79-
&thisModuleHandle))
80-
return nullptr;
81-
82-
if (GetModuleFileNameW(thisModuleHandle, temp, ARRAYSIZE(temp)) <= 0)
83-
return nullptr;
84-
85-
for (auto i = static_cast<ptrdiff_t>(wcslen(temp)) - 1; i > 0; i--)
86-
{
87-
// Split the name out
88-
if (temp[i] == L'\\' || temp[i] == L'/')
89-
return &temp[i + 1];
90-
}
91-
92-
return temp;
93-
}();
72+
wchar_t temp[2048];
73+
const auto targetLibraryName = Util::GetModulePath(temp, false, nullptr);
9474

9575
if (targetLibraryName)
9676
{

0 commit comments

Comments
 (0)