finish /Thumbs/ fixes

This commit is contained in:
lightbulblighter 2022-06-06 02:47:27 -07:00
parent d04cbd5ca8
commit 9ec7686a6f
No known key found for this signature in database
GPG Key ID: 0B2452F9DE0E2D01
4 changed files with 77 additions and 12 deletions

View File

@ -50,7 +50,7 @@ bool Crypt::verifySignatureBase64(std::string message, std::string signatureBase
if (!CryptCreateHash(context, algorithm, NULL, 0, &hash)) if (!CryptCreateHash(context, algorithm, NULL, 0, &hash))
{ {
return false; throw std::runtime_error("");
} }
try try
@ -88,6 +88,8 @@ bool Crypt::verifySignatureBase64(std::string message, std::string signatureBase
} }
::CryptDestroyHash(hash); ::CryptDestroyHash(hash);
return true;
} }
Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64; Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64;

View File

@ -51,20 +51,45 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i
} }
else if (_path == "/thumbs/asset.ashx" || _path == "/thumbs/avatar.ashx") else if (_path == "/thumbs/asset.ashx" || _path == "/thumbs/avatar.ashx")
{ {
// https://www.roblox.com/asset/request-thumbnail-fix?assetId=1818&assetVersionId=0&width=420&height=420&imageFormat=Png&thumbnailFormatId=296&overrideModeration=false /*
// https://www.roblox.com/avatar/request-thumbnail-fix?userId=86890093&width=100&height=100&imageFormat=Png&thumbnailFormatId=41&dummy=false Both Roblox endpoints require thumbnailFormatId to be set. We will make the default value for it as 0.
// https://www.roblox.com/asset/request-thumbnail-fix for asset.ashx ; needs assetId
// https://www.roblox.com/avatar/request-thumbnail-fix for avatar.ashx ; needs userId
std::string replaceWith = _path == "/thumbs/asset.ashx" ? "assetId" : "userId"; Asset.ashx -> requires overrideModeration (default false) -> /asset/request-thumbnail-fix
std::string apiUrl = "https://www.roblox.com/" + std::string(_path == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix?"; Avatar.ashx -> requires dummy (default false) -> /avatar/request-thumbnail-fix
// parse query stuff here 1. Parse query
std::string query = ""; 2. Construct a brand new blank query with thumbnailFormatId as 0 and dummy/overrideModeration as false (if Avatar.ashx or Asset.ashx)
apiUrl += query; 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
*/
printf("\napiUrl: %s\n", apiUrl.c_str()); 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[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));
}
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;
@ -76,7 +101,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i
throw std::runtime_error("Failed to initialize cURL"); throw std::runtime_error("Failed to initialize cURL");
} }
curl_easy_setopt(curl, CURLOPT_URL, apiUrl); 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);

View File

@ -130,4 +130,40 @@ std::vector<BYTE> Util::base64Decode(const std::string_view data)
} }
return out; return out;
}
// https://stackoverflow.com/a/28269049
std::map<std::string, std::string> Util::parseQueryString(std::string query)
{
std::istringstream stream(query);
std::map<std::string, std::string> parsed;
std::string pair, key, value;
while (std::getline(stream, pair, '&')) // split each term
{
std::istringstream term(pair);
if (std::getline(std::getline(term, key, '='), value))
{
parsed[key] = value;
}
}
return parsed;
}
std::string Util::joinQueryString(std::map<std::string, std::string> query)
{
std::stringstream stream;
stream << "?";
for (auto const& pair : query)
{
stream << pair.first << "=" << pair.second << "&";
}
std::string result = stream.str();
result.pop_back(); // remove ending ampersand
return result;
} }

View File

@ -14,4 +14,6 @@ public:
static bool isASCII(const std::string& s); static bool isASCII(const std::string& s);
static std::string toLower(std::string s); static std::string toLower(std::string s);
static std::vector<BYTE> base64Decode(const std::string_view data); static std::vector<BYTE> base64Decode(const std::string_view data);
static std::map<std::string, std::string> parseQueryString(std::string query);
static std::string joinQueryString(std::map<std::string, std::string> query);
}; };