Files
recnet-plugin/include/retspoof.h
T
2026-08-18 15:53:45 -04:00

39 lines
2.1 KiB
C

#ifndef RETSPOOF_H
#define RETSPOOF_H
#include "common.h"
//
// Return-address spoofing for il2cpp utility calls (il2cpp_string_new, il2cpp_object_new, Uri..ctor,
// get_Uri/set_Uri, ...). These are called from inside our hooks (http_rewrite.c, photon_patch.c), which
// means the CPU pushes a return address inside redirector.dll before jumping to them -- so for the
// duration of that call, any stack walk over the calling thread sees an unrecognized module
// (redirector.dll) on the stack. This is exactly the kind of signal an anti-tamper stack-walk check
// looks for (see the ~30s freeze/crash: GameAssembly.dll rewrites hooked methods into stack-exhaustion
// poison once it detects us -- memory note unstable-build-identity-rvas.md).
//
// SpoofCall4 calls a function with the return address the CPU sees replaced by a "jmp qword ptr [rbx]"
// gadget scanned out of the target's own module, so the call looks -- from the stack's perspective --
// like it originated from inside that module instead of from us. See retspoof.asm for the mechanics.
//
// Scans [mod's image] for a usable gadget and caches it. Safe to call once GameAssembly's code has
// decrypted (this build's packer XOR-decrypts .text shortly after mapping -- see CLAUDE.md). Logs the
// found address, or logs a failure and leaves spoofing unavailable (SpoofCall4 falls back to a direct
// call in that case). Returns 1 on success, 0 otherwise.
int InitRetSpoof(HMODULE mod);
// True once InitRetSpoof has found a usable gadget.
int RetSpoofReady(void);
// Waits for GameAssembly.dll to appear and its code to decrypt, then resolves the gadget. Intended to
// run on its own thread (mirrors the WaitForCode pattern in ssl_patch.c / http_rewrite.c), started
// early so the gadget is ready well before real traffic starts flowing through the hooks that use it.
DWORD WINAPI PatchRetSpoof(LPVOID param);
// Calls target(a1, a2, a3, a4) with a spoofed return address (see above). Pad unused trailing
// arguments with 0. Falls back to a direct call if no gadget has been resolved yet.
uint64_t SpoofCall4(void *target, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4);
#endif