normalize spacing ;-;

This commit is contained in:
lightbulblighter 2022-06-07 01:08:26 -07:00
parent d1493f1182
commit 48262dbae3
No known key found for this signature in database
GPG Key ID: 0B2452F9DE0E2D01
6 changed files with 192 additions and 188 deletions

View File

@ -5,23 +5,23 @@
struct Tuple struct Tuple
{ {
void* padding1[4]; void* padding1[4];
bool padding2; bool padding2;
bool padding3; bool padding3;
}; };
struct DataModel struct DataModel
{ {
void* padding1[CLASSPADDING_DATAMODEL__JOBID + PADDING_STRUCT]; void* padding1[CLASSPADDING_DATAMODEL__JOBID + PADDING_STRUCT];
std::string jobId; std::string jobId;
}; };
struct Game struct Game
{ {
// 2010 has a class size of 104 bytes // 2010 has a class size of 104 bytes
void* padding1[8]; void* padding1[8];
std::shared_ptr<DataModel> dataModel; std::shared_ptr<DataModel> dataModel;
void* padding2[9]; void* padding2[9];
}; };
const auto Game__initializeClass = (Game * (__thiscall*)(Game* _this, int a2))0x455D40; const auto Game__initializeClass = (Game * (__thiscall*)(Game* _this, int a2))0x455D40;
@ -34,21 +34,21 @@ const auto ScriptContext__execute = (void (__thiscall*)(void* _this, int identit
struct Http struct Http
{ {
#if PADDING_STRUCT != 0 #if PADDING_STRUCT != 0
void* padding1[1]; void* padding1[1];
#endif #endif
std::string alternateUrl; std::string alternateUrl;
void* padding2[3 + PADDING_STRUCT]; void* padding2[3 + PADDING_STRUCT];
std::string url; std::string url;
}; };
// const auto DataModel__createDataModel = (std::shared_ptr<void>(__thiscall*)(bool startHeartbeat))ADDRESS_DATAMODEL__CREATEDATAMODEL; // const auto DataModel__createDataModel = (std::shared_ptr<void>(__thiscall*)(bool startHeartbeat))ADDRESS_DATAMODEL__CREATEDATAMODEL;
struct Packet struct Packet
{ {
void* padding1[7]; void* padding1[7];
unsigned int length; unsigned int length;
void* padding2[1]; void* padding2[1];
unsigned char* data; unsigned char* data;
}; };
struct ConcurrentRakPeer {}; struct ConcurrentRakPeer {};
@ -56,9 +56,9 @@ struct RakPeerInterface {};
struct ServerReplicator struct ServerReplicator
{ {
void* padding1[1869]; // offset of 0 -> 7476 void* padding1[1869]; // offset of 0 -> 7476
bool padding2; // offset of 7476 -> 7477 bool padding2; // offset of 7476 -> 7477
bool isAuthenticated; // offset of 7477 -> 7478 bool isAuthenticated; // offset of 7477 -> 7478
}; };
// 2010 struct definitions: // 2010 struct definitions:
@ -71,8 +71,8 @@ const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspa
struct CRobloxDoc struct CRobloxDoc
{ {
void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE]; void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE];
CWorkspace* workspace; CWorkspace* workspace;
}; };
struct CApp; struct CApp;
@ -91,8 +91,8 @@ const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp *
struct CCommandLineInfo struct CCommandLineInfo
{ {
void* padding1[3]; void* padding1[3];
BOOL m_bRunAutomated; BOOL m_bRunAutomated;
}; };
class CRobloxCommandLineInfo : public CCommandLineInfo {}; class CRobloxCommandLineInfo : public CCommandLineInfo {};

View File

