Skip to content

Commit

Permalink
SDK: Bruteforce FArray/FObjectProperty offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Oct 28, 2023
1 parent d7fa6fa commit 5c65ef9
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,12 @@ list(APPEND sdk_SOURCES
"shared/sdk/ConsoleManager.cpp"
"shared/sdk/DynamicRHI.cpp"
"shared/sdk/EngineModule.cpp"
"shared/sdk/FArrayProperty.cpp"
"shared/sdk/FBoolProperty.cpp"
"shared/sdk/FField.cpp"
"shared/sdk/FMalloc.cpp"
"shared/sdk/FName.cpp"
"shared/sdk/FObjectProperty.cpp"
"shared/sdk/FProperty.cpp"
"shared/sdk/FRenderTargetPool.cpp"
"shared/sdk/FSceneView.cpp"
Expand Down Expand Up @@ -360,11 +362,13 @@ list(APPEND sdk_SOURCES
"shared/sdk/ConsoleManager.hpp"
"shared/sdk/DynamicRHI.hpp"
"shared/sdk/EngineModule.hpp"
"shared/sdk/FArrayProperty.hpp"
"shared/sdk/FBoolProperty.hpp"
"shared/sdk/FField.hpp"
"shared/sdk/FFieldClass.hpp"
"shared/sdk/FMalloc.hpp"
"shared/sdk/FName.hpp"
"shared/sdk/FObjectProperty.hpp"
"shared/sdk/FProperty.hpp"
"shared/sdk/FRenderTargetPool.hpp"
"shared/sdk/FSceneView.hpp"
Expand Down
67 changes: 67 additions & 0 deletions shared/sdk/FArrayProperty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <windows.h>
#include <spdlog/spdlog.h>

#include "UClass.hpp"
#include "UObjectArray.hpp"
#include "FObjectProperty.hpp"

#include "FArrayProperty.hpp"

namespace sdk {
void FArrayProperty::update_offsets() {
if (s_offsets_updated) {
return;
}

s_offsets_updated = true;

SPDLOG_INFO("[FArrayProperty::update_offsets] Updating offsets");

const auto scene_component = sdk::find_uobject<UClass>(L"Class /Script/Engine.SceneComponent");

if (scene_component == nullptr) {
SPDLOG_ERROR("[FArrayProperty::update_offsets] Failed to find SceneComponent");
return;
}

const auto attach_children = scene_component->find_property(L"AttachChildren");

if (attach_children == nullptr) {
SPDLOG_ERROR("[FArrayProperty::update_offsets] Failed to find AttachChildren");
return;
}

// Start from FProperty's offset offset, and bruteforce until we find the correct offset
const auto initial_start = FProperty::s_offset_offset + 4 + sizeof(void*) + sizeof(void*);
// align up to sizeof(void*)
const auto start = (initial_start + sizeof(void*) - 1) & ~(sizeof(void*) - 1);

for (auto i = start; i < start + 0x100; i += sizeof(void*)) try {
const auto value = *(FProperty**)(attach_children + i);

if (value == nullptr || IsBadReadPtr(value, sizeof(void*))) {
continue;
}

const auto c = value->get_class();

if (c == nullptr || IsBadReadPtr(c, sizeof(void*))) {
continue;
}

if (c->get_name().to_string() == L"ObjectProperty") {
auto prop = (FObjectProperty*)value;

if (prop->get_property_class() == scene_component) {
s_inner_offset = i;
SPDLOG_INFO("[FArrayProperty::update_offsets] Found property inner offset: 0x{:X}", i);
break;
}
}
} catch(...) {
continue;
}

SPDLOG_INFO("[FArrayProperty::update_offsets] Done");
}
}
18 changes: 18 additions & 0 deletions shared/sdk/FArrayProperty.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "FProperty.hpp"

namespace sdk {
class FArrayProperty : public FProperty {
public:
static void update_offsets();

FProperty* get_inner() const {
return *(FProperty**)((uintptr_t)this + s_inner_offset);
}

private:
static inline bool s_offsets_updated{false};
static inline uint32_t s_inner_offset{0x0};
};
}
53 changes: 53 additions & 0 deletions shared/sdk/FObjectProperty.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <windows.h>
#include <spdlog/spdlog.h>

#include "UClass.hpp"
#include "UObjectArray.hpp"

#include "FObjectProperty.hpp"

namespace sdk {
void FObjectProperty::update_offsets() {
if (s_offsets_updated) {
return;
}

s_offsets_updated = true;

SPDLOG_INFO("[FObjectProperty::update_offsets] Updating offsets");

const auto scene_component = sdk::find_uobject<UClass>(L"Class /Script/Engine.SceneComponent");

if (scene_component == nullptr) {
SPDLOG_ERROR("[FObjectProperty::update_offsets] Failed to find SceneComponent");
return;
}

const auto attach_parent = scene_component->find_property(L"AttachParent");

if (attach_parent == nullptr) {
SPDLOG_ERROR("[FObjectProperty::update_offsets] Failed to find AttachParent");
return;
}

// Start from FProperty's offset offset, and bruteforce until we find the correct offset
const auto initial_start = FProperty::s_offset_offset + 4 + sizeof(void*) + sizeof(void*);
// align up to sizeof(void*)
const auto start = (initial_start + sizeof(void*) - 1) & ~(sizeof(void*) - 1);

for (auto i = start; i < start + 0x100; i += sizeof(void*)) try {
const auto value = *(UClass**)(attach_parent + i);

// well this is easy!
if (value == scene_component) {
s_property_class_offset = i;
SPDLOG_INFO("[FObjectProperty::update_offsets] Found property class offset: 0x{:X}", i);
break;
}
} catch(...) {
continue;
}

SPDLOG_INFO("[FObjectProperty::update_offsets] Done");
}
}
20 changes: 20 additions & 0 deletions shared/sdk/FObjectProperty.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "FProperty.hpp"

namespace sdk {
class UClass;

class FObjectProperty : public FProperty {
public:
static void update_offsets();

UClass* get_property_class() const {
return *(UClass**)((uintptr_t)this + s_property_class_offset);
}

private:
static inline bool s_offsets_updated{false};
static inline uint32_t s_property_class_offset{0x0};
};
}
4 changes: 4 additions & 0 deletions shared/sdk/UObjectArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "FField.hpp"
#include "FStructProperty.hpp"
#include "FBoolProperty.hpp"
#include "FObjectProperty.hpp"
#include "FArrayProperty.hpp"
#include "UObjectArray.hpp"

namespace sdk {
Expand Down Expand Up @@ -389,6 +391,8 @@ FUObjectArray* FUObjectArray::get() try {
sdk::UProperty::update_offsets();
sdk::FStructProperty::update_offsets();
sdk::FBoolProperty::update_offsets();
sdk::FObjectProperty::update_offsets();
sdk::FArrayProperty::update_offsets();

#ifdef TESTING_GUOBJECTARRAY
try {
Expand Down

0 comments on commit 5c65ef9

Please sign in to comment.