#pragma once #include #include #include #include #include #include #include namespace wowee { namespace game { // Forward declarations class WardenEmulator; /** * Represents Warden callback functions exported by loaded module * * Real modules expose these 4 functions after loading. * For now, these are stubs for future native code execution. */ struct WardenFuncList { using GenerateRC4KeysFunc = std::function; using UnloadFunc = std::function; using PacketHandlerFunc = std::function; using TickFunc = std::function; GenerateRC4KeysFunc generateRC4Keys; // Triggered by 0x05 packets (re-keying) UnloadFunc unload; // Cleanup, save RC4 state PacketHandlerFunc packetHandler; // Process check requests (0x02, 0x04, etc.) TickFunc tick; // Periodic execution }; /** * 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) * * For strict servers like Warmane, ALL TODOs must be implemented. * For permissive servers, fake responses in GameHandler work. */ class WardenModule { public: WardenModule(); ~WardenModule(); /** * Load module from encrypted module data * * Steps: * 1. Verify MD5 hash against expected identifier * 2. RC4 decrypt using session key * 3. Verify RSA signature * 4. zlib decompress * 5. Parse custom executable format * 6. Apply relocations * 7. Bind API functions * 8. Initialize module and get WardenFuncList * * @param moduleData Encrypted module bytes from SMSG_WARDEN_DATA * @param md5Hash Expected MD5 hash (module identifier) * @param rc4Key RC4 decryption key from seed * @return true if module loaded successfully */ bool load(const std::vector& moduleData, const std::vector& md5Hash, const std::vector& rc4Key); /** * Check if module is loaded and ready */ bool isLoaded() const { return loaded_; } /** * Get module MD5 identifier */ const std::vector& getMD5Hash() const { return md5Hash_; } /** * Process check request packet via module's PacketHandler * * This would call the loaded module's native code to: * - Parse check opcodes (0xF3, 0xB2, 0x98, etc.) * - Perform actual memory scans * - Compute file checksums * - Generate REAL response data * * For now, returns false (not implemented). * * @param checkData Decrypted check request payload * @param responseOut Response data to send back * @return true if processed successfully */ bool processCheckRequest(const std::vector& checkData, std::vector& responseOut); /** * Periodic tick for module state updates * * @param deltaMs Milliseconds since last tick * @return Next tick interval in ms (0 = no more ticks needed) */ uint32_t tick(uint32_t deltaMs); /** * Generate new RC4 keys (triggered by server opcode 0x05) */ void generateRC4Keys(uint8_t* packet); /** * Unload module and cleanup */ void unload(); private: bool loaded_; // Module successfully loaded std::vector md5Hash_; // Module identifier std::vector moduleData_; // Raw encrypted data std::vector decryptedData_; // RC4 decrypted data std::vector decompressedData_; // zlib decompressed data // Module execution context void* moduleMemory_; // Allocated executable memory region size_t moduleSize_; // Size of loaded code uint32_t moduleBase_; // Module base address (for emulator) WardenFuncList funcList_; // Callback functions std::unique_ptr emulator_; // Cross-platform x86 emulator // Validation and loading steps bool verifyMD5(const std::vector& data, const std::vector& expectedHash); bool decryptRC4(const std::vector& encrypted, const std::vector& key, std::vector& decryptedOut); bool verifyRSASignature(const std::vector& data); bool decompressZlib(const std::vector& compressed, std::vector& decompressedOut); bool parseExecutableFormat(const std::vector& exeData); bool applyRelocations(); bool bindAPIs(); bool initializeModule(); }; /** * Warden module manager * * Handles multiple module downloads and lifecycle. * Servers can send different modules per session. */ class WardenModuleManager { public: WardenModuleManager(); ~WardenModuleManager(); /** * Check if we have module cached locally * * @param md5Hash Module identifier * @return true if module is cached */ bool hasModule(const std::vector& md5Hash); /** * Get or create module instance * * @param md5Hash Module identifier * @return Module instance (may not be loaded yet) */ std::shared_ptr getModule(const std::vector& md5Hash); /** * Receive module data chunk from server * * Modules may be sent in multiple SMSG_WARDEN_DATA packets. * This accumulates chunks until complete. * * @param md5Hash Module identifier * @param chunkData Data chunk * @param isComplete true if this is the last chunk * @return true if chunk accepted */ bool receiveModuleChunk(const std::vector& md5Hash, const std::vector& chunkData, bool isComplete); /** * Save module to disk cache * * Cached modules skip re-download on reconnect. * Cache directory: ~/.local/share/wowee/warden_cache/ */ bool cacheModule(const std::vector& md5Hash, const std::vector& moduleData); /** * Load module from disk cache */ bool loadCachedModule(const std::vector& md5Hash, std::vector& moduleDataOut); private: std::map, std::shared_ptr> modules_; std::map, std::vector> downloadBuffer_; // Partial downloads std::string cacheDirectory_; std::string getCachePath(const std::vector& md5Hash); }; } // namespace game } // namespace wowee