normalize spacing ;-;
This commit is contained in:
parent
d1493f1182
commit
48262dbae3
|
|
@ -5,23 +5,23 @@
|
|||
|
||||
struct Tuple
|
||||
{
|
||||
void* padding1[4];
|
||||
bool padding2;
|
||||
bool padding3;
|
||||
void* padding1[4];
|
||||
bool padding2;
|
||||
bool padding3;
|
||||
};
|
||||
|
||||
struct DataModel
|
||||
{
|
||||
void* padding1[CLASSPADDING_DATAMODEL__JOBID + PADDING_STRUCT];
|
||||
std::string jobId;
|
||||
void* padding1[CLASSPADDING_DATAMODEL__JOBID + PADDING_STRUCT];
|
||||
std::string jobId;
|
||||
};
|
||||
|
||||
struct Game
|
||||
{
|
||||
// 2010 has a class size of 104 bytes
|
||||
void* padding1[8];
|
||||
std::shared_ptr<DataModel> dataModel;
|
||||
void* padding2[9];
|
||||
// 2010 has a class size of 104 bytes
|
||||
void* padding1[8];
|
||||
std::shared_ptr<DataModel> dataModel;
|
||||
void* padding2[9];
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
#if PADDING_STRUCT != 0
|
||||
void* padding1[1];
|
||||
void* padding1[1];
|
||||
#endif
|
||||
std::string alternateUrl;
|
||||
void* padding2[3 + PADDING_STRUCT];
|
||||
std::string url;
|
||||
std::string alternateUrl;
|
||||
void* padding2[3 + PADDING_STRUCT];
|
||||
std::string url;
|
||||
};
|
||||
|
||||
// const auto DataModel__createDataModel = (std::shared_ptr<void>(__thiscall*)(bool startHeartbeat))ADDRESS_DATAMODEL__CREATEDATAMODEL;
|
||||
|
||||
struct Packet
|
||||
{
|
||||
void* padding1[7];
|
||||
unsigned int length;
|
||||
void* padding2[1];
|
||||
unsigned char* data;
|
||||
void* padding1[7];
|
||||
unsigned int length;
|
||||
void* padding2[1];
|
||||
unsigned char* data;
|
||||
};
|
||||
|
||||
struct ConcurrentRakPeer {};
|
||||
|
|
@ -56,9 +56,9 @@ struct RakPeerInterface {};
|
|||
|
||||
struct ServerReplicator
|
||||
{
|
||||
void* padding1[1869]; // offset of 0 -> 7476
|
||||
bool padding2; // offset of 7476 -> 7477
|
||||
bool isAuthenticated; // offset of 7477 -> 7478
|
||||
void* padding1[1869]; // offset of 0 -> 7476
|
||||
bool padding2; // offset of 7476 -> 7477
|
||||
bool isAuthenticated; // offset of 7477 -> 7478
|
||||
};
|
||||
|
||||
// 2010 struct definitions:
|
||||
|
|
@ -71,8 +71,8 @@ const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspa
|
|||
|
||||
struct CRobloxDoc
|
||||
{
|
||||
void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE];
|
||||
CWorkspace* workspace;
|
||||
void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE];
|
||||
CWorkspace* workspace;
|
||||
};
|
||||
|
||||
struct CApp;
|
||||
|
|
@ -91,8 +91,8 @@ const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp *
|
|||
|
||||
struct CCommandLineInfo
|
||||
{
|
||||
void* padding1[3];
|
||||
BOOL m_bRunAutomated;
|
||||
void* padding1[3];
|
||||
BOOL m_bRunAutomated;
|
||||
};
|
||||
|
||||
class CRobloxCommandLineInfo : public CCommandLineInfo {};
|
||||
|
|
|
|||
|
|
@ -110,18 +110,18 @@
|
|||
// RobloxPlayerBeta (2012)
|
||||
#ifdef PLAYER2012
|
||||
/*
|
||||
2012 is a bit different in that the player executable is protected with
|
||||
VMProtect. VMProtect offsets the memory locations randomly on startup.
|
||||
This causes address definitions (such as the ones below) to look a bit off.
|
||||
2012 is a bit different in that the player executable is protected with
|
||||
VMProtect. VMProtect offsets the memory locations randomly on startup.
|
||||
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
|
||||
you have a TrustCheck hook that is at 0x00DF20A0, VMProtect will offset the
|
||||
memory location from 0x00000000 - 0x00FF0000. Thus, the 0x00BF0000 in
|
||||
0x00BF1000 is actually an offset.
|
||||
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
|
||||
memory location from 0x00000000 - 0x00FF0000. Thus, the 0x00BF0000 in
|
||||
0x00BF1000 is actually an offset.
|
||||
|
||||
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
|
||||
into the function.
|
||||
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
|
||||
into the function.
|
||||
*/
|
||||
|
||||
// MFC specific definitions
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ extern Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64;
|
|||
|
||||
class Crypt
|
||||
{
|
||||
HCRYPTPROV context;
|
||||
HCRYPTKEY key;
|
||||
HCRYPTPROV context;
|
||||
HCRYPTKEY key;
|
||||
|
||||
public:
|
||||
Crypt();
|
||||
~Crypt();
|
||||
bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm);
|
||||
Crypt();
|
||||
~Crypt();
|
||||
bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm);
|
||||
};
|
||||
|
|
@ -3,194 +3,194 @@
|
|||
#include "Util.h"
|
||||
|
||||
#define CHECK(condition, code) \
|
||||
if(!error) { \
|
||||
if ((condition)) { \
|
||||
error = code; \
|
||||
} \
|
||||
}
|
||||
if(!error) { \
|
||||
if ((condition)) { \
|
||||
error = code; \
|
||||
} \
|
||||
}
|
||||
|
||||
Http__httpGetPostWinInet_t Http__httpGetPostWinInet = (Http__httpGetPostWinInet_t)ADDRESS_HTTP__HTTPGETPOSTWININET;
|
||||
Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK;
|
||||
|
||||
size_t write(char* contents, size_t size, size_t memory, void* pointer)
|
||||
{
|
||||
((std::string*)pointer)->append((char*)contents, size * memory);
|
||||
return size * memory;
|
||||
((std::string*)pointer)->append((char*)contents, size * memory);
|
||||
return size * memory;
|
||||
}
|
||||
|
||||
void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6)
|
||||
{
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, _this->url.c_str(), 0);
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, _this->url.c_str(), 0);
|
||||
|
||||
Http _changed = *_this;
|
||||
Http _changed = *_this;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
char* path;
|
||||
char* host;
|
||||
char* query;
|
||||
if (!result)
|
||||
{
|
||||
char* path;
|
||||
char* host;
|
||||
char* query;
|
||||
|
||||
curl_url_get(curl, CURLUPART_PATH, &path, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_get(curl, CURLUPART_QUERY, &query, 0);
|
||||
curl_url_cleanup(curl);
|
||||
curl_url_get(curl, CURLUPART_PATH, &path, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_get(curl, CURLUPART_QUERY, &query, 0);
|
||||
curl_url_cleanup(curl);
|
||||
|
||||
if (path != NULL && host != NULL && query != NULL)
|
||||
{
|
||||
std::string _path = Util::toLower(std::string(path));
|
||||
std::string _host = std::string(host);
|
||||
std::string _query = std::string(query);
|
||||
if (path != NULL && host != NULL && query != NULL)
|
||||
{
|
||||
std::string _path = Util::toLower(std::string(path));
|
||||
std::string _host = std::string(host);
|
||||
std::string _query = std::string(query);
|
||||
|
||||
if (_host == "roblox.com" || _host == "www.roblox.com")
|
||||
{
|
||||
if (_path == "/asset" || _path == "/asset/" || _path == "/asset/default.ashx")
|
||||
{
|
||||
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + _query;
|
||||
_this = &_changed;
|
||||
}
|
||||
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.
|
||||
if (_host == "roblox.com" || _host == "www.roblox.com")
|
||||
{
|
||||
if (_path == "/asset" || _path == "/asset/" || _path == "/asset/default.ashx")
|
||||
{
|
||||
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + _query;
|
||||
_this = &_changed;
|
||||
}
|
||||
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.
|
||||
|
||||
Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix
|
||||
Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix
|
||||
Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix
|
||||
Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix
|
||||
|
||||
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)
|
||||
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)
|
||||
5. Append to the Roblox url (specific to the endpoint)
|
||||
6. Fetch Roblox API
|
||||
7. Parse JSON
|
||||
8. Set the URL as the given url
|
||||
*/
|
||||
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)
|
||||
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)
|
||||
5. Append to the Roblox url (specific to the endpoint)
|
||||
6. Fetch Roblox API
|
||||
7. Parse JSON
|
||||
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> fixed = {
|
||||
{ _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" },
|
||||
{ "thumbnailFormatId", "0" }
|
||||
};
|
||||
|
||||
for (auto& pair : source)
|
||||
{
|
||||
fixed[Util::toLower(pair.first)] = pair.second;
|
||||
}
|
||||
std::map<std::string, std::string> source = Util::parseQueryString(query);
|
||||
std::map<std::string, std::string> fixed = {
|
||||
{ _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" },
|
||||
{ "thumbnailFormatId", "0" }
|
||||
};
|
||||
|
||||
for (auto& pair : source)
|
||||
{
|
||||
fixed[Util::toLower(pair.first)] = pair.second;
|
||||
}
|
||||
|
||||
if (fixed.find("id") != fixed.end())
|
||||
{
|
||||
auto handler = fixed.extract("id");
|
||||
handler.key() = _path == "/thumbs/asset.ashx" ? "assetId" : "userId";
|
||||
|
||||
fixed.insert(std::move(handler));
|
||||
}
|
||||
if (fixed.find("id") != fixed.end())
|
||||
{
|
||||
auto handler = fixed.extract("id");
|
||||
handler.key() = _path == "/thumbs/asset.ashx" ? "assetId" : "userId";
|
||||
|
||||
fixed.insert(std::move(handler));
|
||||
}
|
||||
|
||||
api += Util::joinQueryString(fixed);
|
||||
|
||||
// get the api response
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
std::string data;
|
||||
api += Util::joinQueryString(fixed);
|
||||
|
||||
// get the api response
|
||||
CURL* curl = curl_easy_init();
|
||||
CURLcode result;
|
||||
long response = 0;
|
||||
std::string data;
|
||||
|
||||
if (!curl)
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize cURL");
|
||||
}
|
||||
if (!curl)
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize cURL");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
result = curl_easy_perform(curl);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (result != CURLE_OK || response != 200)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x1");
|
||||
}
|
||||
if (result != CURLE_OK || response != 200)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x1");
|
||||
}
|
||||
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
|
||||
// Ryelow should fucking kill herself
|
||||
int error = 0;
|
||||
// Ryelow should fucking kill herself
|
||||
int error = 0;
|
||||
|
||||
CHECK(document.HasParseError(), 0x02);
|
||||
CHECK(!document.HasMember("d"), 0x03);
|
||||
CHECK(!document["d"].IsObject(), 0x04);
|
||||
CHECK(!document["d"].HasMember("url"), 0x04);
|
||||
CHECK(!document["d"]["url"].IsString(), 0x04);
|
||||
CHECK(document.HasParseError(), 0x02);
|
||||
CHECK(!document.HasMember("d"), 0x03);
|
||||
CHECK(!document["d"].IsObject(), 0x04);
|
||||
CHECK(!document["d"].HasMember("url"), 0x04);
|
||||
CHECK(!document["d"]["url"].IsString(), 0x04);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error));
|
||||
}
|
||||
if (error != 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error));
|
||||
}
|
||||
|
||||
_changed.url = document["d"]["url"].GetString();
|
||||
_this = &_changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_changed.url = document["d"]["url"].GetString();
|
||||
_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)
|
||||
{
|
||||
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
|
||||
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; // 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
|
||||
// cURL does not treat embedded resources as URLs
|
||||
// checking for embedded schemes must come BEFORE checking if it's valid
|
||||
// cURL does not treat embedded resources as URLs
|
||||
|
||||
if (_url == "about:blank")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (_url == "about:blank")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (std::string allowedEmbeddedScheme : Util::allowedEmbeddedSchemes)
|
||||
{
|
||||
if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (std::string allowedEmbeddedScheme : Util::allowedEmbeddedSchemes)
|
||||
{
|
||||
if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url, 0);
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url, 0);
|
||||
|
||||
if (result != CURLE_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (result != CURLE_OK)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
char* scheme;
|
||||
char* host;
|
||||
char* scheme;
|
||||
char* host;
|
||||
|
||||
curl_url_get(curl, CURLUPART_SCHEME, &scheme, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_cleanup(curl);
|
||||
curl_url_get(curl, CURLUPART_SCHEME, &scheme, 0);
|
||||
curl_url_get(curl, CURLUPART_HOST, &host, 0);
|
||||
curl_url_cleanup(curl);
|
||||
|
||||
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();
|
||||
}
|
||||
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 false;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
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();
|
||||
VOID ResolveOffset();
|
||||
INT GetAddressByOffset(int address);
|
||||
LONG Apply();
|
||||
VOID ResolveOffset();
|
||||
INT GetAddressByOffset(int address);
|
||||
}
|
||||
|
||||
#define START_PATCH_LIST() std::vector<Patches::Patch> Patches::patchList = {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,11 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
|||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue