Removed steam_api hooking

master
acidicoala 1 year ago
parent 8cba428c0f
commit 941d5d7d8c
No known key found for this signature in database
GPG Key ID: D24C6065B49C645B

@ -75,7 +75,6 @@ SmokeAPI does not require any manual configuration. By default, it uses the most
|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|:-------:|
| `$version` | A technical field reserved for future use by tools like GUI config editors | Integer | `1` |
| `logging` | Toggles generation of `*.log` file | Boolean | `false` |
| `hook_steamclient` | When installed in hook mode, this option toggles between hooking steamclient(64).dll and steam_api(64).dll | Boolean | `true` |
| `unlock_all` | Toggles whether all DLCs should be unlocked by default | Boolean | `true` |
| `override` | When `unlock_all` is `true`, this option serves as a blacklist of DLC IDs, which should remain locked. When `unlock_all` is `false`, this option serves as a whitelist of DLC IDs, which should become unlocked | List of Integers | `[]` |
| `dlc_ids` | When game requests list of all DLCs from Steam and the number of registered DLCs is greater than 64, Steam may not return all of them. In this case, SmokeAPI will fetch all released DLCs from Web API. In some games, however (like Monster Hunter: World), web api also doesn't return all possible DLCs. To address this issue, you can specify the missing DLC IDs¹ in this option. For some games (including MH:W), however, it is not necessary because SmokeAPI will also automatically fetch a [manually maintained list of DLC IDs] that are missing from web api | List of Integers | `[]` |

@ -1,7 +1,6 @@
{
"$version": 1,
"$version": 2,
"logging": true,
"hook_steamclient": true,
"unlock_all": true,
"override": [],
"dlc_ids": [],

@ -24,6 +24,65 @@ namespace smoke_api {
Path self_directory;
void init_koalageddon_mode() {
#ifndef _WIN64
logger->info("🐨 Detected Koalageddon mode 💥");
dll_monitor::init({VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& library, const String& name) {
original_library = library; // TODO: Is this necessary?
if (name == VSTDLIB_DLL) {
// Family Sharing functions
DETOUR(Coroutine_Create)
} else if (name == STEAMCLIENT_DLL) {
// Unlocking functions
// TODO: Un-hardcode the pattern
const String pattern("55 8B EC 8B ?? ?? ?? ?? ?? 81 EC ?? ?? ?? ?? 53 FF 15");
auto Log_Interface_address = (FunctionAddress) patcher::find_pattern_address(
win_util::get_module_info(library), "Log_Interface", pattern
);
if (Log_Interface_address) {
DETOUR_EX(Log_Interface, Log_Interface_address)
}
}
});
#endif
}
void init_proxy_mode() {
logger->info("🔀 Detected proxy mode");
original_library = loader::load_original_library(self_directory, ORIGINAL_DLL);
}
void init_hook_mode() {
logger->info("🪝 Detected hook mode");
dll_monitor::init(STEAMCLIENT_DLL, [](const HMODULE& library) {
original_library = library;
DETOUR(CreateInterface)
});
// Hooking steam_api has show itself to be less desirable than steamclient
// for the reasons outlined below:
//
// Calling original in flat functions will actually call the hooked functions
// because the original function redirects the execution to a function taken
// from self pointer, which would have been hooked by SteamInternal_*Interface
// functions.
//
// Furthermore, turns out that many flat functions share the same body,
// which looks like the following snippet:
//
// mov rax, qword ptr ds:[rcx]
// jmp qword ptr ds:[rax+immediate]
//
// This means that we end up inadvertently hooking unintended functions.
// Given that hooking steam_api has no apparent benefits, but has inherent flaws,
// the support for it has been dropped from this project.
}
void init(HMODULE self_module) {
try {
DisableThreadLibraryCalls(self_module);
@ -51,68 +110,13 @@ namespace smoke_api {
if (is_hook_mode) {
hook::init(true);
if (util::strings_are_equal(exe_name, "steam.exe")) {
#ifndef _WIN64
logger->info("🐨 Detected Koalageddon mode 💥");
dll_monitor::init({VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& library, const String& name) {
original_library = library; // TODO: Is this necessary?
if (name == VSTDLIB_DLL) {
// Family Sharing functions
DETOUR(Coroutine_Create)
} else if (name == STEAMCLIENT_DLL) {
// Unlocking functions
// TODO: Un-hardcode the pattern
const String pattern("55 8B EC 8B ?? ?? ?? ?? ?? 81 EC ?? ?? ?? ?? 53 FF 15");
auto Log_Interface_address = (FunctionAddress) patcher::find_pattern_address(
win_util::get_module_info(library), "Log_Interface", pattern
);
if (Log_Interface_address) {
DETOUR_EX(Log_Interface, Log_Interface_address)
}
}
});
#endif
} else if (config.hook_steamclient) { // target steamclient(64).dll
logger->info("🪝 Detected hook mode for SteamClient");
dll_monitor::init(STEAMCLIENT_DLL, [](const HMODULE& library) {
original_library = library;
DETOUR(CreateInterface)
});
} else { // target steam_api.dll
logger->info("🪝 Detected hook mode for Steam_API");
dll_monitor::init(ORIGINAL_DLL, [](const HMODULE& library) {
original_library = library;
DETOUR(SteamInternal_FindOrCreateUserInterface)
DETOUR(SteamInternal_CreateInterface)
DETOUR(SteamApps)
DETOUR(SteamClient)
DETOUR(SteamUser)
DETOUR(SteamAPI_ISteamApps_BIsSubscribedApp)
DETOUR(SteamAPI_ISteamApps_BIsDlcInstalled)
DETOUR(SteamAPI_ISteamApps_GetDLCCount)
DETOUR(SteamAPI_ISteamApps_BGetDLCDataByIndex)
DETOUR(SteamAPI_ISteamClient_GetISteamGenericInterface)
DETOUR(SteamAPI_ISteamInventory_GetResultStatus)
DETOUR(SteamAPI_ISteamInventory_GetResultItems)
DETOUR(SteamAPI_ISteamInventory_GetResultItemProperty)
DETOUR(SteamAPI_ISteamInventory_CheckResultSteamID)
DETOUR(SteamAPI_ISteamInventory_GetAllItems)
DETOUR(SteamAPI_ISteamInventory_GetItemsByID)
DETOUR(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
});
if (util::strings_are_equal(exe_name, "steam.exe") && !util::is_x64()) {
init_koalageddon_mode();
} else {
init_hook_mode();
}
} else {
logger->info("🔀 Detected proxy mode for Steam_API");
original_library = loader::load_original_library(self_directory, ORIGINAL_DLL);
init_proxy_mode();
}
logger->info("🚀 Initialization complete");
} catch (const Exception& ex) {

@ -27,7 +27,6 @@ namespace smoke_api {
struct Config {
uint32_t $version = 1;
bool logging = false;
bool hook_steamclient = true;
bool unlock_all = true;
Set<uint32_t> override;
Vector<uint32_t> dlc_ids;
@ -35,10 +34,9 @@ namespace smoke_api {
Vector<uint32_t> inventory_items;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(
Config, $version,
Config, $version, // NOLINT(misc-const-correctness)
logging,
unlock_all,
hook_steamclient,
override,
dlc_ids,
auto_inject_inventory,

@ -159,18 +159,18 @@ namespace steam_apps {
return count;
};
if (app_id) {
if (app_id != 0) {
logger->debug("{} -> App ID: {}", function_name, app_id);
}
// Compute count only once // FIXME: This doesn't work in Koalageddon mode
// Compute count only once
// FIXME: This doesn't work in Koalageddon mode
original_dlc_count = original_function();
logger->debug("{} -> Original DLC count: {}", function_name, original_dlc_count);
const auto injected_count = static_cast<int>(config.dlc_ids.size());
logger->debug("{} -> Injected DLC count: {}", function_name, injected_count);
if (original_dlc_count < max_dlc) {
return total_count(original_dlc_count + injected_count);
}

@ -3,6 +3,7 @@
using namespace smoke_api;
// TODO: Implement?
VIRTUAL(bool) IClientUser_IsSubscribedApp(PARAMS(AppId_t app_id)) { // NOLINT(misc-unused-parameters)
return steam_apps::IsDlcUnlocked(__func__, 0, app_id);
}

Loading…
Cancel
Save