diff --git a/src/auth/srp.cpp b/src/auth/srp.cpp index 154c4f55..99498164 100644 --- a/src/auth/srp.cpp +++ b/src/auth/srp.cpp @@ -129,11 +129,15 @@ std::vector SRP::computeAuthHash(const std::string& username, void SRP::computeClientEphemeral() { LOG_DEBUG("Computing client ephemeral"); - // Generate random private ephemeral a (19 bytes = 152 bits) - // Keep trying until we get a valid A + // Generate random private ephemeral a (19 bytes = 152 bits). + // WoW SRP-6a requires A != 0 mod N; in practice this almost never fails + // (probability ≈ 2^-152), but we retry to be safe. 100 attempts is far more + // than needed — if it fails, the RNG is broken. + static constexpr int kMaxEphemeralAttempts = 100; + static constexpr int kEphemeralBytes = 19; // 152 bits — matches Blizzard client int attempts = 0; - while (attempts < 100) { - a = BigNum::fromRandom(19); + while (attempts < kMaxEphemeralAttempts) { + a = BigNum::fromRandom(kEphemeralBytes); // A = g^a mod N A = g.modPow(a, N); @@ -146,8 +150,8 @@ void SRP::computeClientEphemeral() { attempts++; } - if (attempts >= 100) { - LOG_ERROR("Failed to generate valid client ephemeral after 100 attempts!"); + if (attempts >= kMaxEphemeralAttempts) { + LOG_ERROR("Failed to generate valid client ephemeral after ", kMaxEphemeralAttempts, " attempts!"); } } diff --git a/src/game/warden_module.cpp b/src/game/warden_module.cpp index bf44c26e..e49007e2 100644 --- a/src/game/warden_module.cpp +++ b/src/game/warden_module.cpp @@ -37,7 +37,9 @@ WardenModule::WardenModule() : loaded_(false) , moduleMemory_(nullptr) , moduleSize_(0) - , moduleBase_(0x400000) // Default module base address + // 0x400000 is the default PE image base for 32-bit Windows executables. + // Warden modules are loaded as if they were PE DLLs at this base address. + , moduleBase_(0x400000) { } @@ -77,10 +79,13 @@ bool WardenModule::load(const std::vector& moduleData, // Expected with placeholder modulus — verification is skipped gracefully } - // Step 4: Strip RSA signature (last 256 bytes) then zlib decompress + // Step 4: Strip RSA-2048 signature (last 256 bytes = 2048 bits) then zlib decompress. + // Blizzard signs each Warden module to prevent tampering; we strip it since we + // use a placeholder RSA modulus and can't verify the signature. + static constexpr size_t kRsaSignatureSize = 256; std::vector dataWithoutSig; - if (decryptedData_.size() > 256) { - dataWithoutSig.assign(decryptedData_.begin(), decryptedData_.end() - 256); + if (decryptedData_.size() > kRsaSignatureSize) { + dataWithoutSig.assign(decryptedData_.begin(), decryptedData_.end() - kRsaSignatureSize); } else { dataWithoutSig = decryptedData_; }