From f49d58cdd73941750362d2e56867520bd94d2110 Mon Sep 17 00:00:00 2001 From: pizzaboxer <41478239+pizzaboxer@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:57:49 +0000 Subject: [PATCH] Add support for 2012 player --- PolygonClientUtilities/Config.h | 40 +++++++++++++++--- PolygonClientUtilities/Patches.cpp | 46 +++++++++++++++++++++ PolygonClientUtilities/Patches.h | 2 + PolygonClientUtilities/RobloxMFCClasses.h | 16 +++----- PolygonClientUtilities/RobloxMFCHooks.cpp | 49 ++++++++++++++--------- PolygonClientUtilities/RobloxMFCHooks.h | 4 +- PolygonClientUtilities/Util.cpp | 1 + PolygonClientUtilities/dllmain.cpp | 4 ++ 8 files changed, 125 insertions(+), 37 deletions(-) diff --git a/PolygonClientUtilities/Config.h b/PolygonClientUtilities/Config.h index 1b23376..86fcf01 100644 --- a/PolygonClientUtilities/Config.h +++ b/PolygonClientUtilities/Config.h @@ -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 diff --git a/PolygonClientUtilities/Patches.cpp b/PolygonClientUtilities/Patches.cpp index f038399..f6eeca6 100644 --- a/PolygonClientUtilities/Patches.cpp +++ b/PolygonClientUtilities/Patches.cpp @@ -3,6 +3,8 @@ #include +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 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; } \ No newline at end of file diff --git a/PolygonClientUtilities/Patches.h b/PolygonClientUtilities/Patches.h index 45f7bb3..2792cd2 100644 --- a/PolygonClientUtilities/Patches.h +++ b/PolygonClientUtilities/Patches.h @@ -7,6 +7,8 @@ namespace Patches extern std::vector patchList; LONG Apply(); + VOID ResolveOffset(); + INT GetAddressByOffset(int address); } #define START_PATCH_LIST() std::vector Patches::patchList = { diff --git a/PolygonClientUtilities/RobloxMFCClasses.h b/PolygonClientUtilities/RobloxMFCClasses.h index 0fcaf35..280d472 100644 --- a/PolygonClientUtilities/RobloxMFCClasses.h +++ b/PolygonClientUtilities/RobloxMFCClasses.h @@ -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 diff --git a/PolygonClientUtilities/RobloxMFCHooks.cpp b/PolygonClientUtilities/RobloxMFCHooks.cpp index 2dd6625..f0e3941 100644 --- a/PolygonClientUtilities/RobloxMFCHooks.cpp +++ b/PolygonClientUtilities/RobloxMFCHooks.cpp @@ -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; diff --git a/PolygonClientUtilities/RobloxMFCHooks.h b/PolygonClientUtilities/RobloxMFCHooks.h index ca1258e..3e9528b 100644 --- a/PolygonClientUtilities/RobloxMFCHooks.h +++ b/PolygonClientUtilities/RobloxMFCHooks.h @@ -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 \ No newline at end of file diff --git a/PolygonClientUtilities/Util.cpp b/PolygonClientUtilities/Util.cpp index 2872425..966ec54 100644 --- a/PolygonClientUtilities/Util.cpp +++ b/PolygonClientUtilities/Util.cpp @@ -6,6 +6,7 @@ const std::vector Util::allowedHosts "polygon.pizzaboxer.xyz", "polygondev.pizzaboxer.xyz", "polygonapi.pizzaboxer.xyz", + "clientsettingsapi.pizzaboxer.xyz", "roblox.com", "www.roblox.com", diff --git a/PolygonClientUtilities/dllmain.cpp b/PolygonClientUtilities/dllmain.cpp index 307ab3f..a24f506 100644 --- a/PolygonClientUtilities/dllmain.cpp +++ b/PolygonClientUtilities/dllmain.cpp @@ -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) {