Compare commits

...

3 Commits

Author SHA1 Message Date
pizzaboxer 0a4a10b8e7 add trust check for calones' domains 2022-04-10 18:34:22 +01:00
pizzaboxer 7a1ed6f4d8 Remove more unnneeded code
(pertains to offset resolving which is only required in 2012/2013 player beta)
2022-04-10 12:03:42 +01:00
pizzaboxer ea84438423 Make trust check only patch for Tadah 2014
Only the trust check patch is needed for this branch, and I'm also retaining the Output patch for easy debugging in case we need it. Some minor tweaks have been made to the two patches that have been kept to remove anything that's now unneeded and also any tweaks needed to make it work with 2014.
2022-04-10 11:46:55 +01:00
12 changed files with 48 additions and 756 deletions

View File

@ -1,103 +1,7 @@
#pragma once
#define MFC2011
#define PLAYERBUILD
#define ARBITERBUILD
#define OUTPUT
// #define DEBUG_SERVERREPLICATOR__PROCESSPACKET
// when PLAYERBUILD is defined, the following changes occur for 2010 and 2012 only:
// the -jobId arg is parsed
// when ARBITERBUILD is defined, the following changes occur:
// DataModel::getJobId is hooked
// DataModel::~DataModel is hooked
// StandardOut::print is hooked
// Network::RakNetAddressToString is hooked
// -jobId arg becomes available
// HTTP requests and output messages are logged to a file
// RobloxApp (2010)
#ifdef MFC2010
#define CLASSPADDING_DATAMODEL__JOBID 729 // when compiled as debug, this must be 728
#define ADDRESS_DATAMODEL__GETJOBID 0x005CACC0
#define ADDRESS_STANDARDOUT__PRINT 0x0059F340
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x004FC1A0
#define ADDRESS_HTTP__TRUSTCHECK 0x005A2680
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x0079ECF0
#define ADDRESS_SERVERREPLICATOR__SENDTOP 0x00506910
#define ADDRESS_SERVERREPLICATOR__PROCESSPACKET 0x00507420
// MFC specific definitions
#define CLASSLOCATION_CROBLOXAPP 0x00BFF898
#define CLASSLOCATION_CAPP 0x00405D20
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 40
#define ADDRESS_CAPP__CREATEGAME 0x00405D20
#define ADDRESS_CAPP__ROBLOXAUTHENTICATE 0x00408060
#define ADDRESS_CROBLOXAPP__INITINSTANCE 0x00452900
#define ADDRESS_CROBLOXAPP__CREATEDOCUMENT 0x0044F6E0
#define ADDRESS_CWORKSPACE__EXECURLSCRIPT 0x0047EC10
#define ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM 0x00450AC0
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x007A80A0
// RakNet packet definitions
#define ID_TIMESTAMP 25
#define ID_SET_GLOBALS 95
#define ID_REQUEST_CHARACTER 96
#define ID_DATA 98
#define ID_SUBMIT_TICKET 104
#endif
// RobloxApp (2011)
#ifdef MFC2011
#define CLASSPADDING_DATAMODEL__JOBID 740 // when compiled as debug, this must be 739
#define ADDRESS_DATAMODEL__GETJOBID 0x005E70C0
#define ADDRESS_DATAMODEL__DESTRUCT 0x006002A0
#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0
#define ADDRESS_NETWORK__RAKNETADDRESSTOSTRING 0x0
#define ADDRESS_HTTP__TRUSTCHECK 0x005B7050
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x00809EC0
#define ADDRESS_SERVERREPLICATOR__SENDTOP 0x00513E80
#define ADDRESS_SERVERREPLICATOR__PROCESSTICKET 0x00514B60
// MFC specific definitions
#define CLASSLOCATION_CROBLOXAPP 0x00CBA8A0
#define CLASSLOCATION_CAPP 0x00406D80
#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45
#define ADDRESS_CAPP__CREATEGAME 0x00406D80
#define ADDRESS_CAPP__ROBLOXAUTHENTICATE 0x00409050
#define ADDRESS_CROBLOXAPP__INITINSTANCE 0x004613C0
#define ADDRESS_CROBLOXAPP__CREATEDOCUMENT 0x0045D030
#define ADDRESS_CWORKSPACE__EXECURLSCRIPT 0x0049FC90
#define ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM 0x0045EE50
#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A
// RakNet definitions
#define ID_SET_GLOBALS 127
#define ID_DATA 129
#define ID_REQUEST_MARKER 130
#define ID_PHYSICS 131
#define ID_CHAT_ALL 132
#define ID_CHAT_TEAM 133
#define ID_REPORT_ABUSE 134
#define ID_SUBMIT_TICKET 135
#define ID_CHAT_GAME 136
#endif
// RobloxApp/RobloxPlayer (2012)
#ifdef MFC2012
#define ADDRESS_HTTP__TRUSTCHECK 0x006D5D20
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x009B1D20
#endif
// RobloxPlayerBeta (2012)
#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
@ -111,24 +15,6 @@
// 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 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)
// Player specific definitions
#define ADDRESS_APPLICATION__PARSEARGUMENTS Patches::GetAddressByOffset(0x00004E60)
#endif
// RobloxStudioBeta (2012)
#ifdef STUDIO2012
#define ADDRESS_HTTP__TRUSTCHECK Patches::GetAddressByOffset(0x001931A0)
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 Patches::GetAddressByOffset(0x004CD250)
#endif
#define RR_STOP_PROCESSING_AND_DEALLOCATE 0
#define RR_CONTINUE_PROCESSING 1
#define RR_STOP_PROCESSING 2
#define ADDRESS_HTTP__TRUSTCHECK 0x005CD760 //Patches::GetAddressByOffset(0x002020A0)
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x00B6C9E0 //Patches::GetAddressByOffset(0x00526330)
#define ADDRESS_STANDARDOUT__PRINT 0x005E3330

