feat: implement Warden API stub dispatch via Unicorn UC_HOOK_CODE

Previously hookAPI() allocated a stub address and registered a C++ handler
but never stored the handler or wrote any executable code to the stub
region, meaning any Warden module call to a Windows API would execute zeros
and crash or silently return garbage.

Changes:
- Store ApiHookEntry {argCount, handler} per stub address in apiHandlers_
- Write RET (0xC3) to stub memory as a safe fallback
- Register UC_HOOK_CODE over the API stub address range during initialize()
- hookCode() now detects stub addresses, reads args from the emulated stack,
  dispatches to the C++ handler, then simulates stdcall epilogue by setting
  EAX/ESP/EIP so Unicorn returns cleanly to the caller
- Convert static-local nextStubAddr to instance member nextApiStubAddr_
  so re-initialization resets the allocator correctly
- Known arg counts for all 7 registered Windows APIs (VirtualAlloc,
  VirtualFree, GetTickCount, Sleep, GetCurrentThreadId,
  GetCurrentProcessId, ReadProcessMemory)
This commit is contained in:
Kelsi 2026-03-17 21:22:41 -07:00
parent b29d76bbc8
commit 005b1fcb54
2 changed files with 92 additions and 16 deletions

View file

@ -147,9 +147,18 @@ private:
uint32_t heapSize_; // Heap size
uint32_t apiStubBase_; // API stub base address
// API hooks: DLL name -> Function name -> Handler
// API hooks: DLL name -> Function name -> stub address
std::map<std::string, std::map<std::string, uint32_t>> apiAddresses_;
// API stub dispatch: stub address -> {argCount, handler}
struct ApiHookEntry {
int argCount;
std::function<uint32_t(WardenEmulator&, const std::vector<uint32_t>&)> handler;
};
std::map<uint32_t, ApiHookEntry> apiHandlers_;
uint32_t nextApiStubAddr_; // tracks next free stub slot (replaces static local)
bool apiCodeHookRegistered_; // true once UC_HOOK_CODE for stub range is added
// Memory allocation tracking
std::map<uint32_t, size_t> allocations_;
std::map<uint32_t, size_t> freeBlocks_; // free-list keyed by base address