mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Added architecture for loading and executing native x86 Warden modules: New classes: - WardenModule: Individual module loader with 8-step pipeline ✅ MD5 verification (working) ✅ RC4 decryption (working) ⏳ RSA/zlib/exe-parsing/relocation/API-binding/execution (TODOs) - WardenModuleManager: Module lifecycle and disk caching ~/.local/share/wowee/warden_cache/<MD5>.wdn - WardenFuncList: Callback structure for module execution Integration: - Added wardenModuleManager_ to GameHandler - Module manager initialized on startup - Foundation ready for phases 3-7 (validation → execution) Documentation: - WARDEN_MODULE_ARCHITECTURE.md (comprehensive 7-phase roadmap) - Estimated 2-3 months for full native code execution - Alternative: packet capture approach (1-2 weeks) Status: Crypto layer complete, execution layer TODO
215 lines
7 KiB
C++
215 lines
7 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <memory>
|
|
#include <functional>
|
|
#include <unordered_map>
|
|
#include <map>
|
|
|
|
namespace wowee {
|
|
namespace game {
|
|
|
|
/**
|
|
* 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<void(uint8_t* packet)>;
|
|
using UnloadFunc = std::function<void(uint8_t* rc4Keys)>;
|
|
using PacketHandlerFunc = std::function<void(uint8_t* data, size_t length)>;
|
|
using TickFunc = std::function<uint32_t(uint32_t deltaMs)>;
|
|
|
|
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<uint8_t>& moduleData,
|
|
const std::vector<uint8_t>& md5Hash,
|
|
const std::vector<uint8_t>& rc4Key);
|
|
|
|
/**
|
|
* Check if module is loaded and ready
|
|
*/
|
|
bool isLoaded() const { return loaded_; }
|
|
|
|
/**
|
|
* Get module MD5 identifier
|
|
*/
|
|
const std::vector<uint8_t>& 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<uint8_t>& checkData,
|
|
std::vector<uint8_t>& 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<uint8_t> md5Hash_; // Module identifier
|
|
std::vector<uint8_t> moduleData_; // Raw encrypted data
|
|
std::vector<uint8_t> decryptedData_; // RC4 decrypted data
|
|
std::vector<uint8_t> decompressedData_; // zlib decompressed data
|
|
|
|
// Module execution context (for future native code execution)
|
|
void* moduleMemory_; // Allocated executable memory region
|
|
size_t moduleSize_; // Size of loaded code
|
|
WardenFuncList funcList_; // Callback functions
|
|
|
|
// Validation and loading steps
|
|
bool verifyMD5(const std::vector<uint8_t>& data,
|
|
const std::vector<uint8_t>& expectedHash);
|
|
bool decryptRC4(const std::vector<uint8_t>& encrypted,
|
|
const std::vector<uint8_t>& key,
|
|
std::vector<uint8_t>& decryptedOut);
|
|
bool verifyRSASignature(const std::vector<uint8_t>& data);
|
|
bool decompressZlib(const std::vector<uint8_t>& compressed,
|
|
std::vector<uint8_t>& decompressedOut);
|
|
bool parseExecutableFormat(const std::vector<uint8_t>& 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<uint8_t>& md5Hash);
|
|
|
|
/**
|
|
* Get or create module instance
|
|
*
|
|
* @param md5Hash Module identifier
|
|
* @return Module instance (may not be loaded yet)
|
|
*/
|
|
std::shared_ptr<WardenModule> getModule(const std::vector<uint8_t>& 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<uint8_t>& md5Hash,
|
|
const std::vector<uint8_t>& 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<uint8_t>& md5Hash,
|
|
const std::vector<uint8_t>& moduleData);
|
|
|
|
/**
|
|
* Load module from disk cache
|
|
*/
|
|
bool loadCachedModule(const std::vector<uint8_t>& md5Hash,
|
|
std::vector<uint8_t>& moduleDataOut);
|
|
|
|
private:
|
|
std::map<std::vector<uint8_t>, std::shared_ptr<WardenModule>> modules_;
|
|
std::map<std::vector<uint8_t>, std::vector<uint8_t>> downloadBuffer_; // Partial downloads
|
|
std::string cacheDirectory_;
|
|
|
|
std::string getCachePath(const std::vector<uint8_t>& md5Hash);
|
|
};
|
|
|
|
} // namespace game
|
|
} // namespace wowee
|