diff --git a/KoalaBox b/KoalaBox index 6fa96ea..c0d357d 160000 --- a/KoalaBox +++ b/KoalaBox @@ -1 +1 @@ -Subproject commit 6fa96ea016482b263827d82f02b86552d5e4d407 +Subproject commit c0d357da78fcfa29e798b99d66d07170d73d6c9c diff --git a/src/core/macros.hpp b/src/core/macros.hpp index 30049ce..f82b76e 100644 --- a/src/core/macros.hpp +++ b/src/core/macros.hpp @@ -8,18 +8,14 @@ #define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec( dllexport ) TYPE __cdecl #define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall -#define GET_ORIGINAL_VIRTUAL_FUNCTION(FUNC) \ - const auto FUNC##_o = koalabox::hook::get_original_function(globals::address_map, #FUNC, FUNC); +#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \ + const auto FUNC##_o = koalabox::hook::get_original_hooked_function(globals::address_map, #FUNC, FUNC); -#define $GET_ORIGINAL_MODULE_FUNCTION(FUNC, MODULE_HANDLE) \ - static const auto FUNC##_o = koalabox::hook::get_original_function(MODULE_HANDLE, #FUNC, FUNC); - -#define GET_ORIGINAL_FUNCTION_STEAMCLIENT(FUNC) $GET_ORIGINAL_MODULE_FUNCTION(FUNC, globals::steamclient_module) -#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) $GET_ORIGINAL_MODULE_FUNCTION(FUNC, globals::steamapi_module) -#define GET_ORIGINAL_FUNCTION_VSTDLIB(FUNC) $GET_ORIGINAL_MODULE_FUNCTION(FUNC, globals::vstdlib_module) +#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \ + static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC); #define $DETOUR(FUNC, MODULE_HANDLE) \ - koalabox::hook::detour_or_warn(MODULE_HANDLE, #FUNC, reinterpret_cast(FUNC)); + koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, #FUNC, reinterpret_cast(FUNC)); #define DETOUR_ADDRESS(FUNC, ADDRESS) \ koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast(FUNC)); diff --git a/src/koalageddon/koalageddon.cpp b/src/koalageddon/koalageddon.cpp index cc9d75c..c685c3c 100644 --- a/src/koalageddon/koalageddon.cpp +++ b/src/koalageddon/koalageddon.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace koalageddon { KoalageddonConfig config; // NOLINT(cert-err58-cpp) @@ -65,13 +66,14 @@ namespace koalageddon { globals::vstdlib_module = module_handle; if (config::instance.unlock_family_sharing) { - init_vstdlib_hooks(); + DETOUR_VSTDLIB(Coroutine_Create) } } else if (util::strings_are_equal(name, STEAMCLIENT_DLL)) { // SteamClient DLL handles unlocking functions globals::steamclient_module = module_handle; - init_steamclient_hooks(); + + DETOUR_STEAMCLIENT(CreateInterface) } if (globals::vstdlib_module != nullptr && globals::steamclient_module != nullptr) { diff --git a/src/koalageddon/koalageddon.hpp b/src/koalageddon/koalageddon.hpp index 700cf7d..fec3ae7 100644 --- a/src/koalageddon/koalageddon.hpp +++ b/src/koalageddon/koalageddon.hpp @@ -15,8 +15,9 @@ namespace koalageddon { uint32_t vstdlib_callback_data_offset = 0; uint32_t vstdlib_callback_name_offset = 4; + uint32_t client_engine_steam_client_internal_ordinal = 12; + uint32_t steam_client_internal_interface_selector_ordinal = 18; String steamclient_interface_interceptor_pattern = "55 8B EC 8B ?? ?? ?? ?? ?? 81 EC ?? ?? ?? ?? 53 FF 15"; - String steamclient_interface_demux_pattern = "55 8B EC 83 EC ?? ?? ?? ?? 8B ?? ?? B8 ?? ?? ?? ?? 8B D9"; uint32_t IClientAppManager_IsAppDlcInstalled_ordinal = 8; uint32_t IClientApps_GetDLCCount_ordinal = 8; @@ -40,8 +41,9 @@ namespace koalageddon { vstdlib_callback_data_offset, vstdlib_callback_name_offset, + client_engine_steam_client_internal_ordinal, + steam_client_internal_interface_selector_ordinal, steamclient_interface_interceptor_pattern, - steamclient_interface_demux_pattern, IClientAppManager_IsAppDlcInstalled_ordinal, IClientApps_GetDLCCount_ordinal, @@ -62,6 +64,6 @@ namespace koalageddon { void init(); - void init_steamclient_hooks(); - void init_vstdlib_hooks(); + void init_steamclient_hooks(const void* interface_selector_address); + void init_steamclient_hooks2(); } diff --git a/src/koalageddon/steamclient.cpp b/src/koalageddon/steamclient.cpp index 156d02c..52f317a 100644 --- a/src/koalageddon/steamclient.cpp +++ b/src/koalageddon/steamclient.cpp @@ -9,14 +9,14 @@ using namespace koalabox; -#define DEMUX_DECL(INTERFACE) \ +#define SELECTOR_DECL(INTERFACE) \ constexpr auto INTERFACE = #INTERFACE; \ - DLL_EXPORT(void) INTERFACE##_Demux(const void*, const void*, const void*, const void*); \ + DLL_EXPORT(void) INTERFACE##_Selector(const void*, const void*, const void*, const void*); \ -DEMUX_DECL(IClientAppManager) -DEMUX_DECL(IClientApps) -DEMUX_DECL(IClientInventory) -DEMUX_DECL(IClientUser) +SELECTOR_DECL(IClientAppManager) +SELECTOR_DECL(IClientApps) +SELECTOR_DECL(IClientInventory) +SELECTOR_DECL(IClientUser) DLL_EXPORT(void) SteamClient_Interface_Interceptor(const char* interface_name, const char* function_name); @@ -134,8 +134,8 @@ namespace koalageddon { return (FunctionAddress) op.imm.value.u; } - const char* find_interface_name(FunctionAddress demux_address) { - auto* instruction_pointer = (uint8_t*) demux_address; + const char* find_interface_name(FunctionAddress selector_address) { + auto* instruction_pointer = (uint8_t*) selector_address; ZydisDecodedInstruction instruction{}; while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, instruction_pointer, 1024, &instruction))) { if (instruction.mnemonic == ZYDIS_MNEMONIC_PUSH) { @@ -159,7 +159,7 @@ namespace koalageddon { return nullptr; } - void init_steamclient_hooks() { + void init_steamclient_hooks(const void* interface_selector_address) { ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LEGACY_32, ZYDIS_ADDRESS_WIDTH_32); const HMODULE module_handle = win_util::get_module_handle_or_throw(STEAMCLIENT_DLL); @@ -168,58 +168,48 @@ namespace koalageddon { const auto start_address = reinterpret_cast(module_info.lpBaseOfDll); auto* terminal_address = (uint8_t*) (start_address + module_info.SizeOfImage); - // TODO: There may actually be a way to find this address from "first principles" - // SteamClient.Steam_CreateSteamPipe begins with a call to fun_alpha() - // fun_alpha() calls fun_beta() - // ordinal 18 - const auto* interface_demux_address = patcher::find_pattern_address( - module_info, - "interface demux", - config.steamclient_interface_demux_pattern - ); + // Then iterate over each function selector call - // Then iterate over each function demux call - - auto* instruction_pointer = (uint8_t*) interface_demux_address; + auto* instruction_pointer = (uint8_t*) interface_selector_address; ZydisDecodedInstruction previous_instruction{}; ZydisDecodedInstruction instruction{}; while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, instruction_pointer, 10, &instruction))) { if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP && previous_instruction.mnemonic == ZYDIS_MNEMONIC_CALL) { - // For every such call, extract a function demux address - const auto call_demux_address = (FunctionAddress) ( + // For every such call, extract a function selector address + const auto call_selector_address = (FunctionAddress) ( instruction_pointer - previous_instruction.length ); - const auto function_demux_address = get_absolute_address( - previous_instruction, call_demux_address + const auto function_selector_address = get_absolute_address( + previous_instruction, call_selector_address ); - if (function_demux_address == 0) { - logger->warn("Failed to extract absolute address of call at {}", (void*) call_demux_address); + if (function_selector_address == 0) { + logger->warn("Failed to extract absolute address of call at {}", (void*) call_selector_address); } else { // Then use this address to extract the interface name - const char* interface_name_address = find_interface_name(function_demux_address); + const char* interface_name_address = find_interface_name(function_selector_address); if (interface_name_address == nullptr) { logger->warn( "Failed to extract interface name address of function demux at {}", - (void*) function_demux_address + (void*) function_selector_address ); } else { const String interface_name((char*) interface_name_address); logger->debug("Detected interface: '{}'", interface_name); - // Finally, hook the demux functions of interest + // Finally, hook the selector functions of interest if (IClientAppManager == interface_name) { - DETOUR_ADDRESS(IClientAppManager_Demux, function_demux_address) + DETOUR_ADDRESS(IClientAppManager_Selector, function_selector_address) } else if (IClientApps == interface_name) { - DETOUR_ADDRESS(IClientApps_Demux, function_demux_address) + DETOUR_ADDRESS(IClientApps_Selector, function_selector_address) } else if (IClientInventory == interface_name) { - DETOUR_ADDRESS(IClientInventory_Demux, function_demux_address) + DETOUR_ADDRESS(IClientInventory_Selector, function_selector_address) } else if (IClientUser == interface_name) { - DETOUR_ADDRESS(IClientUser_Demux, function_demux_address) + DETOUR_ADDRESS(IClientUser_Selector, function_selector_address) } // Update the terminal address to limit the search scope only to relevant portion of the code @@ -256,13 +246,12 @@ namespace koalageddon { DETOUR_ADDRESS(SteamClient_Interface_Interceptor, interface_interceptor_address) } } - } /** * This function intercepts interface name and function names, which we need to determine which functions to hook. * Unfortunately we can't reliably get interface pointer in this function, hence we need to hook corresponding - * parent demux functions which will contain the interface pointer as the first parameter. + * parent selector functions which will contain the interface pointer as the first parameter. */ DLL_EXPORT(void) SteamClient_Interface_Interceptor(const char* interface_name, const char* function_name) { try { @@ -323,7 +312,7 @@ DLL_EXPORT(void) SteamClient_Interface_Interceptor(const char* interface_name, c }); } - GET_ORIGINAL_VIRTUAL_FUNCTION(SteamClient_Interface_Interceptor) + GET_ORIGINAL_HOOKED_FUNCTION(SteamClient_Interface_Interceptor) SteamClient_Interface_Interceptor_o(interface_name, function_name); } catch (const Exception& ex) { logger->error("{} -> Error: {}", __func__, ex.what()); @@ -332,11 +321,11 @@ DLL_EXPORT(void) SteamClient_Interface_Interceptor(const char* interface_name, c /** - * This macro will generate a definition of a demux function, + * This macro will generate a definition of a selector function, * which will cache the interface pointer in the local map. */ -#define DEMUX_IMPL(INTERFACE) \ -DLL_EXPORT(void) INTERFACE##_Demux( \ +#define SELECTOR_IMPL(INTERFACE) \ +DLL_EXPORT(void) INTERFACE##_Selector( \ const void* arg1, \ const void* arg2, \ const void* arg3, \ @@ -346,11 +335,11 @@ DLL_EXPORT(void) INTERFACE##_Demux( \ const std::lock_guard guard(koalageddon::map_mutex); \ koalageddon::interface_name_pointer_map[INTERFACE] = arg1; \ } \ - GET_ORIGINAL_VIRTUAL_FUNCTION(INTERFACE##_Demux) \ - INTERFACE##_Demux_o(arg1, arg2, arg3, arg4); \ + GET_ORIGINAL_HOOKED_FUNCTION(INTERFACE##_Selector) \ + INTERFACE##_Selector_o(arg1, arg2, arg3, arg4); \ } -DEMUX_IMPL(IClientAppManager) -DEMUX_IMPL(IClientApps) -DEMUX_IMPL(IClientInventory) -DEMUX_IMPL(IClientUser) +SELECTOR_IMPL(IClientAppManager) +SELECTOR_IMPL(IClientApps) +SELECTOR_IMPL(IClientInventory) +SELECTOR_IMPL(IClientUser) diff --git a/src/koalageddon/vstdlib.cpp b/src/koalageddon/vstdlib.cpp index 6734b9c..e2bd84c 100644 --- a/src/koalageddon/vstdlib.cpp +++ b/src/koalageddon/vstdlib.cpp @@ -6,15 +6,6 @@ using namespace koalageddon; using namespace koalabox; -typedef uint32_t HCoroutine; -DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, struct CoroutineData* data); - -namespace koalageddon { - void init_vstdlib_hooks() { - DETOUR_VSTDLIB(Coroutine_Create) - } -} - VIRTUAL(bool) SharedLicensesLockStatus(PARAMS(void* arg)) { // NOLINT(misc-unused-parameters) logger->debug("{} -> instance: {}, arg: {}", __func__, fmt::ptr(THIS), fmt::ptr(arg)); return true; @@ -46,7 +37,7 @@ struct CoroutineData { }; VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** p_name)) { - GET_ORIGINAL_FUNCTION_VSTDLIB(VStdLib_Callback_Interceptor) + GET_ORIGINAL_HOOKED_FUNCTION(VStdLib_Callback_Interceptor) VStdLib_Callback_Interceptor_o(ARGS(p_name)); @@ -79,7 +70,7 @@ VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** p_name)) { * hence we must hook an interface method that sets the callback name. */ DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data) { - GET_ORIGINAL_FUNCTION_VSTDLIB(Coroutine_Create) + GET_ORIGINAL_HOOKED_FUNCTION(Coroutine_Create) const auto result = Coroutine_Create_o(callback_address, data); diff --git a/src/steam_api_virtuals/isteamapps.cpp b/src/steam_api_virtuals/isteamapps.cpp index f52a531..ea15b62 100644 --- a/src/steam_api_virtuals/isteamapps.cpp +++ b/src/steam_api_virtuals/isteamapps.cpp @@ -17,7 +17,7 @@ VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t appID)) { // NOLINT(misc } VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS()) { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamApps_GetDLCCount) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_GetDLCCount) return steam_apps::GetDLCCount(__func__, 0, [&]() { @@ -35,7 +35,7 @@ VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex( ) ) { return steam_apps::GetDLCDataByIndex(__func__, 0, iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamApps_BGetDLCDataByIndex) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamApps_BGetDLCDataByIndex) return ISteamApps_BGetDLCDataByIndex_o( ARGS(iDLC, pAppID, pbAvailable, pchName, cchNameBufferSize) diff --git a/src/steam_api_virtuals/isteamclient.cpp b/src/steam_api_virtuals/isteamclient.cpp index f43f35f..513e136 100644 --- a/src/steam_api_virtuals/isteamclient.cpp +++ b/src/steam_api_virtuals/isteamclient.cpp @@ -11,7 +11,7 @@ VIRTUAL(void*) ISteamClient_GetISteamApps( ) ) { return steam_client::GetGenericInterface(__func__, version, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamClient_GetISteamApps) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamApps) return ISteamClient_GetISteamApps_o(ARGS(hSteamUser, hSteamPipe, version)); }); @@ -25,7 +25,7 @@ VIRTUAL(void*) ISteamClient_GetISteamUser( ) ) { return steam_client::GetGenericInterface(__func__, version, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamClient_GetISteamUser) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamUser) return ISteamClient_GetISteamUser_o(ARGS(hSteamUser, hSteamPipe, version)); }); @@ -39,7 +39,7 @@ VIRTUAL(void*) ISteamClient_GetISteamGenericInterface( ) ) { return steam_client::GetGenericInterface(__func__, pchVersion, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamClient_GetISteamGenericInterface) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamGenericInterface) return ISteamClient_GetISteamGenericInterface_o(ARGS(hSteamUser, hSteamPipe, pchVersion)); }); @@ -53,7 +53,7 @@ VIRTUAL(void*) ISteamClient_GetISteamInventory( ) ) { return steam_client::GetGenericInterface(__func__, pchVersion, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamClient_GetISteamInventory) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamClient_GetISteamInventory) return ISteamClient_GetISteamInventory_o(ARGS(hSteamUser, hSteamPipe, pchVersion)); }); diff --git a/src/steam_api_virtuals/isteaminventory.cpp b/src/steam_api_virtuals/isteaminventory.cpp index 496a998..5bd0bfd 100644 --- a/src/steam_api_virtuals/isteaminventory.cpp +++ b/src/steam_api_virtuals/isteaminventory.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) { return steam_inventory::GetResultStatus(__func__, resultHandle, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetResultStatus) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultStatus) return ISteamInventory_GetResultStatus_o(ARGS(resultHandle)); }); @@ -22,12 +22,12 @@ VIRTUAL(bool) ISteamInventory_GetResultItems( return steam_inventory::GetResultItems( __func__, resultHandle, pOutItemsArray, punOutItemsArraySize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetResultItems) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultItems) return ISteamInventory_GetResultItems_o(ARGS(resultHandle, pOutItemsArray, punOutItemsArraySize)); }, [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetItemDefinitionIDs) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs) return ISteamInventory_GetItemDefinitionIDs_o(ARGS(pItemDefIDs, punItemDefIDsArraySize)); } @@ -45,7 +45,7 @@ VIRTUAL(bool) ISteamInventory_GetResultItemProperty( ) { return steam_inventory::GetResultItemProperty( __func__, resultHandle, unItemIndex, pchPropertyName, pchValueBuffer, punValueBufferSizeOut, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetResultItemProperty) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetResultItemProperty) return ISteamInventory_GetResultItemProperty_o( ARGS(resultHandle, unItemIndex, pchPropertyName, pchValueBuffer, punValueBufferSizeOut) @@ -61,7 +61,7 @@ VIRTUAL(bool) ISteamInventory_CheckResultSteamID( ) ) { return steam_inventory::CheckResultSteamID(__func__, resultHandle, steamIDExpected, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_CheckResultSteamID) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_CheckResultSteamID) return ISteamInventory_CheckResultSteamID_o(ARGS(resultHandle, steamIDExpected)); }); @@ -69,7 +69,7 @@ VIRTUAL(bool) ISteamInventory_CheckResultSteamID( VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) { return steam_inventory::GetAllItems(__func__, pResultHandle, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetAllItems) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetAllItems) return ISteamInventory_GetAllItems_o(ARGS(pResultHandle)); }); @@ -83,7 +83,7 @@ VIRTUAL(bool) ISteamInventory_GetItemsByID( ) ) { return steam_inventory::GetItemsByID(__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetItemsByID) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemsByID) return ISteamInventory_GetItemsByID_o(ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs)); }); @@ -97,7 +97,7 @@ VIRTUAL(bool) ISteamInventory_SerializeResult( ) ) { return steam_inventory::SerializeResult(__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_SerializeResult) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_SerializeResult) return ISteamInventory_SerializeResult_o(ARGS(resultHandle, pOutBuffer, punOutBufferSize)); }); @@ -110,7 +110,7 @@ VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs( ) ) { return steam_inventory::GetItemDefinitionIDs(__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamInventory_GetItemDefinitionIDs) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamInventory_GetItemDefinitionIDs) return ISteamInventory_GetItemDefinitionIDs_o(ARGS(pItemDefIDs, punItemDefIDsArraySize)); }); diff --git a/src/steam_api_virtuals/isteamuser.cpp b/src/steam_api_virtuals/isteamuser.cpp index 1a557d9..dfe1b2d 100644 --- a/src/steam_api_virtuals/isteamuser.cpp +++ b/src/steam_api_virtuals/isteamuser.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t appID)) { return steam_user::UserHasLicenseForApp(__func__, appID, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(ISteamUser_UserHasLicenseForApp) + GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp) return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, appID)); }); diff --git a/src/steam_functions/steam_functions.cpp b/src/steam_functions/steam_functions.cpp index d6f40cc..7d0ab21 100644 --- a/src/steam_functions/steam_functions.cpp +++ b/src/steam_functions/steam_functions.cpp @@ -1,9 +1,8 @@ #include #include - #include +#include #include - #include namespace steam_functions { @@ -195,6 +194,19 @@ namespace steam_functions { if (version_number >= 2) { HOOK_STEAM_INVENTORY(ISteamInventory_GetResultItemProperty) } + } else if (version_string.starts_with(CLIENT_ENGINE)) { + // Koalageddon mode + + const auto* steam_client_internal = ((const void****) interface)[ + koalageddon::config.client_engine_steam_client_internal_ordinal + ]; + const auto* interface_selector_address = (*steam_client_internal)[ + koalageddon::config.steam_client_internal_interface_selector_ordinal + ]; + + logger->debug("Found interface selector at: {}", interface_selector_address); + + koalageddon::init_steamclient_hooks(interface_selector_address); } else { return; } diff --git a/src/steam_functions/steam_functions.hpp b/src/steam_functions/steam_functions.hpp index ef5cbcd..7b114a8 100644 --- a/src/steam_functions/steam_functions.hpp +++ b/src/steam_functions/steam_functions.hpp @@ -42,7 +42,6 @@ class ISteamApps; class ISteamUser; class ISteamInventory; - // TODO: Refactor into multiple headers // ISteamClient @@ -128,6 +127,9 @@ VIRTUAL(bool) IClientInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, cons VIRTUAL(bool) IClientInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t, uint32_t *)); VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t, uint32_t *)); +typedef uint32_t HCoroutine; +DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, struct CoroutineData* data); + namespace steam_functions { using namespace koalabox; @@ -135,6 +137,7 @@ namespace steam_functions { const String STEAM_CLIENT = "SteamClient"; // NOLINT(cert-err58-cpp) const String STEAM_USER = "SteamUser"; // NOLINT(cert-err58-cpp) const String STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; // NOLINT(cert-err58-cpp) + const String CLIENT_ENGINE = "CLIENTENGINE_INTERFACE_VERSION"; // NOLINT(cert-err58-cpp) void hook_virtuals(void* interface, const String& version_string); uint32_t get_app_id_or_throw(); diff --git a/src/steamclient_exports/steamclient.cpp b/src/steamclient_exports/steamclient.cpp index a902036..acb85f0 100644 --- a/src/steamclient_exports/steamclient.cpp +++ b/src/steamclient_exports/steamclient.cpp @@ -1,11 +1,8 @@ -#include #include -using namespace smoke_api; - DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result) { return steam_client::GetGenericInterface(__func__, interface_string, [&]() { - GET_ORIGINAL_FUNCTION_STEAMCLIENT(CreateInterface) + GET_ORIGINAL_HOOKED_FUNCTION(CreateInterface) return CreateInterface_o(interface_string, out_result); }); diff --git a/src/steamclient_virtuals/client_app_manager.cpp b/src/steamclient_virtuals/client_app_manager.cpp index 98026af..15110fd 100644 --- a/src/steamclient_virtuals/client_app_manager.cpp +++ b/src/steamclient_virtuals/client_app_manager.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) { return steam_apps::IsDlcUnlocked(__func__, app_id, dlc_id, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientAppManager_IsAppDlcInstalled) + GET_ORIGINAL_HOOKED_FUNCTION(IClientAppManager_IsAppDlcInstalled) return IClientAppManager_IsAppDlcInstalled_o(ARGS(app_id, dlc_id)); }); diff --git a/src/steamclient_virtuals/client_apps.cpp b/src/steamclient_virtuals/client_apps.cpp index c9e6f8a..b236ce9 100644 --- a/src/steamclient_virtuals/client_apps.cpp +++ b/src/steamclient_virtuals/client_apps.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) { return steam_apps::GetDLCCount(__func__, appId, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientApps_GetDLCCount) + GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_GetDLCCount) return IClientApps_GetDLCCount_o(ARGS(appId)); }); @@ -22,7 +22,7 @@ VIRTUAL(bool) IClientApps_BGetDLCDataByIndex( ) ) { return steam_apps::GetDLCDataByIndex(__func__, appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientApps_BGetDLCDataByIndex) + GET_ORIGINAL_HOOKED_FUNCTION(IClientApps_BGetDLCDataByIndex) return IClientApps_BGetDLCDataByIndex_o( ARGS(appID, iDLC, pDlcID, pbAvailable, pchName, cchNameBufferSize) diff --git a/src/steamclient_virtuals/client_inventory.cpp b/src/steamclient_virtuals/client_inventory.cpp index 8ef4f0d..6ec02b3 100644 --- a/src/steamclient_virtuals/client_inventory.cpp +++ b/src/steamclient_virtuals/client_inventory.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) { return steam_inventory::GetResultStatus(__func__, resultHandle, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetResultStatus) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetResultStatus) return IClientInventory_GetResultStatus_o(ARGS(resultHandle)); }); @@ -22,7 +22,7 @@ VIRTUAL(bool) IClientInventory_GetResultItems( return steam_inventory::GetResultItems( __func__, resultHandle, pOutItemsArray, punOutItemsArraySize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetResultItems) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetResultItems) *punOutItemsArraySize = item_count; return IClientInventory_GetResultItems_o( @@ -30,7 +30,7 @@ VIRTUAL(bool) IClientInventory_GetResultItems( ); }, [&](SteamItemDef_t* pItemDefIDs, uint32_t* punItemDefIDsArraySize) { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetItemDefinitionIDs) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetItemDefinitionIDs) return IClientInventory_GetItemDefinitionIDs_o( ARGS(pItemDefIDs, *punItemDefIDsArraySize, punItemDefIDsArraySize) @@ -51,7 +51,7 @@ VIRTUAL(bool) IClientInventory_GetResultItemProperty( ) { return steam_inventory::GetResultItemProperty( __func__, resultHandle, unItemIndex, pchPropertyName, pchValueBuffer, punValueBufferSizeOut, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetResultItemProperty) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetResultItemProperty) *punValueBufferSizeOut = item_count; return IClientInventory_GetResultItemProperty_o( @@ -68,7 +68,7 @@ VIRTUAL(bool) IClientInventory_CheckResultSteamID( ) ) { return steam_inventory::CheckResultSteamID(__func__, resultHandle, steamIDExpected, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_CheckResultSteamID) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_CheckResultSteamID) return IClientInventory_CheckResultSteamID_o(ARGS(resultHandle, steamIDExpected)); }); @@ -76,7 +76,7 @@ VIRTUAL(bool) IClientInventory_CheckResultSteamID( VIRTUAL(bool) IClientInventory_GetAllItems(PARAMS(SteamInventoryResult_t* pResultHandle)) { return steam_inventory::GetAllItems(__func__, pResultHandle, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetAllItems) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetAllItems) return IClientInventory_GetAllItems_o(ARGS(pResultHandle)); }); @@ -90,7 +90,7 @@ VIRTUAL(bool) IClientInventory_GetItemsByID( ) ) { return steam_inventory::GetItemsByID(__func__, pResultHandle, pInstanceIDs, unCountInstanceIDs, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetItemsByID) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetItemsByID) return IClientInventory_GetItemsByID_o(ARGS(pResultHandle, pInstanceIDs, unCountInstanceIDs)); }); @@ -105,7 +105,7 @@ VIRTUAL(bool) IClientInventory_SerializeResult( ) ) { return steam_inventory::SerializeResult(__func__, resultHandle, pOutBuffer, punOutBufferSize, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_SerializeResult) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_SerializeResult) *punOutBufferSize = buffer_size; return IClientInventory_SerializeResult_o(ARGS(resultHandle, pOutBuffer, buffer_size, punOutBufferSize)); @@ -120,7 +120,7 @@ VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs( ) ) { return steam_inventory::GetItemDefinitionIDs(__func__, pItemDefIDs, p_array_size, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientInventory_GetItemDefinitionIDs) + GET_ORIGINAL_HOOKED_FUNCTION(IClientInventory_GetItemDefinitionIDs) *p_array_size = item_count; return IClientInventory_GetItemDefinitionIDs_o(ARGS(pItemDefIDs, item_count, p_array_size)); diff --git a/src/steamclient_virtuals/client_user.cpp b/src/steamclient_virtuals/client_user.cpp index bef1764..925f421 100644 --- a/src/steamclient_virtuals/client_user.cpp +++ b/src/steamclient_virtuals/client_user.cpp @@ -5,7 +5,7 @@ using namespace smoke_api; VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t app_id)) { return steam_apps::IsDlcUnlocked(__func__, 0, app_id, [&]() { - GET_ORIGINAL_VIRTUAL_FUNCTION(IClientUser_BIsSubscribedApp) + GET_ORIGINAL_HOOKED_FUNCTION(IClientUser_BIsSubscribedApp) return IClientUser_BIsSubscribedApp_o(ARGS(app_id)); });