Skip to content

Commit

Permalink
Main
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickBakin committed Feb 17, 2023
0 parents commit 69037c6
Show file tree
Hide file tree
Showing 16 changed files with 2,586 additions and 0 deletions.
34 changes: 34 additions & 0 deletions Headers/Basic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once
namespace Basic
{
template<class T>
class TArray
{
public:
T* Data;
int Count;
int Max;
};

class FString : public TArray<wchar_t>
{
public:

inline const wchar_t* c_str() const
{
return Data;
}

std::string ToString() const
{
const auto length = std::wcslen(Data);

std::string str(length, '\0');

std::use_facet<std::ctype<wchar_t>>(std::locale()).narrow(Data, Data + length, '?', &str[0]);

return str;
}
};

}
181 changes: 181 additions & 0 deletions Headers/FunctionFinders.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#pragma once
#include "aLgorithm.h"

namespace FunctionFinder
{
class FindFunctions
{
public:
bool static GetFunctions(ProfileGen& PG)
{
MEMORY_BASIC_INFORMATION memInfo;
bool LoadFound=false,SpawnFound=false,
CallFuncFound=false,InitGameFound=false,ActorBeginFound=false,ProcessEventFound=false;
for (char *p = (char *)moduleInfo.lpBaseOfDll;p < (char *)moduleInfo.lpBaseOfDll + moduleInfo.SizeOfImage;p += memInfo.RegionSize)
{
SIZE_T size = VirtualQueryEx(hProcess, p, &memInfo, sizeof(memInfo));
if (size == 0)
{

std::cerr << "VirtualQueryEx failed" << std::endl;
continue;
}
auto RegSize = memInfo.RegionSize;
std::vector<BYTE> buffer(RegSize); //buffer size is region size Store in Bytes
if (ReadProcessMemory(hProcess, memInfo.BaseAddress, buffer.data(), RegSize, NULL)/* && bytesRead == size*/)
{
if( !LoadFound && GetStaticLoadObjectAddress(buffer,memInfo.BaseAddress,PG))
{
LoadFound=true;
}

if(!SpawnFound && GetSpawnActorAddress(buffer,memInfo.BaseAddress,PG) )
{
SpawnFound=true;
}
if(!CallFuncFound && GetCallFunctionByNameWithArgumentsAddress(buffer,memInfo.BaseAddress,PG) )
{
CallFuncFound=true;
}
if(!InitGameFound &&GetInitGameStateAddress(buffer,memInfo.BaseAddress,PG) )
{
InitGameFound=true;
}
if(!ActorBeginFound && GetActorBeginPlayAddress(buffer,memInfo.BaseAddress,PG) )
{
ActorBeginFound=true;
}
if(!ProcessEventFound &&GetProcessEventAddress(buffer,memInfo.BaseAddress,PG) )
{
ProcessEventFound=true;
}


}

}
if(LoadFound && SpawnFound && CallFuncFound && InitGameFound && ActorBeginFound && ProcessEventFound)
{
return true;
}
return false;
}
private:
int64_t static GetStaticLoadObjectAddress(std::vector<BYTE>& buffer,void* Address,ProfileGen& PG)
{
if(auto StringAddr=Algorithm::ScanforStringRef(buffer,L"Failed to find object '{ClassName} {OuterName}.{ObjectName}'",reinterpret_cast<int64_t>(Address),0x3,"String Ref UObject::StaticLoadObject()"))
{
auto pushStaticLoad =Algorithm::ScanFor(StringAddr,{/*0xCC,*/0x41,0x56,0x41,0x57,0x48},true);
auto StaticLoadObjectAddr = Algorithm::ScanFor(pushStaticLoad,{0x40,0x55},true,12);
std::cout << "StaticLoadObject: 0x"<<std::hex<<StaticLoadObjectAddr<<std::endl;
PG.GetProfile().StaticLoadObjectOffset=StaticLoadObjectAddr-reinterpret_cast<int64_t>(BaseAddress);
return StaticLoadObjectAddr;
}

return 0;
}
int64_t static GetSpawnActorAddress(std::vector<BYTE>& buffer ,void* Address,ProfileGen& PG)
{
if(auto StringAddr = Algorithm::ScanforStringRef(buffer,L"SpawnActor failed.",reinterpret_cast<int64_t>(Address),0x3,"String Ref UWorld::SpawnActor(UClass *,FTransform*..."))
{


auto CallFunctionSpawnActor = Algorithm::ScanFor(StringAddr,{0xE8},true,20);
auto relative = Algorithm::ReadAs<int32_t>(CallFunctionSpawnActor+1);
auto FunctionSpawnactorAddr= CallFunctionSpawnActor+relative+0x5;
if(PG.GetProfile().EngineVersion/100<=408)
{
std::cout <<"Version is Too Old! Using SpawnActorFVector instead\n"<< "SpawnActorFVector: 0x"<<std::hex<<FunctionSpawnactorAddr<<std::endl;
PG.GetProfile().SpawnActorFTransOffset=FunctionSpawnactorAddr-reinterpret_cast<int64_t>(BaseAddress);
return FunctionSpawnactorAddr;
}
Algorithm::CheckNSkipJump(FunctionSpawnactorAddr,FunctionSpawnactorAddr);
auto retnAddr = Algorithm::ScanFor(FunctionSpawnactorAddr,{0x5B,0xC3},false,192);
auto CallFunctionSpawnActorTransform = Algorithm::ScanFor(retnAddr,{0xE8,0xFF,0xFF,0xFF,0xFF,0x48,0xFF,0xFF,0xFF,0xFF,0x48},true,30);
auto relative1 = Algorithm::ReadAs<int32_t>(CallFunctionSpawnActorTransform+1);
auto FunctionSpawnActorTransformAddr = CallFunctionSpawnActorTransform+relative1+0x5;
Algorithm::CheckNSkipJump(FunctionSpawnActorTransformAddr,FunctionSpawnActorTransformAddr);
std::cout << "SpawnActorFTransform: 0x"<<std::hex<<FunctionSpawnActorTransformAddr<<std::endl;
PG.GetProfile().SpawnActorFTransOffset=FunctionSpawnActorTransformAddr-reinterpret_cast<int64_t>(BaseAddress);
return FunctionSpawnActorTransformAddr;

}
return 0;
}

int64_t static GetCallFunctionByNameWithArgumentsAddress(std::vector<BYTE>& buffer,void* Address,ProfileGen& PG)
{
if(auto StringAddr = Algorithm::ScanforStringRef(buffer,L"'{Message}': Bad or missing property '{PropertyName}'",reinterpret_cast<int64_t>(Address),0x3,"String Ref UObject::CallFunctionByNameWithArguments()"))
{
auto pushCallFunctionByNameWithArguments = Algorithm::ScanFor(StringAddr,{0x41,0x56,0x41,0x57,0x48},true);
auto CallFunctionByNameWithArgumentsAddr = Algorithm::ScanFor(pushCallFunctionByNameWithArguments,{0x40,0x55},true,0x40);
std::cout << "CallFunctionByNameWithArguments: 0x"<<std::hex<<CallFunctionByNameWithArgumentsAddr<<std::endl;
PG.GetProfile().CallFunctionByNameWithArgumentsOffset=CallFunctionByNameWithArgumentsAddr-reinterpret_cast<int64_t>(BaseAddress);
return CallFunctionByNameWithArgumentsAddr;
}
return 0;


}
int64_t static GetInitGameStateAddress(std::vector<BYTE>& buffer,void* Address,ProfileGen& PG)
{
auto Begin=Algorithm::searchArray(buffer,{0x40,0x53,0x48,0x83,0xEC,0x20,0x48,0x8B,0x41,0x10,0x48,0x8B,0xD9,0x48,0x8B,0x91},false);
if(Begin!=-1)
{

auto InitGameStateFunctionAddr = reinterpret_cast<int64_t>(Address)+Begin;
std::cout<< "InitGameState: 0x"<<std::hex<<InitGameStateFunctionAddr<<std::endl;
PG.GetProfile().GameStateInitOffset=InitGameStateFunctionAddr-reinterpret_cast<int64_t>(BaseAddress);
return InitGameStateFunctionAddr;
}

//Need to find a better pattern or stringref?
Begin =Algorithm::searchArray(buffer,{0x48,0xFF, 0xFF, 0xFF ,0x90 ,0xFF,0xFF,0xFF, 0xFF, 0x48,0x8B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48 ,0x8B ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0x48, 0x89 ,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48 ,0x8B},false);

if(Begin!=-1)
{
auto movInitGameStateAddrr = reinterpret_cast<int64_t>(Address)+Begin;
auto InitGameStateFunctionAddr = Algorithm::ScanFor(movInitGameStateAddrr,{0x40,0x53},true,100);
std::cout << "InitGameState: 0x"<<std::hex<<InitGameStateFunctionAddr<<std::endl;
PG.GetProfile().GameStateInitOffset=InitGameStateFunctionAddr-reinterpret_cast<int64_t>(BaseAddress);
return InitGameStateFunctionAddr;
}

return 0;
}
int64_t static GetActorBeginPlayAddress(std::vector<BYTE>& buffer,void* Address,ProfileGen& PG)
{
auto Begin =Algorithm::searchArray(buffer,{0x48,0x8B,0xD9,0xE8,0xFF,0xFF ,0xFF , 0xFF , 0xF6 ,0x83 ,0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x74,0x12,0x48,0x8B ,0x03},false);
if(Begin!=-1)
{
auto CallBeginPlay = reinterpret_cast<int64_t>(Address)+Begin+0x3;

auto ActorBeginPlayFuncAddr = CallBeginPlay+Algorithm::ReadAs<int32_t>(CallBeginPlay+0x1)+0x5;
Algorithm::CheckNSkipJump(ActorBeginPlayFuncAddr,ActorBeginPlayFuncAddr);
std::cout << "ActorBeginPlay: 0x"<<std::hex<<ActorBeginPlayFuncAddr<<std::endl;
PG.GetProfile().BeginPlayOffset=ActorBeginPlayFuncAddr-reinterpret_cast<int64_t>(BaseAddress);
return ActorBeginPlayFuncAddr;
}
return 0;
}
int64_t static GetProcessEventAddress(std::vector<BYTE>& buffer,void* Address,ProfileGen& PG)
{
auto Begin=Algorithm::searchArray(buffer,{0x75,0x0E,0xFF,0xFF, 0xFF, 0x48,0xFF,0xFF, 0x48 ,0xFF, 0xFF, 0xE8 ,0xFF, 0xFF, 0xFF, 0xFF, 0x48,0x8B,0xFF, 0x24,0xFF, 0x48 ,0x8B ,0xFF, 0x24,0x38, 0x48, 0x8B, 0xFF, 0x24, 0x40},false);
if(Begin!=-1)
{
auto MovB4ProcessEvent = reinterpret_cast<int64_t>(Address)+Begin;
auto CallProcessEvent = Algorithm::ScanFor(MovB4ProcessEvent,{0xE8},false,16);
auto ProcessEventFuncAddr = CallProcessEvent + Algorithm::ReadAs<int32_t>(CallProcessEvent+0x1)+0x5;
Algorithm::CheckNSkipJump(ProcessEventFuncAddr,ProcessEventFuncAddr);
std::cout << "ProcessEvent: 0x"<<std::hex<<ProcessEventFuncAddr<<std::endl;
PG.GetProfile().ProcessEventOffset=ProcessEventFuncAddr-reinterpret_cast<int64_t>(BaseAddress);
return ProcessEventFuncAddr;
}
return 0;
}

};



}
6 changes: 6 additions & 0 deletions Headers/Globals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

extern HMODULE hExeModule;
extern void* BaseAddress;
extern HANDLE hProcess;
extern MODULEINFO moduleInfo;
Loading

0 comments on commit 69037c6

Please sign in to comment.