Add support for 2012 player
This commit is contained in:
parent
48f8bebab5
commit
f49d58cdd7
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MFC2010
|
#define PLAYER2012
|
||||||
#define ARBITERBUILD
|
#define ARBITERBUILD
|
||||||
|
|
||||||
// when ARBITERBUILD is defined, the following changes occur:
|
// when ARBITERBUILD is defined, the following changes occur:
|
||||||
|
|
@ -18,8 +18,6 @@
|
||||||
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 40
|
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 40
|
||||||
#define CLASSPADDING_DATAMODEL__JOBID 729 // when compiled as debug, this must be 728
|
#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_DATAMODEL__GETJOBID 0x005CACC0
|
||||||
#define ADDRESS_STANDARDOUT__PRINT 0x0059F340
|
#define ADDRESS_STANDARDOUT__PRINT 0x0059F340
|
||||||
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x004FC1A0
|
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x004FC1A0
|
||||||
|
|
@ -42,8 +40,6 @@
|
||||||
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45
|
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45
|
||||||
#define CLASSPADDING_DATAMODEL__JOBID 740 // when compiled as debug, this must be 739
|
#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_DATAMODEL__GETJOBID 0x005E70C0
|
||||||
#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0
|
#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0
|
||||||
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x0
|
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x0
|
||||||
|
|
@ -58,6 +54,40 @@
|
||||||
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A
|
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A
|
||||||
#endif
|
#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
|
// RakNet definitions
|
||||||
// these are extracted from the 2016 source, but they're probably shifted 2 up compared to 2010 and 2011
|
// 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>
|
#include <detours.h>
|
||||||
|
|
||||||
|
int addressOffset;
|
||||||
|
|
||||||
LONG Patches::Apply()
|
LONG Patches::Apply()
|
||||||
{
|
{
|
||||||
DetourTransactionBegin();
|
DetourTransactionBegin();
|
||||||
|
|
@ -12,3 +14,47 @@ LONG Patches::Apply()
|
||||||
|
|
||||||
return DetourTransactionCommit();
|
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;
|
extern std::vector<Patch> patchList;
|
||||||
|
|
||||||
LONG Apply();
|
LONG Apply();
|
||||||
|
VOID ResolveOffset();
|
||||||
|
INT GetAddressByOffset(int address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = {
|
#define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = {
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,13 @@ struct DataModel
|
||||||
std::string jobId;
|
std::string jobId;
|
||||||
};
|
};
|
||||||
|
|
||||||
// class DataModel;
|
|
||||||
|
|
||||||
#if defined(MFC2010) || defined(MFC2011)
|
#if defined(MFC2010) || defined(MFC2011)
|
||||||
class CWorkspace;
|
|
||||||
|
|
||||||
// 2010 struct definitions:
|
// 2010 struct definitions:
|
||||||
// 0x47E010: CWorkspace->DoExecScript()
|
// 0x47E010: CWorkspace->DoExecScript()
|
||||||
// 0x47EC10: CWorkspace->ExecUrlScript()
|
// 0x47EC10: CWorkspace->ExecUrlScript()
|
||||||
|
|
||||||
|
class CWorkspace;
|
||||||
|
|
||||||
const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT;
|
const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT;
|
||||||
|
|
||||||
struct CRobloxDoc
|
struct CRobloxDoc
|
||||||
|
|
@ -27,20 +25,18 @@ struct CRobloxDoc
|
||||||
CWorkspace* workspace;
|
CWorkspace* workspace;
|
||||||
};
|
};
|
||||||
|
|
||||||
// padding1[4] = offset of 0x10
|
|
||||||
// padding1[40] = offset of 0xA0
|
|
||||||
struct CApp;
|
struct CApp;
|
||||||
|
|
||||||
// const auto CApp__CreateGame = (CWorkspace * (__thiscall*)(CApp * _this, void*, int, LPCWSTR))ADDRESS_CAPP__CREATEGAME;
|
// const auto CApp__CreateGame = (CWorkspace * (__thiscall*)(CApp * _this, int, LPCWSTR))ADDRESS_CAPP__CREATEGAME;
|
||||||
const auto CApp__RobloxAuthenticate = (void * (__thiscall*)(CApp * _this, void*, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE;
|
const auto CApp__RobloxAuthenticate = (void * (__thiscall*)(CApp * _this, LPVOID, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE;
|
||||||
|
|
||||||
struct CRobloxApp;
|
|
||||||
|
|
||||||
// 2010 struct definitions:
|
// 2010 struct definitions:
|
||||||
// 0x405D20: CRobloxApp->CreateDocument()
|
// 0x405D20: CRobloxApp->CreateDocument()
|
||||||
// 0x44F6F0: CRobloxApp->ExitInstance()
|
// 0x44F6F0: CRobloxApp->ExitInstance()
|
||||||
// 0x452900: CRobloxApp->InitInstance()
|
// 0x452900: CRobloxApp->InitInstance()
|
||||||
|
|
||||||
|
struct CRobloxApp;
|
||||||
|
|
||||||
const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp * _this))ADDRESS_CROBLOXAPP__CREATEDOCUMENT;
|
const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp * _this))ADDRESS_CROBLOXAPP__CREATEDOCUMENT;
|
||||||
|
|
||||||
struct CCommandLineInfo
|
struct CCommandLineInfo
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "RobloxMFCHooks.h"
|
#include "RobloxMFCHooks.h"
|
||||||
|
#include "Patches.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
@ -76,6 +77,7 @@ void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, char
|
||||||
#ifdef ARBITERBUILD
|
#ifdef ARBITERBUILD
|
||||||
int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2)
|
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
|
// 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
|
// 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
|
// 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
|
#endif
|
||||||
|
|
||||||
#if defined(MFC2010) || defined(MFC2011)
|
#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)
|
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())
|
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())
|
if (hasJoinArg && !joinScriptUrl.empty())
|
||||||
{
|
{
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
// TODO: use CApp__CreateGame instead
|
// 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);
|
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);
|
CWorkspace__ExecUrlScript(document->workspace, joinScriptUrl.c_str(), VARIANTARG(), VARIANTARG(), VARIANTARG(), VARIANTARG(), nullptr);
|
||||||
}
|
// }
|
||||||
catch (std::runtime_error& exception)
|
// catch (std::runtime_error& exception)
|
||||||
{
|
// {
|
||||||
MessageBoxA(nullptr, exception.what(), nullptr, MB_ICONERROR);
|
// MessageBoxA(nullptr, exception.what(), nullptr, MB_ICONERROR);
|
||||||
return FALSE;
|
// return FALSE;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
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);
|
// typedef std::string(__thiscall* Network__RakNetAddressToString_t)(const int raknetAddress, char portDelineator);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MFC2010) || defined(MFC2011)
|
#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 BOOL(__thiscall* CRobloxApp__InitInstance_t)(CRobloxApp* _this);
|
||||||
typedef void(__thiscall* CRobloxCommandLineInfo__ParseParam_t)(CRobloxCommandLineInfo* _this, const char* pszParam, BOOL bFlag, BOOL bLast);
|
typedef void(__thiscall* CRobloxCommandLineInfo__ParseParam_t)(CRobloxCommandLineInfo* _this, const char* pszParam, BOOL bFlag, BOOL bLast);
|
||||||
#endif
|
#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);
|
// std::string __fastcall Network__RakNetAddressToString_hook(const int raknetAddress, char portDelineator);
|
||||||
#endif
|
#endif
|
||||||
#if defined(MFC2010) || defined(MFC2011)
|
#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);
|
BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this);
|
||||||
void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast);
|
void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -6,6 +6,7 @@ const std::vector<std::string> Util::allowedHosts
|
||||||
"polygon.pizzaboxer.xyz",
|
"polygon.pizzaboxer.xyz",
|
||||||
"polygondev.pizzaboxer.xyz",
|
"polygondev.pizzaboxer.xyz",
|
||||||
"polygonapi.pizzaboxer.xyz",
|
"polygonapi.pizzaboxer.xyz",
|
||||||
|
"clientsettingsapi.pizzaboxer.xyz",
|
||||||
|
|
||||||
"roblox.com",
|
"roblox.com",
|
||||||
"www.roblox.com",
|
"www.roblox.com",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Patches.h"
|
#include "Patches.h"
|
||||||
#include "RobloxMFCHooks.h"
|
#include "RobloxMFCHooks.h"
|
||||||
|
#include "Logger.h" // remove when testing is done
|
||||||
|
|
||||||
START_PATCH_LIST()
|
START_PATCH_LIST()
|
||||||
ADD_PATCH(Http__trustCheck, Http__trustCheck_hook)
|
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)
|
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
|
#ifdef PLAYER2012
|
||||||
|
Logger::Initialize("player2012Test");
|
||||||
|
#endif
|
||||||
LONG error = Patches::Apply();
|
LONG error = Patches::Apply();
|
||||||
if (error != NO_ERROR)
|
if (error != NO_ERROR)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue