mirror of
https://github.com/ApfelTeeSaft/Starfall.git
synced 2026-08-26 19:33:39 +00:00
EOS support & fix 24.20 latest CL
This commit is contained in:
@@ -4,11 +4,18 @@
|
||||
namespace Starfall {
|
||||
namespace Globals {
|
||||
void* buf;
|
||||
void* EOSBuf;
|
||||
|
||||
void* tbuf;
|
||||
size_t tsize;
|
||||
|
||||
void* rbuf;
|
||||
size_t rsize;
|
||||
|
||||
void* EOSTextBuf;
|
||||
size_t EOSTextSize;
|
||||
|
||||
void* EOSRDataBuf;
|
||||
size_t EOSRDataSize;
|
||||
}
|
||||
};
|
||||
@@ -6,12 +6,20 @@ namespace Starfall {
|
||||
namespace Globals {
|
||||
extern void* buf;
|
||||
//extern size_t size;
|
||||
extern void* EOSBuf;
|
||||
|
||||
extern void* tbuf;
|
||||
extern size_t tsize;
|
||||
|
||||
extern void* rbuf;
|
||||
extern size_t rsize;
|
||||
|
||||
|
||||
extern void* EOSTextBuf;
|
||||
extern size_t EOSTextSize;
|
||||
|
||||
extern void* EOSRDataBuf;
|
||||
extern size_t EOSRDataSize;
|
||||
}
|
||||
using namespace Globals;
|
||||
};
|
||||
|
||||
+23
-7
@@ -26,18 +26,34 @@ namespace Starfall {
|
||||
}
|
||||
|
||||
buf = *(void**)(__readgsqword(0x60) + 0x10);
|
||||
EOSBuf = GetModuleHandleA("EOSSDK-Win64-Shipping.dll");
|
||||
if (!EOSBuf)
|
||||
EOSBuf = LoadLibraryA("EOSSDK-Win64-Shipping.dll");
|
||||
|
||||
auto section = pe_get_section((char*)buf, ".text");
|
||||
auto rsection = pe_get_section((char*)buf, ".rdata");
|
||||
{
|
||||
auto section = pe_get_section((char*)buf, ".text");
|
||||
auto rsection = pe_get_section((char*)buf, ".rdata");
|
||||
|
||||
tbuf = (void*)(__int64(buf) + section->virtualAddress);
|
||||
tsize = section->virtualSize;
|
||||
tbuf = (void*)(__int64(buf) + section->virtualAddress);
|
||||
tsize = section->virtualSize;
|
||||
|
||||
rbuf = (void*)(__int64(buf) + rsection->virtualAddress);
|
||||
rsize = rsection->virtualSize;
|
||||
rbuf = (void*)(__int64(buf) + rsection->virtualAddress);
|
||||
rsize = rsection->virtualSize;
|
||||
}
|
||||
|
||||
if (EOSBuf) {
|
||||
auto section = pe_get_section((char*)EOSBuf, ".text");
|
||||
auto rsection = pe_get_section((char*)EOSBuf, ".rdata");
|
||||
|
||||
EOSTextBuf = (void*)(__int64(EOSBuf) + section->virtualAddress);
|
||||
EOSTextSize = section->virtualSize;
|
||||
|
||||
EOSRDataBuf = (void*)(__int64(EOSBuf) + rsection->virtualAddress);
|
||||
EOSRDataSize = rsection->virtualSize;
|
||||
}
|
||||
|
||||
FindProcessRequest();
|
||||
if (Game == Fortnite) FindPushWidget();
|
||||
//if (Game == Fortnite) FindPushWidget();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Starfall {
|
||||
namespace Callbacks {
|
||||
bool RequestExitWithStatusCallback(struct pf_patch_t* patch, void* stream) {
|
||||
AsmHook(stream, Hooks::RequestExitWithStatusHook);
|
||||
AsmHook((void*)(uint64_t(buf) + 0x221a404), Hooks::RequestExitWithStatusHook);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -85,6 +86,9 @@ namespace Starfall {
|
||||
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
|
||||
|
||||
pf_patchset_emit(tbuf, tsize, patchset);
|
||||
//AsmHook((void*)(uint64_t(buf) + 0x221a404), Hooks::RequestExitWithStatusHook);
|
||||
//AsmHook((void*)(uint64_t(buf) + 0x221a438), Hooks::RequestExitWithStatusHook);
|
||||
//AsmHook((void*)(uint64_t(buf) + 0x48830b0), Hooks::UnsafeEnvironmentPopupHook);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "ue.h"
|
||||
|
||||
constexpr bool Console = false; // if the console window should be created
|
||||
constexpr bool Console = true; // if the console window should be created
|
||||
constexpr StarfallURLSet URLSet = Default;
|
||||
constexpr inline FString Backend = L"http://127.0.0.1:3551"; // your backend url
|
||||
constexpr UEGame Game = Fortnite; // use Generic for any UE game other than fortnite
|
||||
|
||||
+1
-2
@@ -94,8 +94,7 @@ namespace Starfall {
|
||||
};
|
||||
enum UEGame {
|
||||
Generic,
|
||||
Fortnite,
|
||||
Generic427 // found in latest EGL
|
||||
Fortnite
|
||||
};
|
||||
}
|
||||
using namespace Types;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Starfall {
|
||||
L"on.epicgames.com",
|
||||
L"game-social.epicgames.com",
|
||||
L"ak.epicgames.com",
|
||||
L"epicgames.dev"
|
||||
//L"cdn2.unrealengine.com" // only needed if you have fixed friend images in friends list
|
||||
};
|
||||
|
||||
|
||||
+90
-28
@@ -14,13 +14,13 @@
|
||||
namespace Unreal {
|
||||
FString FCurlHttpRequest::GetURL()
|
||||
{
|
||||
return GetURLFunc(this, FString());
|
||||
return ((FString&(*)(FCurlHttpRequest*, FString)) VTable[0])(this, FString());
|
||||
}
|
||||
|
||||
void FCurlHttpRequest::SetURL(URL& URL)
|
||||
{
|
||||
FString str = URL;
|
||||
SetURLFunc(this, str);
|
||||
((void (*)(FCurlHttpRequest*, FString)) VTable[SetURLIdx])(this, str);
|
||||
free(str.String);
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,8 @@ namespace Unreal {
|
||||
namespace Starfall {
|
||||
bool setupMemLeak = false;
|
||||
void SetupRequest(FCurlHttpRequest* Request) {
|
||||
if (FCurlHttpRequest::SetURLFunc == nullptr) {
|
||||
if (FCurlHttpRequest::SetURLIdx == 0) {
|
||||
void* GetFunc = *Request->VTable;
|
||||
FCurlHttpRequest::GetURLFunc = (decltype(FCurlHttpRequest::GetURLFunc)) *Request->VTable;
|
||||
uint32_t URLOffset = 0;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
// this is only needed for latest
|
||||
@@ -46,14 +45,14 @@ namespace Starfall {
|
||||
for (int j = 0; j < 100; j++) {
|
||||
if (CheckBytes<0x48, 0x81, 0xC1>(func, j)) {
|
||||
if (*(uint32_t*)(__int64(func) + j + 3) == URLOffset) {
|
||||
FCurlHttpRequest::SetURLFunc = (void (*)(FCurlHttpRequest*, FString)) Request->VTable[i];
|
||||
FCurlHttpRequest::SetURLIdx = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
def:
|
||||
FCurlHttpRequest::SetURLFunc = (void (*)(FCurlHttpRequest*, FString)) Request->VTable[10];
|
||||
FCurlHttpRequest::SetURLIdx = 10;
|
||||
}
|
||||
// this works bc the first request is a datarouter request, and the second request should be after engine init
|
||||
else if (!setupMemLeak && Game == Fortnite) {
|
||||
@@ -74,15 +73,16 @@ def:
|
||||
|
||||
namespace Hooks {
|
||||
bool (*ProcessRequestOG)(FCurlHttpRequest* Request);
|
||||
bool ProcessRequestHook(FCurlHttpRequest* Request) {
|
||||
bool (*EOSProcessRequestOG)(FCurlHttpRequest* Request);
|
||||
bool InternalProcessRequest(FCurlHttpRequest* Request) {
|
||||
SetupRequest(Request);
|
||||
auto urlS = Request->GetURL();
|
||||
auto url = (URL *) malloc(sizeof(URL));
|
||||
auto url = (URL*)malloc(sizeof(URL));
|
||||
if (!url) return false;
|
||||
__stosb((uint8_t*)url, 0, sizeof(URL));
|
||||
url->Construct(urlS);
|
||||
|
||||
Log(Display, "URL: %ls\n", static_cast<wchar_t *>(urlS));
|
||||
Log(Display, "URL: %ls\n", static_cast<wchar_t*>(urlS));
|
||||
if (shouldRedirect(url)) {
|
||||
if (UseBackendParam)
|
||||
url->SetHost(backend);
|
||||
@@ -98,8 +98,17 @@ def:
|
||||
}
|
||||
|
||||
free(url);
|
||||
return true;
|
||||
}
|
||||
bool ProcessRequestHook(FCurlHttpRequest* Request) {
|
||||
if (!InternalProcessRequest(Request)) return false;
|
||||
return ProcessRequestOG(Request);
|
||||
}
|
||||
|
||||
bool EOSProcessRequestHook(FCurlHttpRequest* Request) {
|
||||
if (!InternalProcessRequest(Request)) return false;
|
||||
return EOSProcessRequestOG(Request);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Callbacks {
|
||||
@@ -110,10 +119,28 @@ def:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EOSPtrCallback(struct pf_patch_t* patch, void* stream) {
|
||||
VTHook((void**)stream, EOSProcessRequestHook, (void**)&EOSProcessRequestOG);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
constexpr static char ptrMasks[] = {
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff
|
||||
};
|
||||
|
||||
|
||||
bool StringCallback(struct pf_patch_t* patch, void* stream) {
|
||||
void* saddr = (void*)((__int64(stream) + 7) + *(int32_t*)(__int64(stream) + 3));
|
||||
if (__int64(saddr) >= __int64(rbuf) && __int64(saddr) < (__int64(rbuf) + (int64_t)rsize)) {
|
||||
if (wcscmp((wchar_t*)saddr, Game == Generic427 ? L"Could not perform game thread setup, processing HTTP request failed. Increase verbosity for additional information." : L"Could not set libcurl options for easy handle, processing HTTP request failed. Increase verbosity for additional information.") == 0) {
|
||||
if (wcscmp((wchar_t*)saddr, L"ProcessRequest failed. URL '%s' is not using a whitelisted domain. %p") == 0) {
|
||||
for (int i = 0; i < 2048; i++) {
|
||||
if (CheckBytes<0x48, 0x81, 0xEC>(stream, i, true)) {
|
||||
for (int x = 0; x < 50; x++) {
|
||||
@@ -144,7 +171,9 @@ setStream:
|
||||
Log(Display, "Found using UE 4.25, 4.26 & 5.4+ method\n");
|
||||
stream = (uint8_t*)stream - i - x;
|
||||
goto HookVT;
|
||||
} else if (CheckBytes<0x4C, 0x8B, 0xDC>(stream, i + x, true) || CheckBytes<0x4C, 0x8B, 0xC4>(stream, i + x, true)) break;
|
||||
}
|
||||
else if (CheckBytes<0x4C, 0x8B, 0xDC>(stream, i + x, true) || CheckBytes<0x48, 0x8B, 0xC4>(stream, i + x, true))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -155,17 +184,6 @@ setStream:
|
||||
Log(Display, "ProcessRequest: 0x%llx\n", __int64(stream) - __int64(buf));
|
||||
char* ptrMatches = (char*)&stream;
|
||||
|
||||
constexpr static char ptrMasks[] = {
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff,
|
||||
(char)0xff
|
||||
};
|
||||
|
||||
auto patch2 = pf_construct_patch(ptrMatches, (void*)ptrMasks, 8, PtrCallback);
|
||||
|
||||
struct pf_patch_t patches2[] = {
|
||||
@@ -176,6 +194,36 @@ setStream:
|
||||
while (!pf_patchset_emit(rbuf, rsize, patchset2));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EOSStringCallback(struct pf_patch_t* patch, void* stream) {
|
||||
void* saddr = (void*)((__int64(stream) + 7) + *(int32_t*)(__int64(stream) + 3));
|
||||
if (__int64(saddr) >= __int64(EOSRDataBuf) && __int64(saddr) < (__int64(EOSRDataBuf) + (int64_t)EOSRDataSize)) {
|
||||
if (wcscmp((wchar_t*)saddr, L"ProcessRequest failed. URL '%s' is not using a whitelisted domain. %p") == 0) {
|
||||
for (int i = 0; i < 2048; i++) {
|
||||
if (CheckBytes<0x48, 0x89, 0x5C>(stream, i, true)) {
|
||||
Log(Display, "Found EOS ProcessRequest\n");
|
||||
stream = (uint8_t*)stream - i;
|
||||
goto HookVT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
HookVT:
|
||||
Log(Display, "EOS ProcessRequest: 0x%llx\n", __int64(stream) - __int64(EOSBuf));
|
||||
|
||||
char* ptrMatches = (char*)&stream;
|
||||
|
||||
auto patch2 = pf_construct_patch(ptrMatches, (void*)ptrMasks, 8, EOSPtrCallback);
|
||||
|
||||
struct pf_patch_t patches2[] = {
|
||||
patch2
|
||||
};
|
||||
|
||||
struct pf_patchset_t patchset2 = pf_construct_patchset(patches2, sizeof(patches2) / sizeof(struct pf_patch_t), (bool (*)(void*, size_t, pf_patchset_t))pf_find_maskmatch);
|
||||
while (!pf_patchset_emit(EOSRDataBuf, EOSRDataSize, patchset2));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Finders {
|
||||
@@ -188,16 +236,30 @@ setStream:
|
||||
0xfb,
|
||||
0xff
|
||||
};
|
||||
{
|
||||
constexpr static auto patch = pf_construct_patch((void*)matches.data(), (void*)masks.data(), 2, StringCallback);
|
||||
|
||||
constexpr static auto patch = pf_construct_patch((void*)matches.data(), (void*)masks.data(), 2, StringCallback);
|
||||
constexpr static pf_patch_t patches[] = {
|
||||
patch
|
||||
};
|
||||
|
||||
constexpr static pf_patch_t patches[] = {
|
||||
patch
|
||||
};
|
||||
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), pf_find_maskmatch);
|
||||
|
||||
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), pf_find_maskmatch);
|
||||
while (!pf_patchset_emit(tbuf, tsize, patchset));
|
||||
}
|
||||
|
||||
while (!pf_patchset_emit(tbuf, tsize, patchset));
|
||||
if (EOSBuf) {
|
||||
|
||||
constexpr static auto patch = pf_construct_patch((void*)matches.data(), (void*)masks.data(), 2, EOSStringCallback);
|
||||
|
||||
constexpr static pf_patch_t patches[] = {
|
||||
patch
|
||||
};
|
||||
|
||||
constexpr static struct pf_patchset_t patchset = pf_construct_patchset(patches, sizeof(patches) / sizeof(struct pf_patch_t), pf_find_maskmatch);
|
||||
|
||||
while (!pf_patchset_emit(EOSTextBuf, EOSTextSize, patchset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -10,8 +10,7 @@ namespace Unreal {
|
||||
{
|
||||
public:
|
||||
void** VTable;
|
||||
static inline FString& (*GetURLFunc)(FCurlHttpRequest*, FString) = nullptr;
|
||||
static inline void (*SetURLFunc)(FCurlHttpRequest*, FString) = nullptr;
|
||||
static inline int64_t SetURLIdx;
|
||||
static inline void** ProcessRequestVT = nullptr;
|
||||
|
||||
FString GetURL();
|
||||
|
||||
Reference in New Issue
Block a user