Skip to content

Commit

Permalink
Convert offsets into patterns.
Browse files Browse the repository at this point in the history
  • Loading branch information
EusthEnoptEron committed Dec 14, 2021
1 parent bb54adc commit ffe48a3
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 18 deletions.
23 changes: 16 additions & 7 deletions Mod/MultiplayerModeCore/MultiplayerMod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@


FNativeFuncPtr* MultiplayerMod::GNatives;

float* MultiplayerMod::GNearClippingPlane;
float MultiplayerMod::GNearOriginal;

UE4::UClass* FastGetClass(UE4::UObject* obj) {
return (UE4::UClass*)((SDK::UObject*)(obj))->Class;
Expand Down Expand Up @@ -589,8 +590,20 @@ void MultiplayerMod::InitializeMod()

SetupHooks();

auto offset = (DWORD64)GetModuleHandleW(0);
GNatives = (FNativeFuncPtr*)((DWORD64)(offset + 0x4BC4D80));
// 0x42784DC
auto nearClippingPlanePat = Pattern::Find("66 0F 6E C7 0F 5B C0 0F 2E 05 ?? ?? ?? ??");
auto nearClippingPlaneOff = *reinterpret_cast<uint32_t*>(nearClippingPlanePat + 10);
GNearClippingPlane = (float*)(nearClippingPlanePat + 14 + nearClippingPlaneOff);

GNearOriginal = *GNearClippingPlane;
Log::Info("Found near clipping plane at %p (%f)", GNearClippingPlane, *GNearClippingPlane);

// 0x4BD9F90
auto gnativePat = Pattern::Find("CC 80 3D ?? ?? ?? ?? 00 48 8D 15 ?? ?? ?? ?? 75 49 C6 05 ?? ?? ?? ?? 01 48 8D 05 ?? ?? ?? ??");
auto gnativeOff = *reinterpret_cast<uint32_t*>(gnativePat + 27);
GNatives = (FNativeFuncPtr*)(gnativePat + 31 + gnativeOff);
Log::Info("Found GNatives at %p", GNatives);

//Log::Info("GNatives: %p", GNatives[1]);

//Function Arise.BtlInputExtInputProcessBase.K2_IsBtlButtonJustPressed
Expand Down Expand Up @@ -1042,10 +1055,6 @@ void MultiplayerMod::OnAfterVirtualFunction(UE4::UObject* Context, UE4::FFrame&

}

// FF FF FF FF ?? ?? ?? ?? 84 3C EB F0 F7 7F 00 00 20 46 21 F1
static float* GNearClippingPlane = (float*)((DWORD64)GetModuleHandleW(0) + 0x42644E4);
static float GNearOriginal = *GNearClippingPlane;

void MultiplayerMod::SetNearClippingPlane(float nearPlane) {
//Log::Info("Near Plane: %f (%p)", nearPlane, GNearClippingPlane);
*GNearClippingPlane = nearPlane;
Expand Down
4 changes: 3 additions & 1 deletion Mod/MultiplayerModeCore/MultiplayerMod.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "../SDK/TO14_BPI_GUI_MNU_SAV_classes.h"
#include "FileWatch.hpp"

typedef void (*FNativeFuncPtr)(UE4::UObject* Context, UE4::FFrame& Stack, void *result);
typedef void (*FNativeFuncPtr)(UE4::UObject* Context, UE4::FFrame& Stack, void *result);
struct FScriptName {
/** Index into the Names array (used to find String portion of the string/number pair used for comparison) */
int32 ComparisonIndex;
Expand Down Expand Up @@ -190,6 +190,8 @@ class MultiplayerMod : public Mod
void OnAfterVirtualFunction(UE4::UObject* Context, UE4::FFrame& Stack, void* ret);

static FNativeFuncPtr *GNatives;
static float* GNearClippingPlane;
static float GNearOriginal;

GamepadState OldStates[4] = { 0 };
GamepadState NewStates[4] = { 0 };
Expand Down
92 changes: 83 additions & 9 deletions Mod/MultiplayerModeCore/Tracer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,61 @@ void EX_FinalFunctionHook(UE4::UObject* Context, UE4::FFrame& Stack, void* resul
auto fn = (SDK::UFunction *)TempCode;

auto fnName = Context->GetName() + "::" + fn->GetName();
std::string params = "(";

tracer->OnEnter(fnName);

if (fn != nullptr && fn->NumParms > 0 && (((UPropertyEx*)fn->Children)->PropertyFlags & CPF_ReturnParm) == 0) {
auto SaveCode = Stack.Code;

uint8* memory = (uint8 *)calloc(1, fn->PropertySize);
//Log::Info("Created memory: %p (%d)", memory, fn->PropertySize);

// Step over function pointer
Stack.Code += sizeof(uint64_t);
//Log::Info(fnName);
for (auto Property = (UPropertyEx*)fn->Children; *Stack.Code != EX_EndFunctionParms; Property = (UPropertyEx*)Property->Next)
{
//Log::Info("%d", (int32)*Stack.Code);
Stack.MostRecentPropertyAddress = NULL;

// Skip the return parameter case, as we've already handled it above
const bool bIsReturnParam = ((Property->PropertyFlags & CPF_ReturnParm) != 0);
if (bIsReturnParam)
{
continue;
}

int32 B = *Stack.Code++;
if (Property->PropertyFlags & CPF_OutParm)
{
MultiplayerMod::GNatives[B](Stack.Object, Stack, NULL);
}
else {
auto addr = memory + Property->Offset_Internal;

if(Property->PropertyFlags & CPF_ZeroConstructor) {
//Log::Info("Reset: %p (%d)", addr, Property->ArrayDim * Property->ElementSize);
memset(addr, 0, Property->ArrayDim * Property->ElementSize);
}
else {
// InitializeValueInternal(ContainerPtrToValuePtr<void>(Dest));
//Log::Info("OH SHIT");
}

//Log::Info("b:%p (%d) (%p) (%s)", addr, (int64)Property->ArrayDim * Property->ElementSize, MultiplayerMod::GNatives[B], Property->GetName().c_str());
MultiplayerMod::GNatives[B](Stack.Object, Stack, addr);
params += tracer->ToString((SDK::UProperty*)Property, memory) + ", ";
//Log::Info("a:ok");
}
}

Stack.Code = SaveCode;
free(memory);
}

params += ")";

tracer->OnEnter(fnName + params);
auto begin = std::chrono::high_resolution_clock::now();
EX_FinalFunction(Context, Stack, result);
auto end = std::chrono::high_resolution_clock::now();
Expand All @@ -78,7 +131,7 @@ void EX_FinalFunctionHook(UE4::UObject* Context, UE4::FFrame& Stack, void* resul
}


tracer->OnExit(fnName, "", std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count());
tracer->OnExit(fnName, suffix, std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count());
}


Expand All @@ -105,18 +158,18 @@ void Tracer::OnExit(std::string functionName, std::string suffix, long durationN
// Counter changed, so we had child instructions
_file << std::string(_instructionStack.size() * 2, ' ');
_file << "End " << functionName << " (";
_file << suffix;
_file << (durationNano * 1.0E-6);
_file << "ms)";
_file << suffix;
_file << "\n";
}
else {
// Counter didn't change, so put on same line
_file.seekp(-2, _file.cur);
_file << suffix;
_file << " (";
_file << (durationNano * 1.0E-6);
_file << "ms)";
_file << suffix;
_file << "\n";
}

Expand Down Expand Up @@ -163,8 +216,9 @@ void Tracer::OnEvent(std::string evt) {

void Tracer::Hook()
{
auto offset = (DWORD64)GetModuleHandleW(0);
_GNatives = (FNativeFuncPtr*)((DWORD64)(offset + 0x4BC4D80));
//auto offset = (DWORD64)GetModuleHandleW(0);
//_GNatives = (FNativeFuncPtr*)((DWORD64)(offset + 0x4BC4D80));
_GNatives = MultiplayerMod::GNatives;


MinHook::Add((DWORD_PTR)_GNatives[0x1B],
Expand Down Expand Up @@ -207,6 +261,8 @@ void Tracer::Hook()


std::string Tracer::ToString(SDK::UProperty* prop, void *result) {
if (result == nullptr) return "NULL";

//Log::Info("=> %s", Property->Class->GetName());
if (prop->IsA(SDK::UBoolProperty::StaticClass())) {
return (*(bool*)result) ? "true" : "false";
Expand All @@ -224,13 +280,31 @@ std::string Tracer::ToString(SDK::UProperty* prop, void *result) {
return prop->Class->GetName();
}
else if (prop->IsA(SDK::UObjectProperty::StaticClass())) {
return (*(SDK::UObject**)result)->GetName();
if (*(SDK::UObject**)result != nullptr) {
auto name = (*(SDK::UObject**)result)->Name;
return name.GetName();
}
else {
return "NULL";
}
}
else if (prop->IsA(SDK::UStrProperty::StaticClass())) {
return ((SDK::FString*)result)->ToString();
auto str = (SDK::FString*)result;
if (str->IsValid()) {
return str->ToString();
}
else {
return "";
}
}
/*else if (prop->IsA(SDK::UNameProperty::StaticClass())) {
return ((SDK::FName*)result)->GetName();
}*/
else if (prop->IsA(SDK::UEnumProperty::StaticClass())) {
return ToString(((UEnumPropertyEx*)prop)->UnderlyingProp, result);
}
else {
return prop->Class->GetName();
return "???";
}
//fnName = fnName + " => ???";
//break;
Expand Down
21 changes: 20 additions & 1 deletion Mod/MultiplayerModeCore/Tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

const uint64_t CPF_Parm = 0x0000000000000080;
const uint64_t CPF_ReturnParm = 0x0000000000000400;
const uint64_t CPF_OutParm = 0x0000000000000100;
const uint64_t CPF_ZeroConstructor = 0x0000000000000200;
const uint8_t EX_EndFunctionParms = 0x16;
const uint8_t FUNC_Native = 0x00000400;

struct UPropertyEx : SDK::UField {
public:
Expand All @@ -17,10 +21,25 @@ struct UPropertyEx : SDK::UField {
uint64 PropertyFlags;
uint16 RepIndex;

unsigned char UnknownData00[46]; // 0x0030(0x0040) MISSED OFFSET
uint8 BlueprintReplicationCondition;
int32 Offset_Internal;

unsigned char UnknownData00[41]; // 0x0030(0x0040) MISSED OFFSET

};

struct UEnumPropertyEx : UPropertyEx {
public:
SDK::UNumericProperty* UnderlyingProp; // The property which represents the underlying type of the enum
SDK::UEnum* Enum; //
};

struct UStructPropertyEx : UPropertyEx {
public:
SDK::UScriptStruct* Struct; //
};


template <typename CT, typename ... A> struct function
: public function<decltype(&CT::operator())(A...)> {};

Expand Down

0 comments on commit ffe48a3

Please sign in to comment.