diff --git a/Tadah.DLL/Helpers.cpp b/Tadah.DLL/Helpers.cpp new file mode 100644 index 0000000..59ef0e7 --- /dev/null +++ b/Tadah.DLL/Helpers.cpp @@ -0,0 +1,107 @@ +#include "pch.h" + +#include "Helpers.h" + +#ifdef _DEBUG +const std::vector Helpers::publicKey = Helpers::base64Decode(PUBLIC_KEY); +#else +const std::vector Helpers::publicKey { PUBLIC_KEY }; +#endif + +const std::vector Helpers::allowedWildcardDomains { ALLOWED_WILDCARD_DOMAINS }; +const std::vector Helpers::allowedDomains { ALLOWED_DOMAINS }; +const std::vector Helpers::allowedSchemes { ALLOWED_SCHEMES }; +const std::vector Helpers::allowedEmbeddedSchemes { ALLOWED_EMBEDDED_SCHEMES }; + +// https://stackoverflow.com/questions/48212992/how-to-find-out-if-there-is-any-non-ascii-character-in-a-string-with-a-file-path +bool Helpers::isASCII(const std::string& s) +{ + return !std::any_of(s.begin(), s.end(), [](char c) { + return static_cast(c) > 127; + }); +} + +// https://stackoverflow.com/questions/313970/how-to-convert-an-instance-of-stdstring-to-lower-case +std::string Helpers::toLower(std::string s) +{ + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); + return s; +} + +// https://stackoverflow.com/a/44562527 +std::vector Helpers::base64Decode(const std::string_view data) +{ + // table from '+' to 'z' + const uint8_t lookup[] = { + 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, + 255, 0, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + static_assert(sizeof(lookup) == 'z' - '+' + 1); + + std::vector out; + int val = 0, valb = -8; + for (uint8_t c : data) + { + if (c < '+' || c > 'z') + { + break; + } + + c -= '+'; + if (lookup[c] >= 64) + { + break; + } + + val = (val << 6) + lookup[c]; + valb += 6; + + if (valb >= 0) + { + out.push_back(char((val >> valb) & 0xFF)); + valb -= 8; + } + } + + return out; +} + +// https://stackoverflow.com/a/28269049 +std::map Helpers::parseQueryString(std::string query) +{ + std::istringstream stream(query); + std::map 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 Helpers::joinQueryString(std::map 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; +} \ No newline at end of file diff --git a/Tadah.DLL/Hooks/Context.cpp b/Tadah.DLL/Hooks/Context.cpp index 226f761..f9ff29b 100644 --- a/Tadah.DLL/Hooks/Context.cpp +++ b/Tadah.DLL/Hooks/Context.cpp @@ -1,6 +1,6 @@ #include "pch.h" -#include "Util.h" +#include "Helpers.h" #include "Hooks/Context.h" #ifdef _DEBUG diff --git a/Tadah.DLL/Hooks/Crypt.cpp b/Tadah.DLL/Hooks/Crypt.cpp index 555bd2a..b087e0c 100644 --- a/Tadah.DLL/Hooks/Crypt.cpp +++ b/Tadah.DLL/Hooks/Crypt.cpp @@ -1,7 +1,7 @@ #include "pch.h" #include "Patches.h" -#include "Util.h" +#include "Helpers.h" #include "Hooks/Crypt.h" Crypt::Crypt() @@ -23,16 +23,10 @@ Crypt::Crypt() try { -#ifdef _DEBUG - std::vector publicKey = Util::base64Decode(Util::publicKey); -#else - std::vector publicKey = Util::publicKey; -#endif + BYTE* blob = new BYTE[Helpers::publicKey.size()]; + std::copy(Helpers::publicKey.begin(), Helpers::publicKey.end(), blob); - BYTE* blob = new BYTE[publicKey.size()]; - std::copy(publicKey.begin(), publicKey.end(), blob); - - if (!CryptImportKey(context, blob, publicKey.size(), 0, 0, &key)) + if (!CryptImportKey(context, blob, Helpers::publicKey.size(), 0, 0, &key)) { throw std::runtime_error(""); } @@ -75,7 +69,7 @@ bool Crypt::verifySignatureBase64(std::string message, std::string signatureBase return false; } - std::vector signature = Util::base64Decode(signatureBase64); + std::vector signature = Helpers::base64Decode(signatureBase64); /* The native cryptography API uses little-endian byte order diff --git a/Tadah.DLL/Hooks/Http.cpp b/Tadah.DLL/Hooks/Http.cpp index 12e53ff..9482f13 100644 --- a/Tadah.DLL/Hooks/Http.cpp +++ b/Tadah.DLL/Hooks/Http.cpp @@ -1,6 +1,6 @@ #include "pch.h" -#include "Util.h" +#include "Helpers.h" #include "Hooks/Http.h" #define CHECK(condition, code) \ @@ -39,7 +39,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i if (path != NULL && host != NULL && query != NULL) { - std::string _path = Util::toLower(std::string(path)); + std::string _path = Helpers::toLower(std::string(path)); std::string _host = std::string(host); std::string _query = std::string(query); @@ -70,7 +70,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i std::string api = "https://www.roblox.com/" + std::string(_path == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix"; - std::map source = Util::parseQueryString(query); + std::map source = Helpers::parseQueryString(query); std::map fixed = { { _path == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" }, { "thumbnailFormatId", "0" } @@ -80,7 +80,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i // thus, we are able to do this :-) for (auto& pair : source) { - fixed[Util::toLower(pair.first)] = pair.second; + fixed[Helpers::toLower(pair.first)] = pair.second; } if (fixed.find("id") != fixed.end()) @@ -91,7 +91,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i fixed.insert(std::move(handler)); } - api += Util::joinQueryString(fixed); + api += Helpers::joinQueryString(fixed); // get the api response CURL* curl = curl_easy_init(); @@ -151,7 +151,7 @@ void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, i bool __fastcall Http__trustCheck_hook(const char* url) { - if (strlen(url) == 7 && !Util::isASCII(url)) + if (strlen(url) == 7 && !Helpers::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* @@ -171,7 +171,7 @@ bool __fastcall Http__trustCheck_hook(const char* url) return true; } - for (std::string allowedEmbeddedScheme : Util::allowedEmbeddedSchemes) + for (std::string allowedEmbeddedScheme : Helpers::allowedEmbeddedSchemes) { if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0) { @@ -194,9 +194,20 @@ bool __fastcall Http__trustCheck_hook(const char* url) 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()) + if (std::find(Helpers::allowedSchemes.begin(), Helpers::allowedSchemes.end(), std::string(scheme)) != Helpers::allowedSchemes.end()) { - return std::find(Util::allowedHosts.begin(), Util::allowedHosts.end(), std::string(host)) != Util::allowedHosts.end(); + std::string _host = std::string(host); + + // this is crude and inefficient but I don't care + for (std::string wildcard : Helpers::allowedWildcardDomains) + { + if (_host.size() >= wildcard.size() && 0 == wildcard.compare(_host.size() - wildcard.size(), wildcard.size(), wildcard)) + { + return true; + } + } + + return std::find(Helpers::allowedDomains.begin(), Helpers::allowedDomains.end(), _host) != Helpers::allowedDomains.end(); } return false; diff --git a/Tadah.DLL/Hooks/StandardOut.cpp b/Tadah.DLL/Hooks/StandardOut.cpp index 737095c..07668dc 100644 --- a/Tadah.DLL/Hooks/StandardOut.cpp +++ b/Tadah.DLL/Hooks/StandardOut.cpp @@ -13,6 +13,7 @@ void InitializeOutput() SetStdHandle(STD_OUTPUT_HANDLE, outputHandle); printf("Tadah.DLL v1.0.0\n"); + #ifdef _DEBUG SetConsoleTextAttribute(outputHandle, FOREGROUND_RED | FOREGROUND_GREEN); printf("Compiled as Debug\n\n"); diff --git a/Tadah.DLL/Include/Config.h b/Tadah.DLL/Include/Configuration.h similarity index 83% rename from Tadah.DLL/Include/Config.h rename to Tadah.DLL/Include/Configuration.h index 59a3904..6167038 100644 --- a/Tadah.DLL/Include/Config.h +++ b/Tadah.DLL/Include/Configuration.h @@ -1,5 +1,16 @@ #pragma once +#define ALLOWED_WILDCARD_DOMAINS "tadah.rocks", "rbxcdn.com", "roblox.com" +#define ALLOWED_DOMAINS +#define ALLOWED_SCHEMES "http", "https" +#define ALLOWED_EMBEDDED_SCHEMES "javascript", "jscript", "res" + +#ifdef _DEBUG +#define PUBLIC_KEY "" +#else +#define PUBLIC_KEY 0x0 +#endif + #define PLAYERBUILD // #define ARBITERBUILD diff --git a/Tadah.DLL/Include/Util.h b/Tadah.DLL/Include/Helpers.h similarity index 69% rename from Tadah.DLL/Include/Util.h rename to Tadah.DLL/Include/Helpers.h index c77b6a7..228f871 100644 --- a/Tadah.DLL/Include/Util.h +++ b/Tadah.DLL/Include/Helpers.h @@ -1,19 +1,15 @@ #pragma once -#include +#include "Configuration.h" -class Util +class Helpers { public: -#ifdef _DEBUG - static const std::string publicKey; -#else static const std::vector publicKey; -#endif - static const std::vector allowedHosts; + static const std::vector allowedWildcardDomains; + static const std::vector allowedDomains; static const std::vector allowedSchemes; static const std::vector allowedEmbeddedSchemes; - static std::map parseArgs(std::string args); static bool isASCII(const std::string& s); static std::string toLower(std::string s); static std::vector base64Decode(const std::string_view data); diff --git a/Tadah.DLL/Include/Hooks/CRoblox.h b/Tadah.DLL/Include/Hooks/CRoblox.h index c59b593..d361863 100644 --- a/Tadah.DLL/Include/Hooks/CRoblox.h +++ b/Tadah.DLL/Include/Hooks/CRoblox.h @@ -1,6 +1,6 @@ #pragma once -#include "Config.h" +#include "Configuration.h" class CWorkspace; diff --git a/Tadah.DLL/Include/Hooks/Context.h b/Tadah.DLL/Include/Hooks/Context.h index 336f31f..8e6e41b 100644 --- a/Tadah.DLL/Include/Hooks/Context.h +++ b/Tadah.DLL/Include/Hooks/Context.h @@ -1,6 +1,6 @@ #pragma once -#include "Config.h" +#include "Configuration.h" #ifdef _DEBUG diff --git a/Tadah.DLL/Include/Hooks/Crypt.h b/Tadah.DLL/Include/Hooks/Crypt.h index 87a7d65..34422bb 100644 --- a/Tadah.DLL/Include/Hooks/Crypt.h +++ b/Tadah.DLL/Include/Hooks/Crypt.h @@ -2,7 +2,7 @@ #include -#include "Config.h" +#include "Configuration.h" typedef void(__thiscall* Crypt__verifySignatureBase64_t)(HCRYPTPROV* _this, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); diff --git a/Tadah.DLL/Include/Hooks/Http.h b/Tadah.DLL/Include/Hooks/Http.h index 50ce2d0..fbe109b 100644 --- a/Tadah.DLL/Include/Hooks/Http.h +++ b/Tadah.DLL/Include/Hooks/Http.h @@ -3,7 +3,7 @@ #include #include -#include "Config.h" +#include "Configuration.h" struct Http { diff --git a/Tadah.DLL/Include/Hooks/ServerReplicator.h b/Tadah.DLL/Include/Hooks/ServerReplicator.h index 8eae103..ffc251a 100644 --- a/Tadah.DLL/Include/Hooks/ServerReplicator.h +++ b/Tadah.DLL/Include/Hooks/ServerReplicator.h @@ -1,6 +1,6 @@ #pragma once -#include "Config.h" +#include "Configuration.h" #if defined(ARBITERBUILD) diff --git a/Tadah.DLL/Include/Hooks/StandardOut.h b/Tadah.DLL/Include/Hooks/StandardOut.h index fb0d8cf..37ad63c 100644 --- a/Tadah.DLL/Include/Hooks/StandardOut.h +++ b/Tadah.DLL/Include/Hooks/StandardOut.h @@ -1,6 +1,6 @@ #pragma once -#include "Config.h" +#include "Configuration.h" void InitializeOutput(); diff --git a/Tadah.DLL/Tadah.DLL.vcxproj b/Tadah.DLL/Tadah.DLL.vcxproj index 87307dd..be54a62 100644 --- a/Tadah.DLL/Tadah.DLL.vcxproj +++ b/Tadah.DLL/Tadah.DLL.vcxproj @@ -123,7 +123,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/Tadah.DLL/Tadah.DLL.vcxproj.filters b/Tadah.DLL/Tadah.DLL.vcxproj.filters index 7fc3230..91357ba 100644 --- a/Tadah.DLL/Tadah.DLL.vcxproj.filters +++ b/Tadah.DLL/Tadah.DLL.vcxproj.filters @@ -27,10 +27,10 @@ Header Files - + Header Files - + Header Files @@ -65,7 +65,7 @@ Source Files - + Source Files diff --git a/Tadah.DLL/Util.cpp b/Tadah.DLL/Util.cpp deleted file mode 100644 index 8d81617..0000000 --- a/Tadah.DLL/Util.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "pch.h" - -#include "Util.h" - -// this is ifdef guarded so that the public key cannot easily be replaced -// the std::vector variant is the base64 blob decoded into its byte form (https://cryptii.com/pipes/base64-to-hex) -// for ease of development, the string is retained to easily swap keys -// currently the key is the Project Polygon key - -#ifdef _DEBUG - -const std::string Util::publicKey = - "BgIAAACkAABSU0ExAAQAAAEAAQABmKy9m0NxBRoXTuQPZU8BeM" - "fwBisHcYBy93KSlQB3emeiW/pEMj9YWn2k7JkHiqcjuH+XE5PW" - "K+q9s8oLQsnXTdTYa2l+1BhypP5jefgq0ZHITTIMBfE7rTI39p" - "pzs0ayXKINQMIsBzXaJm25v5gP+vlz4cupJPq+jy9De+kcyw=="; - -#else - -const std::vector Util::publicKey = { - 0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x98, 0xac, 0xbd, 0x9b, 0x43, 0x71, 0x05, 0x1a, 0x17, - 0x4e, 0xe4, 0x0f, 0x65, 0x4f, 0x01, 0x78, 0xc7, 0xf0, 0x06, 0x2b, 0x07, 0x71, 0x80, 0x72, - 0xf7, 0x72, 0x92, 0x95, 0x00, 0x77, 0x7a, 0x67, 0xa2, 0x5b, 0xfa, 0x44, 0x32, 0x3f, 0x58, - 0x5a, 0x7d, 0xa4, 0xec, 0x99, 0x07, 0x8a, 0xa7, 0x23, 0xb8, 0x7f, 0x97, 0x13, 0x93, 0xd6, - 0x2b, 0xea, 0xbd, 0xb3, 0xca, 0x0b, 0x42, 0xc9, 0xd7, 0x4d, 0xd4, 0xd8, 0x6b, 0x69, 0x7e, - 0xd4, 0x18, 0x72, 0xa4, 0xfe, 0x63, 0x79, 0xf8, 0x2a, 0xd1, 0x91, 0xc8, 0x4d, 0x32, 0x0c, - 0x05, 0xf1, 0x3b, 0xad, 0x32, 0x37, 0xf6, 0x9a, 0x73, 0xb3, 0x46, 0xb2, 0x5c, 0xa2, 0x0d, - 0x40, 0xc2, 0x2c, 0x07, 0x35, 0xda, 0x26, 0x6d, 0xb9, 0xbf, 0x98, 0x0f, 0xfa, 0xf9, 0x73, - 0xe1, 0xcb, 0xa9, 0x24, 0xfa, 0xbe, 0x8f, 0x2f, 0x43, 0x7b, 0xe9, 0x1c, 0xcb -}; - -#endif - -const std::vector Util::allowedHosts -{ - "polygon.pizzaboxer.xyz", - "polygondev.pizzaboxer.xyz", - "polygonapi.pizzaboxer.xyz", - "clientsettingsapi.pizzaboxer.xyz", - - "roblox.com", - "www.roblox.com", - "api.roblox.com", - "assetdelivery.roblox.com", - "assetgame.roblox.com", - - "rbxcdn.com", - "www.rbxcdn.com", - - "tr.rbxcdn.com", - "t0.rbxcdn.com", - "t1.rbxcdn.com", - "t2.rbxcdn.com", - "t3.rbxcdn.com", - "t4.rbxcdn.com", - "t5.rbxcdn.com", - "t6.rbxcdn.com", - "t7.rbxcdn.com", - "t8.rbxcdn.com", - "t9.rbxcdn.com", - - "tadah.rocks", - "www.tadah.rocks" -}; - -const std::vector Util::allowedSchemes -{ - "http", - "https", - "ftp" -}; - -const std::vector Util::allowedEmbeddedSchemes -{ - "javascript", - "jscript", - "res" -}; - -std::map Util::parseArgs(std::string args) -{ - std::map 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) -{ - return !std::any_of(s.begin(), s.end(), [](char c) { - return static_cast(c) > 127; - }); -} - -// https://stackoverflow.com/questions/313970/how-to-convert-an-instance-of-stdstring-to-lower-case -std::string Util::toLower(std::string s) -{ - std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); - return s; -} - -// https://stackoverflow.com/a/44562527 -std::vector Util::base64Decode(const std::string_view data) -{ - // table from '+' to 'z' - const uint8_t lookup[] = { - 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, - 255, 0, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - static_assert(sizeof(lookup) == 'z' - '+' + 1); - - std::vector out; - int val = 0, valb = -8; - for (uint8_t c : data) - { - if (c < '+' || c > 'z') - { - break; - } - - c -= '+'; - if (lookup[c] >= 64) - { - break; - } - - val = (val << 6) + lookup[c]; - valb += 6; - - if (valb >= 0) - { - out.push_back(char((val >> valb) & 0xFF)); - valb -= 8; - } - } - - return out; -} - -// https://stackoverflow.com/a/28269049 -std::map Util::parseQueryString(std::string query) -{ - std::istringstream stream(query); - std::map 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 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; -} \ No newline at end of file diff --git a/Tadah.DLL/dllmain.cpp b/Tadah.DLL/dllmain.cpp index 649854d..d23bef6 100644 --- a/Tadah.DLL/dllmain.cpp +++ b/Tadah.DLL/dllmain.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "Config.h" +#include "Configuration.h" #include "Patches.h" #include "Hooks/Http.h"