View File

@ -4,8 +4,6 @@
//#pragma warning(disable : 4996)
HANDLE Logger::handle;
std::ofstream Logger::outputLog;
std::ofstream Logger::httpLog;
void Logger::Initialize(const std::string jobId)
{
@ -24,57 +22,4 @@ void Logger::Initialize(const std::string jobId)
// printf("Service starting...\n");
// printf("Intializing Roblox Web Service\n");
// printf("Service Started on port 64989\n");
Logger::outputLog = std::ofstream(jobId + std::string("-Output.txt"));
Logger::httpLog = std::ofstream(jobId + std::string("-Http.txt"));
}
void Logger::Log(LogType type, const std::string message)
{
if (!handle) return;
switch (type)
{
case LogType::Output:
outputLog << "[" << Logger::UtcTime() << "] " << message.c_str() << std::endl;
break;
case LogType::Http:
httpLog << "[" << Logger::UtcTime() << "] " << message.c_str() << std::endl;
break;
}
}
void Logger::Print(int type, const std::string message)
{
if (!Logger::handle) return;
switch (type)
{
case 1: // RBX::MESSAGE_OUTPUT:
Logger::Log(LogType::Output, std::string("[MESSAGE_OUTPUT] ") + message);
SetConsoleTextAttribute(Logger::handle, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
break;
case 0: // RBX::MESSAGE_INFO:
Logger::Log(LogType::Output, std::string("[MESSAGE_INFO] ") + message);
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
case 2: // RBX::MESSAGE_WARNING:
Logger::Log(LogType::Output, std::string("[MESSAGE_WARNING] ") + message);
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN);
break;
case 3: // RBX::MESSAGE_ERROR:
Logger::Log(LogType::Output, std::string("[MESSAGE_ERROR] ") + message);
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_INTENSITY);
break;
}
printf("%s\n", message.c_str());
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
std::string Logger::UtcTime()
{
std::stringstream time;
std::time_t now = std::time(NULL);
time << std::put_time(std::localtime(&now), "%F %T");
return time.str();
}

View File

