feat: implement Warden module callbacks (sendPacket, validateModule, generateRC4)

Implement the three stubbed Warden module callbacks that were previously
TODO placeholders:

- **sendPacket**: Encrypts module output via WardenCrypto RC4 and sends
  as CMSG_WARDEN_DATA through the game socket. Enables modules to send
  responses back to the server (required for strict servers like Warmane).

- **validateModule**: Compares the module's provided 16-byte MD5 hash
  against the hash received during download. Logs error on mismatch
  (indicates corrupted module transit).

- **generateRC4**: Derives new encrypt/decrypt RC4 keys from a 16-byte
  seed using SHA1Randx, then replaces the active WardenCrypto key state.
  Handles mid-session re-keying requested by the module.

Architecture:
- Add setCallbackDependencies() to inject WardenCrypto* and socket send
  function into WardenModule before load() is called
- Use thread_local WardenModule* so C function pointer callbacks (which
  can't capture state) can reach the module's dependencies during init
- Wire dependencies from WardenHandler before module load

Also update warden_module.hpp status markers — RSA verification, zlib,
executable parsing, relocation, and Unicorn emulation are all implemented
(were incorrectly marked as TODO). Only API binding/IAT patching and
RSA modulus verification against real WoW.exe remain as gaps.
This commit is contained in:
Kelsi 2026-03-30 20:29:26 -07:00
parent 7cfaf2c7e9
commit 248d131af7
3 changed files with 88 additions and 24 deletions

View file

@ -13,6 +13,7 @@ namespace game {
// Forward declarations
class WardenEmulator;
class WardenCrypto;
/**
* Represents Warden callback functions exported by loaded module
@ -36,18 +37,19 @@ struct WardenFuncList {
* Warden module loader and executor
*
* IMPLEMENTATION STATUS:
* Module metadata parsing
* Basic validation framework
* RC4 decryption (uses existing WardenCrypto)
* RSA signature verification (TODO - requires OpenSSL RSA)
* zlib decompression (TODO - requires zlib library)
* Custom executable format parsing (TODO - major reverse engineering)
* Address relocation (TODO - x86 address fixups)
* API binding (TODO - kernel32/user32 function resolution)
* Native code execution (TODO - execute loaded x86 code)
* Module metadata parsing and validation
* RC4 decryption (WardenCrypto)
* RSA-2048 signature verification (OpenSSL EVP placeholder modulus)
* zlib decompression
* Custom executable format parsing (3 pair-format variants)
* Address relocation (delta-encoded fixups)
* x86 emulation via Unicorn Engine (cross-platform)
* Client callbacks (sendPacket, validateModule, generateRC4)
* API binding / IAT patching (stub module imports not yet resolved)
* RSA modulus needs verification against real WoW.exe build
*
* For strict servers like Warmane, ALL TODOs must be implemented.
* For permissive servers, fake responses in GameHandler work.
* For strict servers, the API binding stub may cause module init to fail.
* For permissive servers, fake responses in WardenHandler work.
*/
class WardenModule {
public:
@ -126,6 +128,12 @@ public:
size_t getModuleSize() const { return moduleSize_; }
const std::vector<uint8_t>& getDecompressedData() const { return decompressedData_; }
// Inject dependencies for module callbacks (sendPacket, generateRC4).
// Must be called before initializeModule() so callbacks can reach the
// network layer and crypto state.
using SendPacketFunc = std::function<void(const uint8_t*, size_t)>;
void setCallbackDependencies(WardenCrypto* crypto, SendPacketFunc sendFunc);
private:
bool loaded_; // Module successfully loaded
std::vector<uint8_t> md5Hash_; // Module identifier
@ -142,6 +150,11 @@ private:
std::unique_ptr<WardenEmulator> emulator_; // Cross-platform x86 emulator
uint32_t emulatedPacketHandlerAddr_ = 0; // Raw emulated VA for 4-arg PacketHandler call
// Dependencies injected via setCallbackDependencies() for module callbacks.
// These are NOT owned — the handler owns the crypto and socket lifetime.
WardenCrypto* callbackCrypto_ = nullptr;
SendPacketFunc callbackSendPacket_;
// Validation and loading steps
bool verifyMD5(const std::vector<uint8_t>& data,
const std::vector<uint8_t>& expectedHash);