Merge pull request #6 from kiseki-lol/feature/http-redirects
HTTP redirects
This commit is contained in:
commit
73e6fe9c75
|
|
@ -37,12 +37,13 @@ add_library(Kiseki.Patcher SHARED ${SOURCE} ${HEADER})
|
|||
|
||||
# Packages
|
||||
find_package(CURL CONFIG REQUIRED)
|
||||
find_package(RapidJSON CONFIG REQUIRED)
|
||||
|
||||
find_path(DETOURS_INCLUDE_DIRS "detours/detours.h")
|
||||
find_library(DETOURS_LIBRARY detours REQUIRED)
|
||||
|
||||
target_include_directories(Kiseki.Patcher PRIVATE Header ${DETOURS_INCLUDE_DIRS})
|
||||
target_link_libraries(Kiseki.Patcher PRIVATE CURL::libcurl ${DETOURS_LIBRARY})
|
||||
target_link_libraries(Kiseki.Patcher PRIVATE CURL::libcurl ${DETOURS_LIBRARY} rapidjson)
|
||||
|
||||
# Target-specific linking and compile options
|
||||
if(COMPILE_PLAYER)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#define ALLOWED_WILDCARD_DOMAINS "kiseki.lol", "rbxcdn.com", "roblox.com"
|
||||
#define ALLOWED_DOMAINS
|
||||
#define ALLOWED_WILDCARD_DOMAINS "kiseki.loc", "kiseki.lol", "rbxcdn.com", "roblox.com"
|
||||
#define ALLOWED_DOMAINS "sets.pizzaboxer.xyz"
|
||||
#define ALLOWED_SCHEMES "http", "https"
|
||||
#define ALLOWED_EMBEDDED_SCHEMES "javascript", "jscript", "res"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#undef ALLOWED_WILDCARD_DOMAINS
|
||||
#define ALLOWED_WILDCARD_DOMAINS "kiseki.loc", "kiseki.lol", "rbxcdn.com", "roblox.com"
|
||||
#endif
|
||||
|
||||
#define PUBLIC_KEY 0x06, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xA5, 0x11, 0xD0, 0x9F, 0xAB, 0x9B, 0x3A, 0x96, 0xC5, 0xBE, 0x50, 0xBB, 0xCA, 0x0C, 0xBB, 0xC8, 0x1A, 0x9C, 0xC1, 0x2F, 0x22, 0x7A, 0x80, 0x2C, 0x31, 0x01, 0xE1, 0x21, 0xC2, 0x7F, 0xE0, 0x10, 0xA1, 0x2D, 0x09, 0xED, 0x10, 0x3E, 0x28, 0xB9, 0xBD, 0x0F, 0x38, 0xDB, 0x52, 0x78, 0xC0, 0xEC, 0x04, 0xD4, 0x00, 0xAD, 0x45, 0xD3, 0xC7, 0x78, 0xF2, 0x83, 0xB5, 0x5B, 0x16, 0x0C, 0x32, 0x5D, 0xB3, 0x3B, 0xDA, 0xA2, 0x9C, 0x73, 0xB2, 0x0C, 0x09, 0x93, 0xD8, 0xF8, 0xD9, 0xC5, 0x75, 0xAB, 0x33, 0x19, 0xD3, 0x6A, 0xAF, 0x20, 0x21, 0x6C, 0x78, 0x31, 0x41, 0xD1, 0xCD, 0x6D, 0x4D, 0xA1, 0x6D, 0x49, 0x3A, 0x6A, 0x33, 0x10, 0x6D, 0x52, 0x33, 0x4A, 0x10, 0x32, 0x3D, 0x42, 0xE6, 0xEC, 0x38, 0x97, 0x2F, 0x05, 0x41, 0xDD, 0xD6, 0xB6, 0xAC, 0x17, 0x4B, 0x7E, 0xFA, 0xFE, 0xA4, 0xD2
|
||||
|
||||
#define ADDRESS_HTTP__HTTPGETPOSTWININET 0x006F03B0
|
||||
#define ADDRESS_HTTP__TRUSTCHECK 0x005B7050
|
||||
#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x00809EC0
|
||||
#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0
|
||||
#define ADDRESS_SERVERREPLICATOR__SENDTOP 0x00513E80
|
||||
#define ADDRESS_SERVERREPLICATOR__PROCESSTICKET 0x00514B60
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,24 @@
|
|||
#include <string>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
#include "Globals.hpp"
|
||||
#include "Helpers.hpp"
|
||||
|
||||
// TODO: This breaks on Release
|
||||
struct Http
|
||||
{
|
||||
std::string alternateUrl;
|
||||
void* padding;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
typedef void (__thiscall* Http__httpGetPostWinInet_t)(Http* _this, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6);
|
||||
typedef bool(__thiscall* Http__trustCheck_t)(const char* url);
|
||||
|
||||
void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6);
|
||||
bool __fastcall Http__trustCheck_hook(const char* url);
|
||||
|
||||
extern Http__httpGetPostWinInet_t Http__httpGetPostWinInet;
|
||||
extern Http__trustCheck_t Http__trustCheck;
|
||||
|
|
@ -140,14 +140,8 @@ std::string Helpers::getISOTimestamp()
|
|||
|
||||
std::pair<bool, std::map<std::string, std::string>> Helpers::parseURL(const std::string url)
|
||||
{
|
||||
// This is an ugly hack to url-encode the query before CURL actually parses the URL.
|
||||
// We do this because CURL throws a fit if the query is not properly URL encoded; so URLs such as "/Error/Dmp.ashx?filename=C:/Users/..." won't parse correctly.
|
||||
char* encodedQuery = curl_escape(url.substr(url.find("?") + 1).c_str(), url.substr(url.find("?") + 1).length());
|
||||
std::string encodedUrl = url.substr(0, url.find("?")) + encodedQuery;
|
||||
curl_free(encodedQuery);
|
||||
|
||||
CURLU* curl = curl_url();
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, encodedUrl.c_str(), 0);
|
||||
CURLUcode result = curl_url_set(curl, CURLUPART_URL, url.c_str(), 0);
|
||||
|
||||
std::map<std::string, std::string> map;
|
||||
bool success = false;
|
||||
|
|
@ -195,7 +189,7 @@ std::pair<bool, std::string> Helpers::httpGet(const std::string url)
|
|||
return std::make_pair(false, "");
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,111 @@
|
|||
#include "Hooks/Http.hpp"
|
||||
|
||||
#define CHECK(condition, 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;
|
||||
|
||||
void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6)
|
||||
{
|
||||
std::pair<bool, std::map<std::string, std::string>> parsed = Helpers::parseURL(_this->url);
|
||||
Http _changed = *_this;
|
||||
|
||||
if (parsed.first)
|
||||
{
|
||||
std::map<std::string, std::string> url = parsed.second;
|
||||
|
||||
if (!url["path"].empty() && !url["host"].empty() && !url["query"].empty())
|
||||
{
|
||||
url["path"] = Helpers::toLower(url["path"]);
|
||||
|
||||
if (url["host"] == "roblox.com" || url["host"] == "www.roblox.com")
|
||||
{
|
||||
if (url["path"] == "/game/tools/insertasset.ashx")
|
||||
{
|
||||
_changed.url = "https://sets.pizzaboxer.xyz/" + url["path"] + "?" + url["query"];
|
||||
}
|
||||
else if (url["path"] == "/asset" || url["path"] == "/asset/" || url["path"] == "/asset/default.ashx")
|
||||
{
|
||||
_changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + url["query"];
|
||||
_this = &_changed;
|
||||
}
|
||||
else if (url["path"] == "/thumbs/asset.ashx" || url["path"] == "/thumbs/avatar.ashx")
|
||||
{
|
||||
std::string api = "https://thumbnails.roblox.com";
|
||||
|
||||
api += url["path"] == "/thumbs/asset.ashx" ? "/v1/assets" : "/v1/users/avatar";
|
||||
|
||||
std::map<std::string, std::string> source = Helpers::parseQueryString(url["query"]);
|
||||
std::map<std::string, std::string> fixed = {};
|
||||
|
||||
for (auto& pair : source)
|
||||
{
|
||||
fixed[Helpers::toLower(pair.first)] = pair.second;
|
||||
}
|
||||
|
||||
if (fixed.find("id") != fixed.end())
|
||||
{
|
||||
auto handler = fixed.extract("id");
|
||||
handler.key() = url["path"] == "/thumbs/asset.ashx" ? "assetIds" : "userIds";
|
||||
|
||||
fixed.insert(std::move(handler));
|
||||
}
|
||||
|
||||
if (fixed.find("x") != fixed.end() && fixed.find("y") != fixed.end())
|
||||
{
|
||||
fixed["size"] = fixed["x"] + "x" + fixed["y"];
|
||||
|
||||
fixed.erase("x");
|
||||
fixed.erase("y");
|
||||
}
|
||||
|
||||
if (fixed.find("format") == fixed.end())
|
||||
{
|
||||
fixed["format"] = "Png";
|
||||
}
|
||||
|
||||
api += Helpers::joinQueryString(fixed);
|
||||
|
||||
// Get the API response
|
||||
std::pair<bool, std::string> response = Helpers::httpGet(api);
|
||||
if (!response.first)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0");
|
||||
}
|
||||
|
||||
std::string data = response.second;
|
||||
|
||||
rapidjson::Document document;
|
||||
document.Parse(data.c_str());
|
||||
|
||||
int error = 0;
|
||||
|
||||
CHECK(document.HasParseError(), 1);
|
||||
CHECK(!document.HasMember("data"), 2);
|
||||
CHECK(document["data"].Size() == 0, 3);
|
||||
CHECK(!document["data"][0].HasMember("imageUrl"), 4);
|
||||
CHECK(!document["data"][0]["imageUrl"].IsString(), 5);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error occurred when fetching Roblox API: " + std::to_string(error));
|
||||
}
|
||||
|
||||
_changed.url = document["data"][0]["imageUrl"].GetString();
|
||||
_this = &_changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6);
|
||||
}
|
||||
|
||||
bool __fastcall Http__trustCheck_hook(const char* url)
|
||||
{
|
||||
if (strlen(url) == 7 && !Helpers::isASCII(url))
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
START_PATCH_LIST()
|
||||
|
||||
ADD_PATCH(Http__httpGetPostWinInet, Http__httpGetPostWinInet_hook)
|
||||
ADD_PATCH(Http__trustCheck, Http__trustCheck_hook)
|
||||
|
||||
ADD_PATCH(Crypt__verifySignatureBase64, Crypt__verifySignatureBase64_hook)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": [
|
||||
"curl",
|
||||
"detours"
|
||||
"detours",
|
||||
"rapidjson"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue