Files
gse_fork/steam_old_lib/dllmain.cpp
a 2946dfbcee - mimic delay in winverifytrust hook
- add log messages for errors
2025-08-15 15:22:53 +03:00

313 lines
9.7 KiB
C++

// if you're wondering, sold = steam old
#include "steam_old_lib/steam_old_lib.hpp"
#include "common_helpers/common_helpers.hpp"
#include "dll/common_includes.h"
#include "detours/detours.h"
#include <string>
#include <stdexcept>
#include <exception>
#include <string_view>
#include <cstdint>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Softpub.h> // WinVerifyTrust
#ifndef EMU_RELEASE_BUILD
#include "dbg_log/dbg_log.hpp"
#endif
#ifndef EMU_RELEASE_BUILD
dbg_log dbg_logger(
[]{
static wchar_t dll_path[8192]{};
auto chars = GetModuleFileNameW((HINSTANCE)&__ImageBase, dll_path, sizeof(dll_path) / sizeof(dll_path[0]));
auto wpath = std::wstring_view(dll_path, chars);
return common_helpers::to_str(wpath.substr(0, wpath.find_last_of(L"\\/"))) + PATH_SEPARATOR
+ "STEAM_OLD_LOG_" + std::to_string(common_helpers::rand_number(UINT32_MAX)) + ".log";
}()
);
#endif
static bool dll_loaded = false;
static HMODULE my_hModule = nullptr;
static HMODULE wintrust_dll = nullptr;
static std::wstring wintrust_lib_path = L"";
static bool WinVerifyTrust_hooked = false;
static bool LoadLibraryA_hooked = false;
static bool LoadLibraryExA_hooked = false;
static bool LoadLibraryW_hooked = false;
static bool LoadLibraryExW_hooked = false;
static HMODULE hmod_steamclient = nullptr;
static void *ptr_CreateInterface = nullptr;
static inline bool is_steam_lib_A(const char *str) {
return str && str[0] && (
common_helpers::ends_with_i(str, "Steam.dll") ||
common_helpers::ends_with_i(str, "Steam")
);
}
static inline bool is_steam_lib_W(const wchar_t *str) {
return str && str[0] && (
common_helpers::ends_with_i(str, L"Steam.dll") ||
common_helpers::ends_with_i(str, L"Steam")
);
}
static decltype(WinVerifyTrust) *actual_WinVerifyTrust = nullptr;
__declspec(noinline)
static LONG WINAPI WinVerifyTrust_hook(HWND hwnd, GUID *pgActionID, LPVOID pWVTData) {
if (WinVerifyTrust_hooked) {
PRINT_DEBUG_ENTRY();
Sleep(2000); // mimic original behavior
SetLastError(ERROR_SUCCESS);
return 0; // success
}
if (actual_WinVerifyTrust) {
return actual_WinVerifyTrust(hwnd, pgActionID, pWVTData);
}
PRINT_DEBUG("[X] hook isn't enabled but original pointer is null, returning success anyway!");
Sleep(2000); // mimic original behavior
SetLastError(ERROR_SUCCESS);
return 0; // success
}
static decltype(LoadLibraryA) *actual_LoadLibraryA = LoadLibraryA;
__declspec(noinline)
static HMODULE WINAPI LoadLibraryA_hook(LPCSTR lpLibFileName)
{
if (LoadLibraryA_hooked && is_steam_lib_A(lpLibFileName)) {
PRINT_DEBUG_ENTRY();
SetLastError(ERROR_SUCCESS);
return my_hModule;
}
return actual_LoadLibraryA(lpLibFileName);
}
static decltype(LoadLibraryExA) *actual_LoadLibraryExA = LoadLibraryExA;
__declspec(noinline)
static HMODULE WINAPI LoadLibraryExA_hook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
if (LoadLibraryExA_hooked && is_steam_lib_A(lpLibFileName)) {
PRINT_DEBUG_ENTRY();
SetLastError(ERROR_SUCCESS);
return my_hModule;
}
return actual_LoadLibraryExA(lpLibFileName, hFile, dwFlags);
}
static decltype(LoadLibraryW) *actual_LoadLibraryW = LoadLibraryW;
__declspec(noinline)
static HMODULE WINAPI LoadLibraryW_hook(LPCWSTR lpLibFileName)
{
if (LoadLibraryW_hooked && is_steam_lib_W(lpLibFileName)) {
PRINT_DEBUG_ENTRY();
SetLastError(ERROR_SUCCESS);
return my_hModule;
}
return actual_LoadLibraryW(lpLibFileName);
}
static decltype(LoadLibraryExW) *actual_LoadLibraryExW = LoadLibraryExW;
__declspec(noinline)
static HMODULE WINAPI LoadLibraryExW_hook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
{
if (LoadLibraryExW_hooked && is_steam_lib_W(lpLibFileName)) {
PRINT_DEBUG_ENTRY();
SetLastError(ERROR_SUCCESS);
return my_hModule;
}
return actual_LoadLibraryExW(lpLibFileName, hFile, dwFlags);
}
static bool redirect_win32_apis()
{
PRINT_DEBUG_ENTRY();
try {
wintrust_dll = LoadLibraryExW(wintrust_lib_path.c_str(), NULL, 0);
if (!wintrust_dll) throw std::runtime_error("failed to load wintrust lib");
actual_WinVerifyTrust = (decltype(actual_WinVerifyTrust))GetProcAddress(wintrust_dll, "WinVerifyTrust");
if (!actual_WinVerifyTrust) throw std::runtime_error("failed to get proc address of WinVerifyTrust()");
if (DetourTransactionBegin() != NO_ERROR) throw std::runtime_error("call failed: DetourTransactionBegin");
if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) throw std::runtime_error("call failed: DetourUpdateThread");
if (DetourAttach((PVOID *)&actual_WinVerifyTrust, (PVOID)WinVerifyTrust_hook) != NO_ERROR) throw std::runtime_error("attach failed: WinVerifyTrust");
if (DetourAttach((PVOID *)&actual_LoadLibraryA, (PVOID)LoadLibraryA_hook) != NO_ERROR) throw std::runtime_error("attach failed: LoadLibraryA");
if (DetourAttach((PVOID *)&actual_LoadLibraryExA, (PVOID)LoadLibraryExA_hook) != NO_ERROR) throw std::runtime_error("attach failed: LoadLibraryExA");
if (DetourAttach((PVOID *)&actual_LoadLibraryW, (PVOID)LoadLibraryW_hook) != NO_ERROR) throw std::runtime_error("attach failed: LoadLibraryW");
if (DetourAttach((PVOID *)&actual_LoadLibraryExW, (PVOID)LoadLibraryExW_hook) != NO_ERROR) throw std::runtime_error("attach failed: LoadLibraryExW");
if (DetourTransactionCommit() != NO_ERROR) throw std::runtime_error("call failed: DetourTransactionCommit");
WinVerifyTrust_hooked = true;
LoadLibraryA_hooked = true;
LoadLibraryExA_hooked = true;
LoadLibraryW_hooked = true;
LoadLibraryExW_hooked = true;
PRINT_DEBUG("success!");
return true;
} catch (const std::exception &ex) {
PRINT_DEBUG("[X] error: %s", ex.what());
}
if (wintrust_dll) {
FreeLibrary(wintrust_dll);
wintrust_dll = nullptr;
}
PRINT_DEBUG("[X] Win32 API redirection failed");
return false;
}
static bool restore_win32_apis()
{
PRINT_DEBUG_ENTRY();
WinVerifyTrust_hooked = false;
LoadLibraryA_hooked = false;
LoadLibraryExA_hooked = false;
LoadLibraryW_hooked = false;
LoadLibraryExW_hooked = false;
bool ret = false;
try {
if (DetourTransactionBegin() != NO_ERROR) throw std::runtime_error("call failed: DetourTransactionBegin");
if (DetourUpdateThread(GetCurrentThread()) != NO_ERROR) throw std::runtime_error("call failed: DetourUpdateThread");
if (actual_WinVerifyTrust) {
DetourDetach((PVOID *)&actual_WinVerifyTrust, (PVOID)WinVerifyTrust_hook);
}
DetourDetach((PVOID *)&actual_LoadLibraryA, (PVOID)LoadLibraryA_hook);
DetourDetach((PVOID *)&actual_LoadLibraryExA, (PVOID)LoadLibraryExA_hook);
DetourDetach((PVOID *)&actual_LoadLibraryW, (PVOID)LoadLibraryW_hook);
DetourDetach((PVOID *)&actual_LoadLibraryExW, (PVOID)LoadLibraryExW_hook);
if (DetourTransactionCommit() != NO_ERROR) throw std::runtime_error("call failed: DetourTransactionCommit");
ret = true;
} catch (const std::exception &ex) {
PRINT_DEBUG("[X] error: %s", ex.what());
}
if (wintrust_dll) {
FreeLibrary(wintrust_dll);
wintrust_dll = nullptr;
}
PRINT_DEBUG("result = %i", (int)ret);
return ret;
}
static void* steamclient_loader(bool load)
{
if (load) {
if (!ptr_CreateInterface) {
PRINT_DEBUG("loading steamclient");
if (!hmod_steamclient) {
hmod_steamclient = LoadLibraryExW(L"steamclient.dll", NULL, 0);
}
if (hmod_steamclient) {
ptr_CreateInterface = GetProcAddress(hmod_steamclient, "CreateInterface");
}
}
} else {
if (hmod_steamclient) {
PRINT_DEBUG("unloading steamclient");
FreeLibrary(hmod_steamclient);
hmod_steamclient = nullptr;
ptr_CreateInterface = nullptr;
}
}
return ptr_CreateInterface;
}
static bool patch()
{
PRINT_DEBUG_ENTRY();
if (wintrust_lib_path.empty()) {
auto size = GetSystemDirectoryW(&wintrust_lib_path[0], 0);
if (size <= 0) return false;
wintrust_lib_path.resize(size);
size = GetSystemDirectoryW(&wintrust_lib_path[0], (unsigned)wintrust_lib_path.size());
if (size >= (unsigned)wintrust_lib_path.size()) {
wintrust_lib_path.clear();
return false;
}
wintrust_lib_path.pop_back(); // remove null
wintrust_lib_path += L"\\Wintrust.dll";
}
return redirect_win32_apis();
}
static void deinit()
{
PRINT_DEBUG_ENTRY();
steamclient_loader(false);
sold::set_steamclient_loader(nullptr);
sold::set_tid(0);
if (dll_loaded) {
restore_win32_apis();
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
switch (reason) {
case DLL_PROCESS_ATTACH: {
PRINT_DEBUG("DLL_PROCESS_ATTACH");
my_hModule = hModule;
auto my_tid = GetCurrentThreadId();
if (!steamclient_loader(true)) {
PRINT_DEBUG("[X] failed to load steamclient.dll");
// https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain
// "The system immediately calls your entry-point function with DLL_PROCESS_DETACH and unloads the DLL"
return FALSE;
}
if (!patch()) {
PRINT_DEBUG("[X] failed to patch");
return FALSE;
}
sold::set_steamclient_loader(steamclient_loader);
sold::set_tid(my_tid);
dll_loaded = true;
}
break;
case DLL_PROCESS_DETACH: {
PRINT_DEBUG("DLL_PROCESS_DETACH");
deinit();
}
break;
}
return TRUE;
}