@ -6,13 +6,7 @@ enum class LogType { Output, Http };
class Logger
{
private:
static std::ofstream outputLog;
static std::ofstream httpLog;
public:
static HANDLE handle;
static void Initialize(const std::string jobId);
static void Log(LogType type, const std::string message);
static void Print(int type, const std::string message);
static std::string UtcTime();
};

View File

@ -13,48 +13,4 @@ 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,8 +7,6 @@ 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

@ -33,10 +33,10 @@
<ClInclude Include="LUrlParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger.h">
<ClInclude Include="Util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Util.h">
<ClInclude Include="Logger.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@ -56,10 +56,10 @@
<ClCompile Include="LUrlParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Logger.cpp">
<ClCompile Include="Util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Util.cpp">
<ClCompile Include="Logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -1,71 +1,3 @@
#pragma once
#include "Config.h"
#include <oaidl.h>
#ifdef ARBITERBUILD
struct DataModel
{
void* padding1[CLASSPADDING_DATAMODEL__JOBID];
std::string jobId;
};
struct Packet
{
void* padding1[7];
unsigned int length;
void* padding2[1];
unsigned char* data;
};
struct ConcurrentRakPeer {};
struct RakPeerInterface {};
struct ServerReplicator
{
void* padding1[1869]; // offset of 0 -> 7476
bool padding2; // offset of 7476 -> 7477
bool isAuthenticated; // offset of 7477 -> 7478
};
#endif
#if defined(MFC2010) || defined(MFC2011)
// 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
{
void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE];
CWorkspace* workspace;
};
struct CApp;
// 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
{
void* padding1[3];
BOOL m_bRunAutomated;
};
class CRobloxCommandLineInfo : public CCommandLineInfo {};
const auto CCommandLineInfo__ParseLast = (void(__thiscall*)(CCommandLineInfo * _this, BOOL bLast))ADDRESS_CCOMMANDLINEINFO__PARSELAST;
#endif
#include "Config.h"

View File

