Add support for 2012 player

This commit is contained in:
pizzaboxer 2022-01-26 17:57:49 +00:00
parent 48f8bebab5
commit f49d58cdd7
8 changed files with 125 additions and 37 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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",

View File

@ -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)
{