@ -110,18 +110,18 @@
// RobloxPlayerBeta (2012) // RobloxPlayerBeta (2012)
#ifdef PLAYER2012 #ifdef PLAYER2012
/* /*
2012 is a bit different in that the player executable is protected with 2012 is a bit different in that the player executable is protected with
VMProtect. VMProtect offsets the memory locations randomly on startup. VMProtect. VMProtect offsets the memory locations randomly on startup.
This causes address definitions (such as the ones below) to look a bit off. This causes address definitions (such as the ones below) to look a bit off.
For example, if the beginning of the program is located at 0x00BF1000 and For example, if the beginning of the program is located at 0x00BF1000 and
you have a TrustCheck hook that is at 0x00DF20A0, VMProtect will offset the you have a TrustCheck hook that is at 0x00DF20A0, VMProtect will offset the
memory location from 0x00000000 - 0x00FF0000. Thus, the 0x00BF0000 in memory location from 0x00000000 - 0x00FF0000. Thus, the 0x00BF0000 in
0x00BF1000 is actually an offset. 0x00BF1000 is actually an offset.
With that offset, the address you'd have to put for your TrustCheck hook will With that offset, the address you'd have to put for your TrustCheck hook will
be (0x00DF20A0 - 0x00BF0000) = 0x002020A0. Then, you just put that address be (0x00DF20A0 - 0x00BF0000) = 0x002020A0. Then, you just put that address
into the function. into the function.
*/ */
// MFC specific definitions // MFC specific definitions

View File

@ -9,11 +9,11 @@ extern Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64;
class Crypt class Crypt
{ {
HCRYPTPROV context; HCRYPTPROV context;
HCRYPTKEY key; HCRYPTKEY key;
public: public:
Crypt(); Crypt();
~Crypt(); ~Crypt();
bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm); bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm);
}; };

View File

