From a3b3a5e84d63e766bf7187693f6e1bd15f808b74 Mon Sep 17 00:00:00 2001 From: praydog Date: Fri, 20 Oct 2023 20:35:29 -0700 Subject: [PATCH] SDK: Add initial UObjectBase::get_destructor --- shared/sdk/UObjectBase.cpp | 67 ++++++++++++++++++++++++++++++++++++++ shared/sdk/UObjectBase.hpp | 2 ++ 2 files changed, 69 insertions(+) diff --git a/shared/sdk/UObjectBase.cpp b/shared/sdk/UObjectBase.cpp index af570c05..48faad0f 100644 --- a/shared/sdk/UObjectBase.cpp +++ b/shared/sdk/UObjectBase.cpp @@ -7,6 +7,7 @@ #include "UClass.hpp" #include "UObjectArray.hpp" #include "UObjectBase.hpp" +#include "UObject.hpp" namespace sdk { void UObjectBase::update_offsets() { @@ -175,6 +176,72 @@ void UObjectBase::update_process_event_index() try { SPDLOG_ERROR("[UObjectBase] Failed to update ProcessEvent index"); } +std::optional UObjectBase::get_destructor() { + static auto result = []() -> std::optional { + SPDLOG_INFO("[UObjectBase] Searching for destructor..."); + + const auto uobject_class = sdk::UObject::static_class(); + + if (uobject_class == nullptr) { + SPDLOG_ERROR("[UObjectBase] Failed to find UObject class, cannot find destructor"); + return {}; + } + + const auto default_object = uobject_class->get_class_default_object(); + + if (default_object == nullptr) { + SPDLOG_ERROR("[UObjectBase] Failed to find default UObject, cannot find destructor"); + return {}; + } + + const auto uobject_vtable = *(void***)default_object; + + if (uobject_vtable == nullptr || IsBadReadPtr(uobject_vtable, sizeof(void*))) { + SPDLOG_ERROR("[UObjectBase] Failed to find UObject vtable, cannot find destructor"); + return {}; + } + + const auto uobject_destructor = uobject_vtable[0]; + + if (uobject_destructor == nullptr || IsBadReadPtr(uobject_destructor, sizeof(void*))) { + SPDLOG_ERROR("[UObjectBase] Failed to find UObject destructor, cannot find destructor"); + return {}; + } + + // Now we need to exhaustively decode the destructor, looking for a call to the destructor of parent class + std::optional out{}; + + utility::exhaustive_decode((uint8_t*)uobject_destructor, 100, [&](utility::ExhaustionContext& ctx) -> utility::ExhaustionResult { + if (out) { + return utility::ExhaustionResult::BREAK; + } + + if (ctx.instrux.BranchInfo.IsBranch) { + return utility::ExhaustionResult::CONTINUE; + } + + const auto disp = utility::resolve_displacement(ctx.addr); + + if (disp && *disp != (uintptr_t)uobject_vtable) { + out = ctx.branch_start; + return utility::ExhaustionResult::BREAK; + } + + return utility::ExhaustionResult::CONTINUE; + }); + + if (out) { + SPDLOG_INFO("[UObjectBase] Found destructor at 0x{:X}", *out); + } else { + SPDLOG_ERROR("[UObjectBase] Failed to find destructor"); + } + + return out; + }(); + + return result; +} + std::wstring UObjectBase::get_full_name() const { auto c = get_class(); diff --git a/shared/sdk/UObjectBase.hpp b/shared/sdk/UObjectBase.hpp index 92d2f1d7..2b4eb572 100644 --- a/shared/sdk/UObjectBase.hpp +++ b/shared/sdk/UObjectBase.hpp @@ -38,6 +38,8 @@ class UObjectBase { return s_outer_private_offset + sizeof(void*); } + static std::optional get_destructor(); + private: using ProcessEventFn = void(*)(UObjectBase*, UFunction*, void*); static void update_process_event_index();