Add support for 2012 player
This commit is contained in:
parent
48f8bebab5
commit
f49d58cdd7
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#define MFC2010
|
||||
#define PLAYER2012
|
||||
#define ARBITERBUILD
|
||||
|
||||
// when ARBITERBUILD is defined, the following changes occur:
|
||||
|
|
@ -18,8 +18,6 @@
|
|||
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 40
|
||||
#define CLASSPADDING_DATAMODEL__JOBID 729 // when compiled as debug, this must be 728
|
||||
|
||||
// #define STRUCTOFFSET_DATAMODEL__JOBID 2912
|
||||
|
||||
#define ADDRESS_DATAMODEL__GETJOBID 0x005CACC0
|
||||
#define ADDRESS_STANDARDOUT__PRINT 0x0059F340
|
||||
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x004FC1A0
|
||||
|
|
@ -42,8 +40,6 @@
|
|||
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45
|
||||
#define CLASSPADDING_DATAMODEL__JOBID 740 // when compiled as debug, this must be 739
|
||||
|
||||
// #define STRUCTOFFSET_DATAMODEL__JOBID 2956
|
||||
|
||||
#define ADDRESS_DATAMODEL__GETJOBID 0x005E70C0
|
||||
#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0
|
||||
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x0
|
||||
|
|
@ -58,6 +54,40 @@
|
|||
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A
|
||||
#endif
|
||||
|
||||
#ifdef PLAYER2012
|
||||
// so 2012's a bit different
|
||||
// VMProtect likes to offset the memory locations randomly on startup
|
||||
// so defining the addresses here are a bit weird
|
||||
|
||||
// say the beginning of the program is located at 0x00BF1000
|
||||
// and you have a trust check hook that's, for example, located at 0x00DF20A0
|
||||
|
||||
// VMProtect is offsetting the memory location from 0x00000000 - 0x00FF0000
|
||||
// so the 0x00BF0000 in 0x00BF1000 is actually an offset
|
||||
|
||||
// with that offset, the address you'd have to put for your trust check hook will be 0x00DF20A0 - 0x00BF0000 = 0x002020A0
|
||||
// and you just put that address into the function
|
||||
|
||||
#define CLASSLOCATION_CROBLOXAPP 0x00CBA8A0
|
||||
#define CLASSLOCATION_CAPP 0x00406D80
|
||||
|
||||
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 0
|
||||
#define CLASSPADDING_DATAMODEL__JOBID 763 // when compiled as debug, this must be 762
|
||||
|
||||
#define ADDRESS_DATAMODEL__GETJOBID Patches::GetAddressByOffset(0x002079A0)
|
||||
#define ADDRESS_STANDARDOUT__PRINT Patches::GetAddressByOffset(0x0023A8C0)
|
||||
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x0
|
||||
#define ADDRESS_HTTP__TRUSTCHECK Patches::GetAddressByOffset(0x002020A0)
|
||||
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 Patches::GetAddressByOffset(0x00526330)
|
||||
#define ADDRESS_CAPP__CREATEGAME 0x0
|
||||
#define ADDRESS_CAPP__ROBLOXAUTHENTICATE 0x0
|
||||
#define ADDRESS_CROBLOXAPP__INITINSTANCE 0x0
|
||||
#define ADDRESS_CROBLOXAPP__CREATEDOCUMENT 0x0
|
||||
#define ADDRESS_CWORKSPACE__EXECURLSCRIPT 0x0
|
||||
#define ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM 0x0
|
||||
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0
|
||||
#endif
|
||||
|
||||
|
||||
// RakNet definitions
|
||||
// these are extracted from the 2016 source, but they're probably shifted 2 up compared to 2010 and 2011
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <detours.h>
|
||||
|
||||
int addressOffset;
|
||||
|
||||
LONG Patches::Apply()
|
||||
{
|
||||
DetourTransactionBegin();
|
||||
|
|
@ -11,4 +13,48 @@ LONG Patches::Apply()
|
|||
DetourAttach(&(PVOID&)*patch.first, patch.second);
|
||||
|
||||
return DetourTransactionCommit();
|
||||
}
|
||||
|
||||
VOID Patches::ResolveOffset()
|
||||
{
|
||||
// the only surviving fragment of PolygonUtil.dll
|
||||
// RIP 05/08/2021 - 20/01/2022
|
||||
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
DWORD ProcID = GetCurrentProcessId();
|
||||
HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcID);
|
||||
|
||||
unsigned int Opcode = 0xC7F18B56;
|
||||
int BaseAddress = 0x00001000;
|
||||
|
||||
int Offset = 0x00010000;
|
||||
int Searches = 0xFFF;
|
||||
|
||||
for (int i = 1; i <= Searches; i++)
|
||||
{
|
||||
int SearchAddress = Offset * i;
|
||||
int Address = SearchAddress + BaseAddress;
|
||||
if (VirtualQuery((LPVOID)Address, &mbi, sizeof(mbi)) == 0) continue;
|
||||
|
||||
std::vector<int> buffer(mbi.RegionSize);
|
||||
|
||||
if (!ReadProcessMemory(Handle, (LPCVOID)Address, &buffer[0], buffer.size(), NULL)) continue;
|
||||
|
||||
if (buffer[0] == Opcode)
|
||||
{
|
||||
addressOffset = SearchAddress;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SearchAddress == Offset * Searches)
|
||||
{
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT Patches::GetAddressByOffset(int address)
|
||||
{
|
||||
if (!addressOffset) ResolveOffset();
|
||||
return address + addressOffset;
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ namespace Patches
|
|||
extern std::vector<Patch> patchList;
|
||||
|
||||
LONG Apply();
|
||||
VOID ResolveOffset();
|
||||
INT GetAddressByOffset(int address);
|
||||
}
|
||||
|
||||
#define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = {
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ struct DataModel
|
|||
std::string jobId;
|
||||
};
|
||||
|
||||
// class DataModel;
|
||||
|
||||
#if defined(MFC2010) || defined(MFC2011)
|
||||
class CWorkspace;
|
||||
|
||||
// 2010 struct definitions:
|
||||
// 0x47E010: CWorkspace->DoExecScript()
|
||||
// 0x47EC10: CWorkspace->ExecUrlScript()
|
||||
|
||||
class CWorkspace;
|
||||
|
||||
const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT;
|
||||
|
||||
struct CRobloxDoc
|
||||
|
|
@ -27,20 +25,18 @@ struct CRobloxDoc
|
|||
CWorkspace* workspace;
|
||||
};
|
||||
|
||||
// padding1[4] = offset of 0x10
|
||||
// padding1[40] = offset of 0xA0
|
||||
struct CApp;
|
||||
|
||||
// const auto CApp__CreateGame = (CWorkspace * (__thiscall*)(CApp * _this, void*, int, LPCWSTR))ADDRESS_CAPP__CREATEGAME;
|
||||
const auto CApp__RobloxAuthenticate = (void * (__thiscall*)(CApp * _this, void*, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE;
|
||||
|
||||
struct CRobloxApp;
|
||||
// const auto CApp__CreateGame = (CWorkspace * (__thiscall*)(CApp * _this, int, LPCWSTR))ADDRESS_CAPP__CREATEGAME;
|
||||
const auto CApp__RobloxAuthenticate = (void * (__thiscall*)(CApp * _this, LPVOID, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE;
|
||||
|
||||
// 2010 struct definitions:
|
||||
// 0x405D20: CRobloxApp->CreateDocument()
|
||||
// 0x44F6F0: CRobloxApp->ExitInstance()
|
||||
// 0x452900: CRobloxApp->InitInstance()
|
||||
|
||||
struct CRobloxApp;
|
||||
|
||||
const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp * _this))ADDRESS_CROBLOXAPP__CREATEDOCUMENT;
|
||||
|
||||
struct CCommandLineInfo
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "pch.h"
|
||||
#include "RobloxMFCHooks.h"
|
||||
#include "Patches.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "Logger.h"
|
||||
|
|
@ -51,7 +52,7 @@ BOOL __fastcall Http__trustCheck_hook(const char* url)
|
|||
return std::find(Util::allowedHosts.begin(), Util::allowedHosts.end(), parsedUrl.host_) != Util::allowedHosts.end();
|
||||
|
||||
if (std::find(Util::allowedEmbeddedSchemes.begin(), Util::allowedEmbeddedSchemes.end(), parsedUrl.scheme_) != Util::allowedEmbeddedSchemes.end())
|
||||
return true;
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -76,6 +77,7 @@ void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, char
|
|||
#ifdef ARBITERBUILD
|
||||
int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2)
|
||||
{
|
||||
// the actual function signature is (DataModel* _this)
|
||||
// this only sets the job id when game.jobId is called by lua
|
||||
// so the gameserver script must call game.jobId at the beginning for this to take effect
|
||||
// also, this only applies to the first datamodel that is created
|
||||
|
|
@ -132,9 +134,18 @@ void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string*
|
|||
#endif
|
||||
|
||||
#if defined(MFC2010) || defined(MFC2011)
|
||||
/* INT __fastcall CApp__CreateGame_hook(CApp* _this, void*, int a2, LPCWSTR a3)
|
||||
/* INT __fastcall CApp__CreateGame_hook(CApp* _this, void*, int* a2, LPCWSTR a3)
|
||||
{
|
||||
return CApp__CreateGame(_this, a2, a3);
|
||||
printf("CApp::CreateGame called\n");
|
||||
// printf("Location of _this: %p\n", _this);
|
||||
// printf("Location of a2: %p\n", a2);
|
||||
// printf("Location of a3: %p\n", a3);
|
||||
|
||||
// int result = (int)CApp__CreateGame(_this, a2, a3);
|
||||
// int result = (int)CApp__CreateGame(_this, a2, L"44340105256");
|
||||
int result = (int)CApp__CreateGame(_this, a2, L"44340105256");
|
||||
|
||||
return result;
|
||||
} */
|
||||
|
||||
BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this)
|
||||
|
|
@ -146,29 +157,27 @@ BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this)
|
|||
|
||||
if (hasAuthUrlArg && hasAuthTicketArg && !authenticationUrl.empty() && !authenticationTicket.empty())
|
||||
{
|
||||
CApp__RobloxAuthenticate(app, NULL, authenticationUrl.c_str(), authenticationTicket.c_str());
|
||||
CApp__RobloxAuthenticate(app, nullptr, authenticationUrl.c_str(), authenticationTicket.c_str());
|
||||
}
|
||||
|
||||
if (hasJoinArg && !joinScriptUrl.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: use CApp__CreateGame instead
|
||||
// try
|
||||
// {
|
||||
// so... i would've wanted to just use CApp::CreateGame instead but there's a few issues
|
||||
// in the typelib, CreateGame is exposed as being IApp::CreateGame(string p) - 'p' is "44340105256"
|
||||
// however internally the function is actually CApp::CreateGame(int something, LPCWSTR p)
|
||||
// it's obvious that 'something' is a pointer to a class but i have no clue what the class is
|
||||
// until i figure out wtf its supposed to be we've gotta stick to doing CRobloxApp::CreateDocument for now
|
||||
|
||||
CRobloxDoc* document = CRobloxApp__CreateDocument(_this);
|
||||
|
||||
printf("address of document: %p\n", document);
|
||||
printf("\n");
|
||||
printf("address of &document->workspace: %p\n", &document->workspace);
|
||||
printf("address of document->workspace: %p\n", document->workspace);
|
||||
printf("\n");
|
||||
|
||||
CWorkspace__ExecUrlScript(document->workspace, joinScriptUrl.c_str(), VARIANTARG(), VARIANTARG(), VARIANTARG(), VARIANTARG(), nullptr);
|
||||
}
|
||||
catch (std::runtime_error& exception)
|
||||
{
|
||||
MessageBoxA(nullptr, exception.what(), nullptr, MB_ICONERROR);
|
||||
return FALSE;
|
||||
}
|
||||
// }
|
||||
// catch (std::runtime_error& exception)
|
||||
// {
|
||||
// MessageBoxA(nullptr, exception.what(), nullptr, MB_ICONERROR);
|
||||
// return FALSE;
|
||||
// }
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ typedef void(__thiscall* StandardOut__print_t)(int _this, int type, std::string*
|
|||
// typedef std::string(__thiscall* Network__RakNetAddressToString_t)(const int raknetAddress, char portDelineator);
|
||||
#endif
|
||||
#if defined(MFC2010) || defined(MFC2011)
|
||||
// typedef INT(__thiscall* CApp__CreateGame_t)(CApp* _this, int a2, LPCWSTR a3);
|
||||
// typedef INT(__thiscall* CApp__CreateGame_t)(CApp* _this, int *a2, LPCWSTR a3);
|
||||
typedef BOOL(__thiscall* CRobloxApp__InitInstance_t)(CRobloxApp* _this);
|
||||
typedef void(__thiscall* CRobloxCommandLineInfo__ParseParam_t)(CRobloxCommandLineInfo* _this, const char* pszParam, BOOL bFlag, BOOL bLast);
|
||||
#endif
|
||||
|
|
@ -42,7 +42,7 @@ void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string*
|
|||
// std::string __fastcall Network__RakNetAddressToString_hook(const int raknetAddress, char portDelineator);
|
||||
#endif
|
||||
#if defined(MFC2010) || defined(MFC2011)
|
||||
// INT __fastcall CApp__CreateGame_hook(CApp* _this, void*, int a2, LPCWSTR a3);
|
||||
// INT __fastcall CApp__CreateGame_hook(CApp* _this, void*, int *a2, LPCWSTR a3);
|
||||
BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this);
|
||||
void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast);
|
||||
#endif
|
||||
|
|
@ -6,6 +6,7 @@ const std::vector<std::string> Util::allowedHosts
|
|||
"polygon.pizzaboxer.xyz",
|
||||
"polygondev.pizzaboxer.xyz",
|
||||
"polygonapi.pizzaboxer.xyz",
|
||||
"clientsettingsapi.pizzaboxer.xyz",
|
||||
|
||||
"roblox.com",
|
||||
"www.roblox.com",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "Config.h"
|
||||
#include "Patches.h"
|
||||
#include "RobloxMFCHooks.h"
|
||||
#include "Logger.h" // remove when testing is done
|
||||
|
||||
START_PATCH_LIST()
|
||||
ADD_PATCH(Http__trustCheck, Http__trustCheck_hook)
|
||||
|
|
@ -28,6 +29,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||
{
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
#ifdef PLAYER2012
|
||||
Logger::Initialize("player2012Test");
|
||||
#endif
|
||||
LONG error = Patches::Apply();
|
||||
if (error != NO_ERROR)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue