Skip to content

Commit

Permalink
SDK: Add initial IConsoleManager scanner
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed May 31, 2023
1 parent d9805a9 commit 6cbdd7e
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ set(sdk_SOURCES "")

list(APPEND sdk_SOURCES
"shared/sdk/CVar.cpp"
"shared/sdk/ConsoleManager.cpp"
"shared/sdk/DynamicRHI.cpp"
"shared/sdk/EngineModule.cpp"
"shared/sdk/FRenderTargetPool.cpp"
Expand All @@ -328,6 +329,7 @@ list(APPEND sdk_SOURCES
"shared/sdk/UGameViewportClient.cpp"
"shared/sdk/Utility.cpp"
"shared/sdk/CVar.hpp"
"shared/sdk/ConsoleManager.hpp"
"shared/sdk/DynamicRHI.hpp"
"shared/sdk/EngineModule.hpp"
"shared/sdk/FRenderTargetPool.hpp"
Expand Down Expand Up @@ -393,6 +395,7 @@ set(sdk-nolog_SOURCES "")

list(APPEND sdk-nolog_SOURCES
"shared/sdk/CVar.cpp"
"shared/sdk/ConsoleManager.cpp"
"shared/sdk/DynamicRHI.cpp"
"shared/sdk/EngineModule.cpp"
"shared/sdk/FRenderTargetPool.cpp"
Expand All @@ -406,6 +409,7 @@ list(APPEND sdk-nolog_SOURCES
"shared/sdk/UGameViewportClient.cpp"
"shared/sdk/Utility.cpp"
"shared/sdk/CVar.hpp"
"shared/sdk/ConsoleManager.hpp"
"shared/sdk/DynamicRHI.hpp"
"shared/sdk/EngineModule.hpp"
"shared/sdk/FRenderTargetPool.hpp"
Expand Down
93 changes: 93 additions & 0 deletions shared/sdk/ConsoleManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include <spdlog/spdlog.h>
#include <utility/Scan.hpp>

#include "EngineModule.hpp"

#include "ConsoleManager.hpp"

namespace sdk {
IConsoleManager* get_console_manager() {
static auto result = []() -> IConsoleManager** {
SPDLOG_INFO("Finding IConsoleManager...");

const auto core_module = sdk::get_ue_module(L"Core");
const auto r_dumping_movie_string = utility::scan_string(core_module, L"r.DumpingMovie");

if (!r_dumping_movie_string) {
SPDLOG_ERROR("Failed to find r.DumpingMovie string");
return nullptr;
}

const auto r_dumping_movie_stringref = utility::scan_displacement_reference(core_module, *r_dumping_movie_string);

if (!r_dumping_movie_stringref) {
SPDLOG_ERROR("Failed to find r.DumpingMovie stringref");
return nullptr;
}

SPDLOG_INFO("Found r.DumpingMovie stringref: {:x}", (uintptr_t)*r_dumping_movie_stringref);

const auto containing_function = utility::find_function_start_with_call(*r_dumping_movie_stringref);

if (!containing_function) {
SPDLOG_ERROR("Failed to find containing function");
return nullptr;
}

// Check how many references there are to this function, if it's greater than say... 20, this is
// IConsoleManager::SetupSingleton
// If not, we can just disassemble the function looking for references to global variables
const auto function_references = utility::scan_displacement_references(core_module, *containing_function, 20);

if (function_references.empty()) {
SPDLOG_ERROR("Failed to find any references to containing function");
return nullptr;
}

if (function_references.size() < 20) {
SPDLOG_ERROR("Found too few references to containing function");
return nullptr;
}

// Disassemble the function and look for references to global variables
std::unordered_map<uintptr_t, size_t> global_variable_references{};
std::optional<std::tuple<uintptr_t, size_t>> 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);

if (!displacement) {
return utility::ExhaustionResult::CONTINUE;
}

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;
});

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));

return (IConsoleManager**)std::get<0>(*highest_global_variable_reference);
}();

if (result == nullptr) {
return nullptr;
}

return *result;
}
}
7 changes: 7 additions & 0 deletions shared/sdk/ConsoleManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

namespace sdk {
class IConsoleManager;

IConsoleManager* get_console_manager();
}

0 comments on commit 6cbdd7e

Please sign in to comment.