mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 09:33:51 +00:00
Implement Warden module execution foundation (Phase 1 & 2)
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
This commit is contained in:
parent
615efd01b7
commit
4b425f1225
6 changed files with 1141 additions and 0 deletions
|
|
@ -22,6 +22,7 @@
|
|||
namespace wowee::game {
|
||||
class TransportManager;
|
||||
class WardenCrypto;
|
||||
class WardenModuleManager;
|
||||
}
|
||||
|
||||
namespace wowee {
|
||||
|
|
@ -1188,6 +1189,7 @@ private:
|
|||
uint32_t wardenPacketsAfterGate_ = 0;
|
||||
bool wardenCharEnumBlockedLogged_ = false;
|
||||
std::unique_ptr<WardenCrypto> wardenCrypto_;
|
||||
std::unique_ptr<WardenModuleManager> wardenModuleManager_;
|
||||
|
||||
// ---- XP tracking ----
|
||||
uint32_t playerXp_ = 0;
|
||||
|
|
|
|||
215
include/game/warden_module.hpp
Normal file
215
include/game/warden_module.hpp
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
#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
|
||||
Loading…
Add table
Add a link
Reference in a new issue