diff --git a/PolygonClientUtilities/Crypt.cpp b/PolygonClientUtilities/Crypt.cpp index d8ca61d..18c6913 100644 --- a/PolygonClientUtilities/Crypt.cpp +++ b/PolygonClientUtilities/Crypt.cpp @@ -1,43 +1,35 @@ +// CARROT WAS HERE + #include "pch.h" #include "Crypt.h" #include "Patches.h" #include "Util.h" -// Carrot: Notes; -// - The public key should be taken from the attached executable. Find "BgIAAACk" and get 200 characters -// - I didn't test this -// - All the std::runtime_errors here should use RBX::runtime_error but I didn't want to hook it. YOu do it pizza -// - Idk how iffy the base64 decoding is lol - -// Base/rbx/Crypt.cpp - Crypt::Crypt() { - static const char* keyB64 = "BgIAAACkAABSU0ExAAQAAAEAAQBBC9x87ewme1daAWZGJpK3rTepuMbivjpgTyNwu+f7gxpyreKUzQDSpqj+DhT7ni432DY0H4+Zv6MazZFrjeBnS6YnD02fuGkmLb0mg0yO784esDkImtDpqNrmoqPwAe94jr8K8vsxaOeF5b7OfA+lWUcag6Jh0Yb+mZxhFbmvrg=="; - char pbKeyBlob[256]; - int dwBlobLen = 256; - - // http://support.microsoft.com/kb/238187 - if (!CryptAcquireContext(&context, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { if (::GetLastError() == NTE_BAD_KEYSET) { - if (!CryptAcquireContext(&context, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) + if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) { - throw std::runtime_error("Error " + std::to_string(GetLastError()) + " during CryptAcquireContext 2\n"); + throw std::runtime_error("Error during CryptAcquireContext 2\n"); } } else { - throw std::runtime_error("Error " + std::to_string(GetLastError()) + " during CryptAcquireContext\n"); + throw std::runtime_error("Error during CryptAcquireContext\n"); } } - ATL::Base64Decode(keyB64, strlen(keyB64), (BYTE*)pbKeyBlob, &dwBlobLen); + std::vector publicKey = Util::base64Decode(Util::publicKey); + BYTE* blob = new BYTE[publicKey.size()]; - if (!CryptImportKey(context, (BYTE*)pbKeyBlob, dwBlobLen, 0, 0, &key)) + std::copy(publicKey.begin(), publicKey.end(), blob); + + if (!CryptImportKey(context, blob, publicKey.size(), 0, 0, &key)) { - throw std::runtime_error("Error " + std::to_string(GetLastError()) + " during CryptImportKey"); + throw std::runtime_error("Error during CryptImportKey"); } } @@ -69,15 +61,14 @@ void Crypt::verifySignatureBase64(std::string message, std::string signatureBase throw std::runtime_error(""); } - // Roblox does stupid stuff. We can just use C++17 features :-) - std::vector signature = Util::base64Decode(signatureBase64); /* The native cryptography API uses little-endian byte order - while the .NET Framework API uses big-endian byte order. - If you are verifying a signature generated by using a .NET Framework - API (or similar), you must swap the order of signature bytes before + while OpenSSL uses big-endian byte order. + + If you are verifying a signature generated by using a OpenSSL API + (or similar), you must swap the order of signature bytes before calling the CryptVerifySignature function to verify the signature. */ @@ -100,24 +91,21 @@ void Crypt::verifySignatureBase64(std::string message, std::string signatureBase ::CryptDestroyHash(hash); } -// End Base/rbx/Crypt.cpp - Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64; +// Crypt::verifySignatureBase64(std::string message, std::string signatureBase64) 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) { + /* + Ideally, we would be able to just use the function signature as-is. + However, it causes inexplicable crashes. Thus, we must reconstruct + the strings by hand given the manual parameters. + */ + std::string message; std::string signatureBase64; // Get message - /* - v18 = pbData; - if ((unsigned int)a8 < 0x10) - { - v18 = (const BYTE*)&pbData; - } - */ - const BYTE* v18 = pbData; if ((unsigned int)a8 < 0x10) { @@ -127,16 +115,6 @@ void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int message = std::string(reinterpret_cast(pbData), dwDataLen); // Get signatureBase64 - /* - v21 = (int *)a10; - if ((unsigned int)a15 < 0x10) - { - v21 = &a10; - } - - sub_79EA70(v21, a14, &v30, &dwSigLen); // ATL::Base64Decode - */ - int* v21 = (int*)a10; if ((unsigned int)a15 < 0x10) { @@ -145,5 +123,6 @@ void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int signatureBase64 = std::string(reinterpret_cast(v21), a14); + // Verify the signature Crypt().verifySignatureBase64(message, signatureBase64); } \ No newline at end of file diff --git a/PolygonClientUtilities/Util.cpp b/PolygonClientUtilities/Util.cpp index d2ebc9b..c0851c7 100644 --- a/PolygonClientUtilities/Util.cpp +++ b/PolygonClientUtilities/Util.cpp @@ -2,6 +2,11 @@ #include "Util.h" #include +const std::string Util::publicKey = "BgIAAACkAABSU0ExAAQAAAEAAQABmKy9m0NxBRoXTuQPZU8BeM" + "fwBisHcYBy93KSlQB3emeiW/pEMj9YWn2k7JkHiqcjuH+XE5PW" + "K+q9s8oLQsnXTdTYa2l+1BhypP5jefgq0ZHITTIMBfE7rTI39p" + "pzs0ayXKINQMIsBzXaJm25v5gP+vlz4cupJPq+jy9De+kcyw=="; + const std::vector Util::allowedHosts { "polygon.pizzaboxer.xyz", diff --git a/PolygonClientUtilities/Util.h b/PolygonClientUtilities/Util.h index bf1e323..b2aa6bf 100644 --- a/PolygonClientUtilities/Util.h +++ b/PolygonClientUtilities/Util.h @@ -5,6 +5,7 @@ class Util { public: + static const std::string publicKey; static const std::vector allowedHosts; static const std::vector allowedSchemes; static const std::vector allowedEmbeddedSchemes;