From 5ba2f7dc1d807e2913e5ce7b3f9e2a819add3701 Mon Sep 17 00:00:00 2001 From: praydog Date: Sat, 10 Jun 2023 14:40:15 -0700 Subject: [PATCH] SDK: Fix case where IConsoleManager could fail to be found --- shared/sdk/ConsoleManager.cpp | 119 +++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/shared/sdk/ConsoleManager.cpp b/shared/sdk/ConsoleManager.cpp index 127f7162..c89bc8f0 100644 --- a/shared/sdk/ConsoleManager.cpp +++ b/shared/sdk/ConsoleManager.cpp @@ -1,78 +1,107 @@ #include #include #include +#include #include "EngineModule.hpp" #include "ConsoleManager.hpp" -namespace sdk { -FConsoleManager* FConsoleManager::get() { - static auto result = []() -> FConsoleManager** { - SPDLOG_INFO("Finding IConsoleManager..."); +namespace detail { +sdk::FConsoleManager** try_find_console_manager(const std::wstring& string_candidate) { + SPDLOG_INFO("Finding IConsoleManager..."); - const auto now = std::chrono::steady_clock::now(); + const auto now = std::chrono::steady_clock::now(); - const auto core_module = sdk::get_ue_module(L"Core"); - const auto r_dumping_movie_string = utility::scan_string(core_module, L"r.DumpingMovie"); + const auto core_module = sdk::get_ue_module(L"Core"); + const auto candidate_string = utility::scan_string(core_module, string_candidate.c_str()); - if (!r_dumping_movie_string) { - SPDLOG_ERROR("Failed to find r.DumpingMovie string"); - return nullptr; - } + if (!candidate_string) { + SPDLOG_ERROR("Failed to find {} string", utility::narrow(string_candidate)); + return nullptr; + } - const auto r_dumping_movie_stringref = utility::scan_displacement_reference(core_module, *r_dumping_movie_string); + const auto candidate_stringref = utility::scan_displacement_reference(core_module, *candidate_string); - if (!r_dumping_movie_stringref) { - SPDLOG_ERROR("Failed to find r.DumpingMovie stringref"); - return nullptr; - } + if (!candidate_stringref) { + SPDLOG_ERROR("Failed to find {} stringref", utility::narrow(string_candidate)); + return nullptr; + } - SPDLOG_INFO("Found r.DumpingMovie stringref: {:x}", (uintptr_t)*r_dumping_movie_stringref); + SPDLOG_INFO("Found {} stringref: {:x}", utility::narrow(string_candidate), (uintptr_t)*candidate_stringref); - const auto containing_function = utility::find_function_start_with_call(*r_dumping_movie_stringref); + const auto containing_function = utility::find_function_start_with_call(*candidate_stringref); - if (!containing_function) { - SPDLOG_ERROR("Failed to find containing function"); - return nullptr; + if (!containing_function) { + SPDLOG_ERROR("Failed to find containing function"); + return nullptr; + } + + // Disassemble the function and look for references to global variables + std::unordered_map global_variable_references{}; + std::optional> highest_global_variable_reference{}; + + utility::exhaustive_decode((uint8_t*)*containing_function, 20, [&](INSTRUX& ix, uintptr_t ip) -> utility::ExhaustionResult { + if (std::string_view{ix.Mnemonic}.starts_with("CALL")) { + return utility::ExhaustionResult::STEP_OVER; } - - // Disassemble the function and look for references to global variables - std::unordered_map global_variable_references{}; - std::optional> highest_global_variable_reference{}; - - utility::exhaustive_decode((uint8_t*)*containing_function, 20, [&](INSTRUX& ix, uintptr_t ip) -> utility::ExhaustionResult { - if (std::string_view{ix.Mnemonic}.starts_with("CALL")) { - return utility::ExhaustionResult::STEP_OVER; - } - const auto displacement = utility::resolve_displacement(ip); + const auto displacement = utility::resolve_displacement(ip); - if (!displacement) { - return utility::ExhaustionResult::CONTINUE; - } + if (!displacement) { + return utility::ExhaustionResult::CONTINUE; + } + // hinges on IConsoleManager actually being constructed and assigned + if (!IsBadReadPtr((void*)*displacement, sizeof(void*)) && !IsBadReadPtr(*(void**)*displacement, sizeof(void*))) { global_variable_references[*displacement]++; if (!highest_global_variable_reference || global_variable_references[*displacement] > std::get<1>(*highest_global_variable_reference)) { highest_global_variable_reference = std::make_tuple(*displacement, global_variable_references[*displacement]); } + } - return utility::ExhaustionResult::CONTINUE; - }); + return utility::ExhaustionResult::CONTINUE; + }); - if (!highest_global_variable_reference) { - SPDLOG_ERROR("Failed to find any references to global variables"); - return nullptr; - } + if (!highest_global_variable_reference) { + SPDLOG_ERROR("Failed to find any references to global variables"); + return nullptr; + } + + SPDLOG_INFO("Found IConsoleManager**: {:x}", (uintptr_t)std::get<0>(*highest_global_variable_reference)); + SPDLOG_INFO("Points to IConsoleManager*: {:x}", *(uintptr_t*)std::get<0>(*highest_global_variable_reference)); + + const auto diff = std::chrono::duration_cast(std::chrono::steady_clock::now() - now).count(); + SPDLOG_INFO("Took {}ms to find IConsoleManager", diff); + + return (sdk::FConsoleManager**)std::get<0>(*highest_global_variable_reference); +} +} + +namespace sdk { +FConsoleManager* FConsoleManager::get() { + static auto result = []() -> FConsoleManager** { + std::vector candidates { + L"r.DumpingMovie", + L"vr.pixeldensity" + }; - SPDLOG_INFO("Found IConsoleManager**: {:x}", (uintptr_t)std::get<0>(*highest_global_variable_reference)); - SPDLOG_INFO("Points to IConsoleManager*: {:x}", *(uintptr_t*)std::get<0>(*highest_global_variable_reference)); + const auto now = std::chrono::steady_clock::now(); - const auto diff = std::chrono::duration_cast(std::chrono::steady_clock::now() - now).count(); - SPDLOG_INFO("Took {}ms to find IConsoleManager", diff); + for (const auto& candidate : candidates) { + spdlog::info("Trying to find IConsoleManager with candidate: {}", utility::narrow(candidate)); + auto result = detail::try_find_console_manager(candidate); - return (FConsoleManager**)std::get<0>(*highest_global_variable_reference); + if (result) { + spdlog::info("Took {}ms to search through all candidates", std::chrono::duration_cast(std::chrono::steady_clock::now() - now).count()); + return result; + } + } + + spdlog::error("Failed to find IConsoleManager"); + + return nullptr; }(); if (result == nullptr) {