@ -4,71 +4,24 @@
#include "Config.h"
#include "Util.h"
#include "LUrlParser.h"
#ifdef ARBITERBUILD
#include "Logger.h"
#endif
static bool hasAuthUrlArg = false;
static bool hasAuthTicketArg = false;
static bool hasJoinArg = false;
static bool hasJobId = false;
static bool setJobId = false;
static std::wstring authenticationUrl;
static std::wstring authenticationTicket;
static std::wstring joinScriptUrl;
static std::string jobId;
static std::map<ServerReplicator*, RakPeerInterface*> rakPeers;
// Functions //
Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK;
Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64;
#ifdef ARBITERBUILD
DataModel__getJobId_t DataModel__getJobId = (DataModel__getJobId_t)ADDRESS_DATAMODEL__GETJOBID;
#ifdef OUTPUT
StandardOut__print_t StandardOut__print = (StandardOut__print_t)ADDRESS_STANDARDOUT__PRINT;
// Network__RakNetAddressToString_t Network__RakNetAddressToString = (Network__RakNetAddressToString_t)ADDRESS_NETWORK__RAKNETADDRESSTOSTRING;
#ifdef MFC2011
ServerReplicator__sendTop_t ServerReplicator__sendTop = (ServerReplicator__sendTop_t)ADDRESS_SERVERREPLICATOR__SENDTOP;
ServerReplicator__processTicket_t ServerReplicator__processTicket = (ServerReplicator__processTicket_t)ADDRESS_SERVERREPLICATOR__PROCESSTICKET;
#endif
#ifdef PLAYER2012
Application__ParseArguments_t Application__ParseArguments = (Application__ParseArguments_t)ADDRESS_APPLICATION__PARSEARGUMENTS;
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
// CApp__CreateGame_t CApp__CreateGame = (CApp__CreateGame_t)ADDRESS_CAPP__CREATEGAME;
CRobloxApp__InitInstance_t CRobloxApp__InitInstance = (CRobloxApp__InitInstance_t)ADDRESS_CROBLOXAPP__INITINSTANCE;
CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam = (CRobloxCommandLineInfo__ParseParam_t)ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM;
#endif
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
ServerReplicator__processPacket_t ServerReplicator__processPacket = (ServerReplicator__processPacket_t)ADDRESS_SERVERREPLICATOR__PROCESSPACKET;
#endif
// Hook Definitions //
BOOL __fastcall Http__trustCheck_hook(const char* url)
BOOL __fastcall Http__trustCheck_hook(int _this, void*, const char* url)
{
if (strlen(url) == 7 && !Util::isASCII(url))
{
// so the client does this really fucking stupid thing where if it opens an ie window,
// it passes a char**, and not a char*
// no idea if thats a detours quirk (i doubt it) or if thats how its just actually handled
// practically no url is ever going to be seven characters long so it doesn't really matter
url = *(char**)url;
}
LUrlParser::ParseURL parsedUrl = LUrlParser::ParseURL::parseURL(url);
if (!parsedUrl.isValid())
return false;
#ifdef ARBITERBUILD
Logger::Log(LogType::Http, url);
#endif
if (std::string("about:blank") == url)
return true;
@ -81,316 +34,32 @@ BOOL __fastcall Http__trustCheck_hook(const char* url)
return false;
}
void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, char a2, int a3, int a4, int a5, int a6, int a7, int a8, char a9, int a10, int a11, int a12, int a13, int a14, int a15)
{
// the actual function signature is (HCRYPTPROV* _this, std::string message, std::string signatureBase64)
// but for some reason it throws a memory access violation when you pass the parameters back into the function, without even modifying them
// each char represents the beginning of new std::string (with the int parameters, that totalls to a length of 24 bytes)
// the signature length is stored in a14 though so we can just use that
if (a14 > 1024)
{
std::ostringstream error;
error << "Signature too large. " << a14 << " > 1024";
throw std::runtime_error(error.str());
}
Crypt__verifySignatureBase64(_this, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15);
}
#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
if (!setJobId && hasJobId && !jobId.empty())
{
_this->jobId = jobId;
setJobId = true;
}
return DataModel__getJobId(_this, a2);
}
#ifdef OUTPUT
void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message)
{
StandardOut__print(_this, type, message);
if (Logger::handle)
{
#ifdef NDEBUG
// i have absolutely no clue why but the location of the message pointer is offset 4 bytes when the dll compiled as release
int messagePtr = (int)message + 4;
std::string* message = reinterpret_cast<std::string*>(messagePtr);
#endif
if (!Logger::handle) return;
Logger::Print(type, *message);
}
}
// std::string __fastcall Network__RakNetAddressToString_hook(const int raknetAddress, char portDelineator)
// {
// return Network__RakNetAddressToString(raknetAddress, portDelineator);
// }
#ifdef MFC2011
void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer)
{
if (_this->isAuthenticated)
{
// printf("ServerReplicator::sendTop called: player is authenticated\n");
ServerReplicator__sendTop(_this, peer);
}
else if (rakPeers.find(_this) == rakPeers.end())
{
// printf("ServerReplicator::sendTop called: player is not authenticated\n");
rakPeers.insert(std::pair<ServerReplicator*, RakPeerInterface*>(_this, peer));
}
}
void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet)
{
ServerReplicator__processTicket(_this, packet);
// THIS IS TEMPORARY
// i literally cant find a way to obtain rakpeerinterface from _this, like it's really damn hard
// so i'm cheating on doing that by getting rakpeerinterface from the first sendtop call,
// throwing that into a lookup table and then using that here
auto pos = rakPeers.find(_this);
if (pos == rakPeers.end())
{
// printf("ServerReplicator::sendTop called: could not find rakpeer for %08X\n", (int)_this);
}
else if (_this->isAuthenticated)
{
// printf("ServerReplicator::sendTop called: Value of peer: %08X - associated with %08X\n", (int)pos->second, (int)_this);
ServerReplicator__sendTop_hook(_this, nullptr, pos->second);
}
else
{
// printf("ServerReplicator::sendTop called: player is not authenticated\n");
}
}
#endif
#ifdef PLAYER2012
BOOL __fastcall Application__ParseArguments_hook(int _this, void*, int a2, const char* argv)
{
std::map<std::string, std::string> argslist = Util::parseArgs(argv);
if (argslist.count("-jobId"))
{
hasJobId = true;
jobId = argslist["-jobId"];
Logger::Initialize(jobId);
// now we have to exclude the -jobId arg from argv
// i'm being really lazy here, so don't do this
// i'm just gonna erase everything that comes after the -jobId arg
// thats gonna cause issues if the joinscript params are after the jobId arg,
// but really it shouldn't matter because the arbiter always starts it up in the correct order
char* pch = (char*)strstr(argv, " -jobId");
if (pch != NULL)
strncpy_s(pch, strlen(pch) + 1, "", 0);
}
return Application__ParseArguments(_this, a2, argv);
}
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
/* INT __fastcall CApp__CreateGame_hook(CApp* _this, void*, int* a2, LPCWSTR 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)
{
if (!CRobloxApp__InitInstance(_this))
return FALSE;
CApp* app = reinterpret_cast<CApp*>(CLASSLOCATION_CAPP);
if (hasAuthUrlArg && hasAuthTicketArg && !authenticationUrl.empty() && !authenticationTicket.empty())
{
CApp__RobloxAuthenticate(app, nullptr, authenticationUrl.c_str(), authenticationTicket.c_str());
}
#ifdef PLAYERBUILD
if (hasJoinArg && !joinScriptUrl.empty())
{
try
switch (type)
{
// 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);
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;
case 1: // RBX::MESSAGE_OUTPUT:
SetConsoleTextAttribute(Logger::handle, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
break;
case 0: // RBX::MESSAGE_INFO:
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
break;
case 2: // RBX::MESSAGE_WARNING:
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN);
break;
case 3: // RBX::MESSAGE_ERROR:
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_INTENSITY);
break;
}
printf("%s\n", message->c_str());
SetConsoleTextAttribute(Logger::handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
#endif
return TRUE;
}
void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast)
{
#ifdef PLAYERBUILD
if (hasJoinArg && joinScriptUrl.empty())
{
int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0);
joinScriptUrl.resize(size);
MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &joinScriptUrl[0], size);
_this->m_bRunAutomated = TRUE;
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#endif
if (hasAuthUrlArg && authenticationUrl.empty())
{
int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0);
authenticationUrl.resize(size);
MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationUrl[0], size);
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
if (hasAuthTicketArg && authenticationTicket.empty())
{
int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0);
authenticationTicket.resize(size);
MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationTicket[0], size);
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#ifdef ARBITERBUILD
if (hasJobId && jobId.empty())
{
// command line args are parsed AFTER CRobloxApp::InitInstance is run, so the logger will too be initialized after
jobId = std::string(pszParam);
Logger::Initialize(jobId);
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#endif
if (bFlag && _stricmp(pszParam, "a") == 0)
{
hasAuthUrlArg = true;
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
if (bFlag && _stricmp(pszParam, "t") == 0)
{
hasAuthTicketArg = true;
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#ifdef PLAYERBUILD
if (bFlag && _stricmp(pszParam, "j") == 0)
{
hasJoinArg = true;
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#endif
#ifdef ARBITERBUILD
if (bFlag && _stricmp(pszParam, "jobId") == 0)
{
hasJobId = true;
CCommandLineInfo__ParseLast(_this, bLast);
return;
}
#endif
CRobloxCommandLineInfo__ParseParam(_this, pszParam, bFlag, bLast);
}
#endif
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
INT __fastcall ServerReplicator__processPacket_hook(int _this, void*, Packet* packet)
{
switch ((unsigned char)packet->data[0])
{
case ID_TIMESTAMP:
printf("ServerReplicator::processPacket received ID_TIMESTAMP with length %d\n", packet->length);
break;
case ID_REQUEST_CHARACTER:
printf("ServerReplicator::processPacket received ID_REQUEST_CHARACTER with length %d\n", packet->length);
break;
case ID_DATA:
printf("ServerReplicator::processPacket received ID_DATA with length %d\n", packet->length);
break;
case ID_SUBMIT_TICKET:
printf("ServerReplicator::processPacket received ID_SUBMIT_TICKET with length %d\n", packet->length);
break;
default:
printf("ServerReplicator::processPacket received packet %d with length %d\n", packet->data[0], packet->length);
break;
}
/* if ((unsigned char)packet->data[0] == ID_SUBMIT_TICKET)
{
printf("ServerReplicator::processPacket received ID_SUBMIT_TICKET with length %d\n", packet->length);
}
else
{
printf("ServerReplicator::processPacket received packet %d with length %d\n", packet->data[0], packet->length);
} */
/* switch ((unsigned char)packet->data[0])
{
case ID_SUBMIT_TICKET:
// printf("ServerReplicator::processPacket called: ID_SUBMIT_TICKET\n");
return ServerReplicator__processPacket(_this, packet);
default:
if (true)
{
Logger::Print(2, "Player not authenticated s");
return RR_STOP_PROCESSING_AND_DEALLOCATE;
}
return ServerReplicator__processPacket(_this, packet);
} */
return ServerReplicator__processPacket(_this, packet);
}
#endif
#endif