@ -3,194 +3,194 @@
#include "Util.h" #include "Util.h"
#define CHECK(condition, code) \ #define CHECK(condition, code) \
if(!error) { \ if(!error) { \
if ((condition)) { \ if ((condition)) { \
error = code; \ error = code; \
} \ } \
} }
Http__httpGetPostWinInet_t Http__httpGetPostWinInet = (Http__httpGetPostWinInet_t)ADDRESS_HTTP__HTTPGETPOSTWININET; Http__httpGetPostWinInet_t Http__httpGetPostWinInet = (Http__httpGetPostWinInet_t)ADDRESS_HTTP__HTTPGETPOSTWININET;
Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK; Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK;
size_t write(char* contents, size_t size, size_t memory, void* pointer) size_t write(char* contents, size_t size, size_t memory, void* pointer)
{ {
((std::string*)pointer)->append((char*)contents, size * memory); ((std::string*)pointer)->append((char*)contents, size * memory);
return size * memory; return size * memory;
} }
void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6) void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6)
{ {
CURLU* curl = curl_url(); CURLU* curl = curl_url();
CURLUcode result = curl_url_set(curl, CURLUPART_URL, _this->url.c_str(), 0); CURLUcode result = curl_url_set(curl, CURLUPART_URL, _this->url.c_str(), 0);
Http _changed = *_this; Http _changed = *_this;
if (!result) if (!result)
{ {
char* path; char* path;
char* host; char* host;
char* query; char* query;
curl_url_get(curl, CURLUPART_PATH, &path, 0); curl_url_get(curl, CURLUPART_PATH, &path, 0);
curl_url_get(curl, CURLUPART_HOST, &host, 0); curl_url_get(curl, CURLUPART_HOST, &host, 0);
curl_url_get(curl, CURLUPART_QUERY, &query, 0); curl_url_get(curl, CURLUPART_QUERY, &query, 0);
curl_url_cleanup(curl); curl_url_cleanup(curl);
if (path != NULL && host != NULL && query != NULL) if (path != NULL && host != NULL && query != NULL)
{ {
std::string _path = Util::toLower(std::string(path)); std::string _path = Util::toLower(std::string(path));
std::string _host = std::string(host); std::string _host = std::string(host);
std::string _query = std::string(query); std::string _query = std::string(query);
if (_host == "roblox.com" || _host == "www.roblox.com") if (_host == "roblox.com" || _host == "www.roblox.com")
{ {
if (_path == "/asset" || _path == "/asset/" || _path == "/asset/default.ashx") if (_path == "/asset" || _path == "/asset/" || _path == "/asset/default.ashx")
{ {
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + _query; _changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + _query;
_this = &_changed; _this = &_changed;
} }
else if (_path == "/thumbs/asset.ashx" || _path == "/thumbs/avatar.ashx") else if (_path == "/thumbs/asset.ashx" || _path == "/thumbs/avatar.ashx")
{ {
/* /*
Both Roblox endpoints require thumbnailFormatId to be set. We will make the default value for it as 0. Both Roblox endpoints require thumbnailFormatId to be set. We will make the default value for it as 0.
Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix
Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix
1. Parse query 1. Parse query
2. Construct a brand new blank query with thumbnailFormatId as 0 and dummy/overrideModeration as false (if Avatar.ashx or Asset.ashx) 2. Construct a brand new blank query with thumbnailFormatId as 0 and dummy/overrideModeration as false (if Avatar.ashx or Asset.ashx)
3. Merge the old query with priority over the old query so that if they declared any of the special variables, ours gets overwritten 3. Merge the old query with priority over the old query so that if they declared any of the special variables, ours gets overwritten
4. Rename id (if found) to assetId or userId (specific to the endpoint) 4. Rename id (if found) to assetId or userId (specific to the endpoint)
5. Append to the Roblox url (specific to the endpoint) 5. Append to the Roblox url (specific to the endpoint)
6. Fetch Roblox API 6. Fetch Roblox API
7. Parse JSON 7. Parse JSON
8. Set the URL as the given url 8. Set the URL as the given url
*/ */
std::string api = "https://www.roblox.com/" + std::string(_path == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix"; std::string api = "https://www.roblox.com/" + std::string(_path == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix";
std::map<std::string, std::string> source = Util::parseQueryString(query); std::map<std::string, std::string> source = Util::parseQueryString(query);
std::map<std::string, std::string> fixed = { std::map<std::string, std::string> fixed = {
{ _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" }, { _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" },
{ "thumbnailFormatId", "0" } { "thumbnailFormatId", "0" }
}; };
for (auto& pair : source) for (auto& pair : source)
{ {
fixed[Util::toLower(pair.first)] = pair.second; fixed[Util::toLower(pair.first)] = pair.second;
} }
if (fixed.find("id") != fixed.end()) if (fixed.find("id") != fixed.end())
{ {
auto handler = fixed.extract("id"); auto handler = fixed.extract("id");
handler.key() = _path == "/thumbs/asset.ashx" ? "assetId" : "userId"; handler.key() = _path == "/thumbs/asset.ashx" ? "assetId" : "userId";
fixed.insert(std::move(handler)); fixed.insert(std::move(handler));
} }
api += Util::joinQueryString(fixed); api += Util::joinQueryString(fixed);
// get the api response // get the api response
CURL* curl = curl_easy_init(); CURL* curl = curl_easy_init();
CURLcode result; CURLcode result;
long response = 0; long response = 0;
std::string data; std::string data;
if (!curl) if (!curl)
{ {
throw std::runtime_error("Failed to initialize cURL"); throw std::runtime_error("Failed to initialize cURL");
} }
curl_easy_setopt(curl, CURLOPT_URL, api); curl_easy_setopt(curl, CURLOPT_URL, api);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
result = curl_easy_perform(curl); result = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (result != CURLE_OK || response != 200) if (result != CURLE_OK || response != 200)
{ {
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x1"); throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x1");
} }
rapidjson::Document document; rapidjson::Document document;
document.Parse(data.c_str()); document.Parse(data.c_str());
// Ryelow should fucking kill herself // Ryelow should fucking kill herself
int error = 0; int error = 0;
CHECK(document.HasParseError(), 0x02); CHECK(document.HasParseError(), 0x02);
CHECK(!document.HasMember("d"), 0x03); CHECK(!document.HasMember("d"), 0x03);
CHECK(!document["d"].IsObject(), 0x04); CHECK(!document["d"].IsObject(), 0x04);
CHECK(!document["d"].HasMember("url"), 0x04); CHECK(!document["d"].HasMember("url"), 0x04);
CHECK(!document["d"]["url"].IsString(), 0x04); CHECK(!document["d"]["url"].IsString(), 0x04);
if (error != 0) if (error != 0)
{ {
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error)); throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error));
} }
_changed.url = document["d"]["url"].GetString(); _changed.url = document["d"]["url"].GetString();
_this = &_changed; _this = &_changed;
} }
} }
} }
} }
Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6); Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6);
} }
BOOL __fastcall Http__trustCheck_hook(const char* url) BOOL __fastcall Http__trustCheck_hook(const char* url)
{ {
if (strlen(url) == 7 && !Util::isASCII(url)) if (strlen(url) == 7 && !Util::isASCII(url))
{ {
// so the client does this really fucking stupid thing where if it opens an ie window, // so the client does this really fucking stupid thing where if it opens an ie window,
// it passes a char**, and not a char* // 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 // 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 // practically no url is ever going to be seven characters long so it doesn't really matter
url = *(char**)url; // wHOEVER DID THIS FUCKING CAST NEEDS TO GET RAPED BY 10 GORILLION GRIGRGERS url = *(char**)url; // wHOEVER DID THIS FUCKING CAST NEEDS TO GET RAPED BY 10 GORILLION GRIGRGERS
} }
std::string _url = std::string(url); std::string _url = std::string(url);
// checking for embedded schemes must come BEFORE checking if it's valid // checking for embedded schemes must come BEFORE checking if it's valid
// cURL does not treat embedded resources as URLs // cURL does not treat embedded resources as URLs
if (_url == "about:blank") if (_url == "about:blank")
{ {
return true; return true;
} }
for (std::string allowedEmbeddedScheme : Util::allowedEmbeddedSchemes) for (std::string allowedEmbeddedScheme : Util::allowedEmbeddedSchemes)
{ {
if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0) if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0)
{ {
return true; return true;
} }
} }
CURLU* curl = curl_url(); CURLU* curl = curl_url();
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url, 0); CURLUcode result = curl_url_set(curl, CURLUPART_URL, url, 0);
if (result != CURLE_OK) if (result != CURLE_OK)
{ {
return false; return false;
} }
char* scheme; char* scheme;
char* host; char* host;
curl_url_get(curl, CURLUPART_SCHEME, &scheme, 0); curl_url_get(curl, CURLUPART_SCHEME, &scheme, 0);
curl_url_get(curl, CURLUPART_HOST, &host, 0); curl_url_get(curl, CURLUPART_HOST, &host, 0);
curl_url_cleanup(curl); curl_url_cleanup(curl);
if (std::find(Util::allowedSchemes.begin(), Util::allowedSchemes.end(), std::string(scheme)) != Util::allowedSchemes.end()) if (std::find(Util::allowedSchemes.begin(), Util::allowedSchemes.end(), std::string(scheme)) != Util::allowedSchemes.end())
{ {
return std::find(Util::allowedHosts.begin(), Util::allowedHosts.end(), std::string(host)) != Util::allowedHosts.end(); return std::find(Util::allowedHosts.begin(), Util::allowedHosts.end(), std::string(host)) != Util::allowedHosts.end();
} }
return false; return false;
} }

View File

@ -2,13 +2,13 @@
namespace Patches namespace Patches
{ {
typedef std::pair<void**, void*> Patch; typedef std::pair<void**, void*> Patch;
extern std::vector<Patch> patchList; extern std::vector<Patch> patchList;
LONG Apply(); LONG Apply();
VOID ResolveOffset(); VOID ResolveOffset();
INT GetAddressByOffset(int address); INT GetAddressByOffset(int address);
} }
#define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = { #define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = {

View File

@ -80,7 +80,11 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
ExitProcess(EXIT_FAILURE); ExitProcess(EXIT_FAILURE);
} }
curl_global_init(CURL_GLOBAL_DEFAULT); CURLcode result = curl_global_init(CURL_GLOBAL_DEFAULT);
if (result != CURLE_OK)
{
ExitProcess(EXIT_FAILURE);
}
} }
if (ul_reason_for_call == DLL_PROCESS_DETACH) if (ul_reason_for_call == DLL_PROCESS_DETACH)