View File

@ -4,75 +4,21 @@
// Type Definitions //
typedef BOOL(__thiscall* Http__trustCheck_t)(const char* url);
typedef void(__thiscall* Crypt__verifySignatureBase64_t)(HCRYPTPROV* _this, char a2, int a3, int a4, int a5, int a6, int a7, int a8, char a9, int a10, int a11, int a12, int a13, int a14, int a15);
#ifdef ARBITERBUILD
typedef INT(__thiscall* DataModel__getJobId_t)(DataModel* _this, int a2);
typedef BOOL(__thiscall* Http__trustCheck_t)(int _this, const char* url);
#ifdef OUTPUT
typedef void(__thiscall* StandardOut__print_t)(int _this, int type, std::string* message);
// typedef std::string(__thiscall* Network__RakNetAddressToString_t)(const int raknetAddress, char portDelineator);
#ifdef MFC2011
typedef void(__thiscall* ServerReplicator__sendTop_t)(ServerReplicator* _this, RakPeerInterface* peer);
typedef void(__thiscall* ServerReplicator__processTicket_t)(ServerReplicator* _this, Packet* packet);
#endif
#ifdef PLAYER2012
typedef BOOL(__thiscall* Application__ParseArguments_t)(int _this, int a2, const char* argv);
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
// 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
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
typedef int(__thiscall* ServerReplicator__processPacket_t)(int _this, Packet* packet);
#endif
// Hook Declarations //
BOOL __fastcall Http__trustCheck_hook(const char* url);
void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, char a2, int a3, int a4, int a5, int a6, int a7, int a8, char a9, int a10, int a11, int a12, int a13, int a14, int a15);
#ifdef ARBITERBUILD
INT __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2);
BOOL __fastcall Http__trustCheck_hook(int _this, void*, const char* url);
#ifdef OUTPUT
void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message);
// std::string __fastcall Network__RakNetAddressToString_hook(const int raknetAddress, char portDelineator);
#ifdef MFC2011
void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer);
void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet);
#endif
#ifdef PLAYER2012
BOOL __fastcall Application__ParseArguments_hook(int _this, void*, int a2, const char* argv);
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
// 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
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
INT __fastcall ServerReplicator__processPacket_hook(int _this, void*, Packet* packet);
#endif
// Externals //
extern Http__trustCheck_t Http__trustCheck;
extern Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64;
#ifdef ARBITERBUILD
extern DataModel__getJobId_t DataModel__getJobId;
#ifdef OUTPUT
extern StandardOut__print_t StandardOut__print;
// extern Network__RakNetAddressToString_t Network__RakNetAddressToString;
#ifdef MFC2011
extern ServerReplicator__sendTop_t ServerReplicator__sendTop;
extern ServerReplicator__processTicket_t ServerReplicator__processTicket;
#endif
#ifdef PLAYER2012
extern Application__ParseArguments_t Application__ParseArguments;
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
// extern CApp__CreateGame_t CApp__CreateGame;
extern CRobloxApp__InitInstance_t CRobloxApp__InitInstance;
extern CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam;
#endif
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
extern ServerReplicator__processPacket_t ServerReplicator__processPacket;
#endif

View File

@ -13,7 +13,13 @@ const std::vector<std::string> Util::allowedHosts
"assetdelivery.roblox.com",
"tadah.rocks",
"www.tadah.rocks"
"www.tadah.rocks",
"api.tadah.rocks",
"clientsettings.tadah.rocks",
"calones.xyz",
"www.calones.xyz",
"cdn.calones.xyz"
};
const std::vector<std::string> Util::allowedSchemes
@ -30,31 +36,6 @@ const std::vector<std::string> Util::allowedEmbeddedSchemes
"res"
};
std::map<std::string, std::string> Util::parseArgs(std::string args)
{
std::map<std::string, std::string> map;
std::string::size_type key_pos = 0;
std::string::size_type key_end;
std::string::size_type val_pos;
std::string::size_type val_end;
while ((key_end = args.find(' ', key_pos)) != std::string::npos)
{
if ((val_pos = args.find_first_not_of(" -", key_end)) == std::string::npos)
break;
val_end = args.find(" -", val_pos);
map.emplace(args.substr(key_pos, key_end - key_pos), args.substr(val_pos, val_end - val_pos));
key_pos = val_end;
if (key_pos != std::string::npos)
++key_pos;
}
return map;
}
// https://stackoverflow.com/questions/48212992/how-to-find-out-if-there-is-any-non-ascii-character-in-a-string-with-a-file-path
bool Util::isASCII(const std::string& s)
{

View File

@ -2,38 +2,20 @@
#include "Config.h"
#include "Patches.h"
#include "RobloxMFCHooks.h"
#include "Logger.h" // remove when testing is done
#include "Logger.h"
START_PATCH_LIST()
ADD_PATCH(Http__trustCheck, Http__trustCheck_hook)
ADD_PATCH(Crypt__verifySignatureBase64, Crypt__verifySignatureBase64_hook)
#ifdef ARBITERBUILD
ADD_PATCH(DataModel__getJobId, DataModel__getJobId_hook)
#ifdef OUTPUT
ADD_PATCH(StandardOut__print, StandardOut__print_hook)
// ADD_PATCH(Network__RakNetAddressToString, Network__RakNetAddressToString_hook)
#ifdef MFC2011
ADD_PATCH(ServerReplicator__sendTop, ServerReplicator__sendTop_hook)
ADD_PATCH(ServerReplicator__processTicket, ServerReplicator__processTicket_hook)
#endif
#ifdef PLAYER2012
ADD_PATCH(Application__ParseArguments, Application__ParseArguments_hook)
#endif
#endif
#if defined(MFC2010) || defined(MFC2011)
// ADD_PATCH(CApp__CreateGame, CApp__CreateGame_hook)
ADD_PATCH(CRobloxApp__InitInstance, CRobloxApp__InitInstance_hook)
ADD_PATCH(CRobloxCommandLineInfo__ParseParam, CRobloxCommandLineInfo__ParseParam_hook)
#endif
#ifdef DEBUG_SERVERREPLICATOR__PROCESSPACKET
ADD_PATCH(ServerReplicator__processPacket, ServerReplicator__processPacket_hook)
#endif
END_PATCH_LIST()
// DLLs for release will be loaded with VMProtect, so this isn't necessary
// Arbiter will still use Stud_PE for ease in swapping DLLs however
#ifdef ARBITERBUILD
// #ifdef ARBITERBUILD
void __declspec(dllexport) import() {}
#endif
// #endif
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
@ -49,6 +31,9 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
ExitProcess(EXIT_FAILURE);
}
#ifdef OUTPUT
Logger::Initialize("output");
#endif
}
return TRUE;