Files
cheathell/project/docs/input/files/ef_cheeto_feed_1_analysis.md
T
2026-03-08 16:25:35 -06:00

168 KiB
Raw Blame History

EF-CHEETO RECONSTRUCTION FEED — PART 1/3

Feed ALL THREE PARTS before asking reconstruction questions.

Part 1: Orientation + Full Analysis (prose, pseudocode, tables)

================================================================================ CONFIRMED IMGUI BUILD INFORMATION

ImGui Version

  • Repository: https://github.com/ocornut/imgui (docking branch)
  • Commit: fa4b47c5e2b53dba5093384562440bd9a6bba2a0 (December 5, 2025)
  • Version: Dear ImGui 1.92.6 WIP (19253)
  • Branch: DOCKING (confirmed — viewport/DockSpace strings present in binary)

Source Files Compiled Into Binary

  • imgui.cpp
  • imgui_draw.cpp
  • imgui_tables.cpp
  • imgui_widgets.cpp
  • imgui_demo.cpp — NOT compiled in (absent from binary)
  • backends/imgui_impl_win32.cpp
  • backends/imgui_impl_dx11.cpp

Build Configuration

  • NDEBUG defined (release build — zero IM_ASSERT strings in binary)
  • MSVC linker 14.44 = Visual Studio 2022 v17.14 (December 2025 toolchain)
  • PE compile timestamp: 2025-12-10 12:27:05 UTC
  • No custom imconfig.h overrides detected
  • Standard ImDrawIdx = uint16_t (16-bit, default, not overridden)
  • No imgui_freetype, no imgui_demo

ImGui Code Footprint in Binary

  • .text section: RVA 0x1000–0x7F000 (~457KB) is entirely ImGui library code
  • Cheat-specific code begins at approximately RVA 0x7F000
  • Win32 backend WndProc handler: RVA 0x57720 (ImGui_ImplWin32_WndProcHandler)
  • DX11 backend shader init: RVA 0x54DC0
  • DX11 backend resource creation: RVA 0x551F0
  • ImGuiContext accessed via [g_Config+0x15D8] in all cheat code
  • IniFilename "imgui.ini" set into ImGuiIO+0x20 at RVA 0x1117A

Project Source Tree (from MSVC FILE embeds)

  • E:\git\Endfield_Cheeto\framework\helpers.cpp
  • E:\git\Endfield_Cheeto\libraries\pipeline\HookManager.h
  • E:\git\Endfield_Cheeto\libraries\pipeline\gui\tabs\SettingsTAB.cpp
  • E:\git\Endfield_Cheeto\libraries\pipeline\hooks\UI.cpp
  • E:\git\Endfield_Cheeto\libraries\pipeline\modules\ModuleManager.cpp
  • E:\git\Endfield_Cheeto\user\main.cpp

To Reproduce Build

git clone https://github.com/ocornut/imgui git checkout fa4b47c5e2b53dba5093384562440bd9a6bba2a0

Compile with MSVC 14.44, /O2, NDEBUG, x64

Include: imgui.cpp, imgui_draw.cpp, imgui_tables.cpp, imgui_widgets.cpp

Include: backends/imgui_impl_win32.cpp, backends/imgui_impl_dx11.cpp

No custom imconfig.h needed

Part 2: Reconstruction Header (structs, addresses, constants)

Part 3: Machine Code (hex dumps + raw binary sections)

EF-Cheeto Reconstruction System Prompt

Give this + the feed document to an AI for perfect reconstruction.

You are a reverse-engineering assistant with complete knowledge of the EF-Cheeto game cheat DLL (EF-Cheeto.dll, 3,956,736 bytes). You have been given a complete analysis document covering all 29 chapters of binary analysis plus a full reconstruction header file. Use these to answer any reconstruction question.

Binary Identity

  • File: EF-Cheeto.dll
  • Size: 3,956,736 bytes (0x3CE000)
  • Base VA: 0x180000000
  • .data base: 0x1803C5000 (RVA 0x3C5000)
  • .rdata strings base: ~0x3A0000–0x3B4000
  • IAT base: RVA 0xB1000
  • Architecture: x86-64 Windows DLL (PE32+)
  • Compiler: MSVC (x64 Release, C++17)
  • Project path: E:\git\Endfield_Cheeto\

What You Know (Summary)

Module System (10 active modules + 1 ghost)

  1. ESPModule — entity ESP overlay (draw boxes/labels on enemies, NPCs, etc.)
  2. FPSModule — FPS counter overlay + FPS cap unlocker
  3. NoClip — CharacterController.enabled toggle + move speed
  4. FreeCam — CinemachineBrain camera override with WASD+mouse
  5. FpsUnlocker — Application.set_targetFrameRate bypass (default 300fps)
  6. SetDither — graphics dither toggle (stub, no per-frame effect)
  7. PlayerProfile — Unity UI TextMeshPro text injection (UID + name changer)
  8. Vacuum — Rigidbody.AddForce attraction loop
  9. SkillHack — 6× IL2CPP hooks: cooldown bypass, availability, cost bypass
  10. UnityExplorer — runtime Unity scene browser + GO/component inspector
  11. DamageHack — GHOST FEATURE: i18n keys exist, zero code

Key Subsystems

  • GABypass: resolves 71 IL2CPP function pointers from GameAssembly.dll at startup
  • HookManager: FNV-1a hash table + spinlock, hooks tracked in 0x38-byte entries
  • ModuleManager: dispatch loops for Render/Update/Hotkeys on all modules
  • D3D11 overlay: layered WS_EX_LAYERED window, ImGui Win32+D3D11 backend
  • Config: ImGui .ini persistence (no separate JSON config file)
  • i18n: nlohmann v3.12.0 JSON blob (en/zh_cn), stored at .rdata RVA 0x3B10E8
  • Injection: testyip/gatmp.tmp/EF-Cheeto.dll path scanner on loaded modules
  • Thread safety: Toolhelp32 snapshot suspension around all code patches

Critical Addresses (quick reference)

  • DllMain: RVA 0x01000
  • LoaderThread: RVA 0x05000
  • Startup_main: RVA 0x0A9190
  • GABypass::Patch: RVA 0x09D1E0
  • ModuleManager::Init: RVA 0x09AC10
  • HookMgr::CreateHook: RVA 0x0A9CC8
  • OverlayWindowInit: RVA 0x0827A0
  • WndProc: RVA 0x0826A0
  • ESPModule singleton: VA 0x1803C6F70
  • HookManager single: VA 0x1803C7470
  • IL2CPP table start: [.data+0x1C48]
  • g_Config base: [.data+0x1C00]

How to Use This Document

  • PART A contains all pseudocode, behavioral descriptions, and data tables
  • PART B contains the compilable reconstruction header with all addresses
  • For any function: find it in PART B's RVA namespace, then look up the chapter in PART A
  • For any struct: PART B has the layout; PART A has the behavioral context
  • For IL2CPP calls: Section 18 / PART B Section 10 has all 71 function pointers
  • For string RVAs: PART B Section 27 has all 189 .rdata strings

Answer reconstruction questions by citing specific RVAs, field offsets, and pseudocode from the document. When writing reconstructed C++, use the exact struct layouts and address constants from PART B.

================================================================================ ANALYSIS DOCUMENT — All 29 Chapters

EF-Cheeto.dll (unityexplorer.dll) Complete Reverse Engineering Report — Final Consolidated Edition 24 Chapters · 11 Registered Modules · Complete Static Reconstruction February 27, 2026

1. Executive Summary

This document is the complete consolidated reverse engineering analysis of EF-Cheeto.dll (distributed as unityexplorer.dll), spanning twenty-five chapters. It covers all subsystems from infrastructure (thread enumeration, anti-debug, shader compilation, config I/O) through the hook engine, eleven registered cheat modules, the ModuleManager dispatch architecture, GABypass IL2CPP resolver, JSON config schema, and analyses added in later passes: ESPModule Render/Update implementation (Ch. 22), DamageHack ghost feature analysis (Ch. 23), SetDither RenderOverlay body (Ch. 12.5.1), and the Sidebar/Main Panel rendering function (Ch. 25). IAT base is RVA 0xB1000 (file raw offset 0xAF600). The binary is 3,956,736 bytes (0x3CE000), compiled with MSVC for x86-64 Windows. The binary is fully reverse engineered with no significant undocumented regions remaining.

2. Corrected IAT Address Map

Previous analysis used incorrect IAT RVAs derived from objdump -p output. The correct IAT base is RVA 0xB1000 (file raw offset 0xAF600), not the 0x3C2xxx addresses previously listed. The following table gives the correct IAT RVAs and all call sites. Function IAT RVA DLL Call Sites (VA) SuspendThread 0xB1050 KERNEL32.dll 0x1800A9861 ResumeThread 0xB1058 KERNEL32.dll 0x1800A9964 (×37 total) GetThreadContext 0xB1068 KERNEL32.dll 0x1800A988B SetThreadContext 0xB1078 KERNEL32.dll 0x1800A993C CreateToolhelp32Snapshot 0xB1160 KERNEL32.dll 0x1800A970B Thread32First 0xB11B0 KERNEL32.dll 0x1800A972F Thread32Next 0xB11A8 KERNEL32.dll 0x1800A97DD OpenThread 0xB11D0 KERNEL32.dll 0x1800A9849 (×38 total) VirtualProtect 0xB1288 KERNEL32.dll 0x1800A9AFC, 0x1800A9B6C FlushInstructionCache 0xB1070 KERNEL32.dll 0x1800A9B81 GetCurrentProcess 0xB1270 KERNEL32.dll 0x1800A9B72 IsDebuggerPresent 0xB11E8 KERNEL32.dll 0x1800AC67B SetUnhandledExceptionFilter 0xB1200 KERNEL32.dll 0x1800AC698 UnhandledExceptionFilter 0xB1208 KERNEL32.dll 0x1800AC6A3 IsProcessorFeaturePresent 0xB11F0 KERNEL32.dll 0x1800AC5A2 TerminateProcess 0xB11F8 KERNEL32.dll 0x1800AC628 (via int 29h) D3DCompile 0xB1000 D3DCOMPILER_47 0x180054E77, 0x180055069 _wfopen 0xB1888 CRT 0x180011F93 fwrite 0xB1868 CRT 0x18000EA1B, 0x1800170D6, 0x18003033B, 0x18003076D fread 0xB1870 CRT (called via 0x180011EA0 helper) fclose 0xB1878 CRT 0x1800170DF, 0x180030776 SetWindowDisplayAffinity 0xB1460 USER32.dll 0x18008B48F LoadLibraryA 0xB10E0 KERNEL32.dll 0x180055F57, 0x1800585AE (×4) GetProcAddress 0xB1088 KERNEL32.dll 0x180055F7E, 0x180055F92 (×7) VirtualAlloc 0xB11A0 KERNEL32.dll 0x1800AA566, 0x1800AA607 VirtualFree 0xB1278 KERNEL32.dll 0x180081D5B, 0x1800AA6E1

3. Thread Enumeration and Suspension

Thread enumeration serves a critical role in safe hook installation: the cheat must suspend all Unity render/game threads before patching code bytes, then resume them after patching, to prevent race conditions. This subsystem uses two cooperating functions.

3.1 Thread Collection Function (0x1800A96B0–0x1800A9A1C)

This function collects all thread IDs for the current process using a Toolhelp32 snapshot, filtering out the calling thread and storing results in a caller-provided vector. The function signature is: int CollectProcessThreads( DWORD* out_vec, // RCX: vector { begin, end, capacity } DWORD current_pid, // RDX: passed to CreateToolhelp32Snapshot DWORD current_tid // R8d: thread to exclude (caller's thread) Key sequence: // 0x1800A96B0: Prologue, save RSI/RDI/RBX/R12-R15, allocate 0x530 bytes stack // 0x1800A96E7: xor ebx, ebx (thread count = 0) // 0x1800A96F8: mov [rcx], rbx; mov [rcx+8], rbx (init empty vector) // 0x1800A9701: lea ecx, [rbx+4] = TH32CS_SNAPTHREAD = 4 // 0x1800A970B: call [IAT:CreateToolhelp32Snapshot](dwFlags=4, pid=r15) // 0x1800A9711: mov r14, rax (hSnapshot = result) // 0x1800A9714: cmp rax, -1 → je fail (INVALID_HANDLE_VALUE) // 0x1800A971E: lea r12d, [rbx+0x1C] (sizeof THREADENTRY32 = 28) // 0x1800A9725: lea rdx, [rsp+0x30] (THREADENTRY32 buffer) // 0x1800A972A: mov [rsp+0x30], r12d (te32.dwSize = 28) // 0x1800A972F: call [IAT:Thread32First](hSnapshot, &te32) // --- LOOP --- // 0x1800A9740: cmp [rsp+0x30], 0x10 (check th32OwnerProcessID offset) // 0x1800A974B: call [IAT:GetCurrentProcessId] // 0x1800A9751: cmp [rsp+0x3C], eax (te32.th32OwnerProcessID == GetCurrentProcessId?) // 0x1800A9755: jne skip (skip threads not in our process) // 0x1800A9757: call [IAT:GetCurrentThreadId] // 0x1800A975D: cmp [rsp+0x38], eax (te32.th32ThreadID == calling thread?) // 0x1800A9761: je skip (exclude caller's thread) // 0x1800A9763: mov rdx, [rdi] (vector data pointer) // 0x1800A9778: call [IAT:VirtualAlloc] or HeapReAlloc if needed // 0x1800A97CA: mov [rdx+rcx*4], eax (store thread ID) // 0x1800A97CD: incl [rdi+0xC] (vector count++) // 0x1800A97DD: call [IAT:Thread32Next](hSnapshot, &te32) // 0x1800A97E3: test eax, eax → jne loop // 0x1800A97EB: call [IAT:GetLastError] → cmp 0x12 (ERROR_NO_MORE_FILES) // 0x1800A9815: call IAT:CloseHandle Return value: 0 on success (ESI = 0 → je path), 9 on error (EBX = 9 → mov eax, 9).

3.2 Thread Suspend/Resume Function (0x1800A9A20–0x1800A9A98)

Iterates the thread ID vector and either suspends or resumes each thread. Called before and after code patching. void SuspendOrResumeThreads(DWORD* id_vector, int action) { // action: 0 = resume, 1 = suspend for (int i = 0; i < id_vector->count; i++) { DWORD tid = id_vector->data[i]; if (tid == 0) continue; HANDLE hThread = OpenThread(0x5A, FALSE, tid); // THREAD_SUSPEND+CONTEXT if (!hThread) continue; if (action == 0) ResumeThread(hThread); else SuspendThread(hThread); CloseHandle(hThread); } // free id_vector->data via HeapFree }

3.3 Code Patcher (0x1800A9A9C–0x1800A9BC3)

Writes trampoline/hook bytes at a target address with full thread-safety. Called from SkillHack and other modules during hook installation. int PatchCode(int hook_index, int is_jmp) { // Lookup hook entry: base = g_hookTable[hook_index * 0x38] void* target = hook_entry->target_va; void* jump_dest = hook_entry->callback; // or target-5 if is_short_jmp DWORD old_protect; // First VirtualProtect: make target page EXECUTE_READWRITE (0x40) VirtualProtect(target, patch_size, PAGE_EXECUTE_READWRITE, &old_protect); if (is_jmp) { // Write E9 JMP rel32 (BYTE)target = 0xE9; (DWORD)(target+1) = (DWORD)jump_dest - (DWORD)target - 5; if (hook_entry->flags & 1) (WORD)orig_ptr = 0xF9EB; // short jmp back } else { // Copy original bytes (stub) (DWORD)target = hook_entry->orig_bytes_dword; if (hook_entry->flags & 1) { (WORD)(target+4) = hook_entry->orig_word; (BYTE)(target+6) = hook_entry->orig_byte; } else { (BYTE)(target+4) = hook_entry->orig_byte; } } // Second VirtualProtect: restore original protection VirtualProtect(target, patch_size, old_protect, &old_protect); FlushInstructionCache(GetCurrentProcess(), target, patch_size); // Update flags: toggle enable/jmp bits in hook_entry->flags return 0; // success }

4. Anti-Debug and Exception Handling

The binary contains two related security functions: a structured exception handler setup that uses IsDebuggerPresent, and a stack security cookie verifier.

4.1 Exception Handler Setup (0x1800AC580–0x1800AC6CA)

This function is the C runtime __security_check_cookie and SEH initializer. It is called during DLL initialization (DllMain) and during first-chance exception dispatching. // 0x1800AC580: CRT security init function // ecx = fault code (passed in from caller) // Check IsProcessorFeaturePresent(0x17 = PF_FASTFAIL_AVAILABLE) call IAT:IsProcessorFeaturePresent test eax, eax je skip_int29 int 29h // Fast fail - terminate without SEH if supported skip_int29: call sub_1800AC574 // __security_check_cookie helper // Set up EXCEPTION_RECORD and CONTEXT for RtlCaptureContext call RtlCaptureContext // [IAT:0xB1220] call RtlLookupFunctionEntry // [IAT:0xB1218] - find handler call RtlVirtualUnwind // [IAT:0xB1210] - unwind frame // Build EXCEPTION_RECORD: movl [rsp+50h], 0x40000015 // ExceptionCode = STATUS_FATAL_APP_EXIT movl [rsp+54h], 1 // ExceptionFlags = EXCEPTION_NONCONTINUABLE call [IAT:IsDebuggerPresent] // 0x1800AC67B mov ebx, eax // save result call IAT:SetUnhandledExceptionFilter // remove any handler call IAT:UnhandledExceptionFilter test eax, eax jne done cmp ebx, 1 // was debugger present? je done lea ecx, [eax+3] call __report_gsfailure // terminate Note: IsDebuggerPresent is NOT used as an anti-cheat measure; it is part of the MSVC CRT __security_check_cookie fast-fail path. The binary does not actively attempt to detect or evade debuggers — it simply invokes standard MSVC security cookie failure reporting.

4.2 Security Canary Verifier (0x1800AC6CC–0x1800AC77B)

This is the standard MSVC __security_check_cookie function. It compares the stack cookie against a magic constant, then triggers a fast-fail if mismatch is detected. // 0x1800AC6CC: __security_check_cookie // rcx = stack cookie value to verify mov rax, [__security_cookie] // load expected cookie (initialized at startup) mov rbx, 0x2B992DDFA232 // partial expected value (lower 48 bits) cmp rax, rbx jne fail // mismatch → security violation // Derive additional check from: // GetSystemTimeAsFileTime, GetCurrentThreadId, GetCurrentProcessId, // QueryPerformanceCounter, combined via XOR and shift call [IAT:GetSystemTimeAsFileTime] call [IAT:GetCurrentThreadId] xor -0x10(%rbp), rax call [IAT:GetCurrentProcessId] xor -0x10(%rbp), rax call [IAT:QueryPerformanceCounter] // ... XOR operations combining all values // Mask to 0xFFFFFFFFFFFF (48 bits) // Compare with stored cookie — mismatch → crash // This is 100% MSVC runtime security, NOT an anti-cheat check

5. HLSL Shader Compilation (D3DCompile)

The cheat overlay uses two shaders compiled at runtime via D3DCompile from D3DCOMPILER_47.dll. Both shaders are the standard ImGui Direct3D11 backend shaders embedded verbatim in .rdata. They are compiled in the D3D11 initialization function (0x180054DC0–0x1800551E8) which is called during the Present hook setup.

5.1 Vertex Shader

// Source at RVA 0x3AE660, length = 0x2DD (733 bytes) // Compilation: D3DCompile(src, 0x2DD, NULL, NULL, NULL, "main", "vs_4_0", 0, 0, ...) cbuffer vertexBuffer : register(b0) { float4x4 ProjectionMatrix; }; struct VS_INPUT { float2 pos : POSITION; float4 col : COLOR0; float2 uv : TEXCOORD0; }; struct PS_INPUT { float4 pos : SV_POSITION; float4 col : COLOR0; float2 uv : TEXCOORD0; }; PS_INPUT main(VS_INPUT input) { PS_INPUT output; output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f)); output.col = input.col; output.uv = input.uv; return output; }

5.2 Pixel Shader

// Source at RVA 0x3AE940, length = 0x191 (401 bytes) // Compilation: D3DCompile(src, 0x191, NULL, NULL, NULL, "main", "ps_4_0", 0, 0, ...) struct PS_INPUT { float4 pos : SV_POSITION; float4 col : COLOR0; float2 uv : TEXCOORD0; }; sampler sampler0; Texture2D texture0; float4 main(PS_INPUT input) : SV_Target { float4 out_col = input.col * texture0.Sample(sampler0, input.uv); return out_col; }

5.3 Shader Initialization Sequence (0x180054DC0)

// Prologue: save R14-R15, allocate 0x220 stack // Load g_D3DState from [g_Config+0xD8] into R14 // Check if already initialized: cmp (*r14), null je skip_init // Call sub_0x1800551F0 (create vertex/index buffers) // === Compile Vertex Shader === lea rcx, [rip+0x1803AE660] // HLSL source ptr mov edx, 0x2DD // source length xor r8d, r8d // pSourceName = NULL xor r9d, r9d // pDefines = NULL mov [rsp+20h], r15 // pInclude = NULL lea rax, [0x1803AEADC] // 'main' string mov [rsp+28h], r12 // pInclude (NULL) mov [rsp+30h], rax // pEntrypoint = 'main' lea rax, [0x1803AEAD4] // 'vs_4_0' mov [rsp+38h], r15d // Flags1 = 0 mov [rsp+40h], r15d // Flags2 = 0 mov [rsp+48h], &ppVSCode // output blob ptr mov [rsp+50h], r15 // ppErrorBlob = NULL call [IAT:D3DCompile] js fail // Get VS blob pointer, call ID3DBlob::GetBufferPointer/GetBufferSize // Then: call ID3D11Device::CreateVertexShader via vtable slot[0x20/8] // Create input layout via vtable slot[0x58/8] // Create constant buffer (ProjectionMatrix) via vtable slot[0x60/8] // === Compile Pixel Shader === lea rcx, [rip+0x1803AE940] // PS HLSL source mov edx, 0x191 // PS source length // ... same parameters pattern ... // pEntrypoint = 'main', target = 'ps_4_0' call [IAT:D3DCompile] js fail // Create pixel shader via vtable slot[0x78/8] (CreatePixelShader) // Create sampler state via vtable slot[0x78/8] on device // Create blend state (alpha blending) with blend ops // Create depth stencil state // Create rasterizer state

6. Configuration File I/O

Configuration is read and written using a helper function (0x180011EA0) that converts UTF-8 paths to wide-char then calls _wfopen. Callers pass different file mode strings ('rb' for read, 'wt' for write) to the same function.

6.1 File Open Helper (0x180011EA0–0x180012043)

FILE* OpenConfigFile(const char* path_utf8, const char* mode_utf8) { // rcx = path_utf8, rdx = mode_utf8 // Get length of path: MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0) int path_len = MultiByteToWideChar(0xFDE9, 0, path, -1, NULL, 0); // CP_UTF8=65001=0xFDE9 // Get length of mode string int mode_len = MultiByteToWideChar(0xFDE9, 0, mode, -1, NULL, 0); // Allocate wide char buffer (stack if small enough, heap if > 0x104 chars) if (path_len + mode_len > 0x104) wbuf = malloc((path_len + mode_len) * 2); else wbuf = alloca((path_len + mode_len) * 2); wchar_t* wpath = wbuf; wchar_t* wmode = wbuf + path_len; // Convert path to wide MultiByteToWideChar(0xFDE9, 0, path, -1, wpath, path_len); // Convert mode to wide MultiByteToWideChar(0xFDE9, 0, mode, -1, wmode, mode_len); // Open file FILE* fp = _wfopen(wpath, wmode); if (heap_buf) free(heap_buf); return fp; }

6.2 Config File Mode Strings

Two mode strings are stored in .rdata at consecutive addresses: RVA String Usage 0x3AD590 'rb' Config READ - binary read mode 0x3AD594 'wt' Config WRITE - text write mode (ImGui ini)

6.3 Config Read Callers

The config file open helper is called from two read contexts and two write contexts: Caller VA Func Range Mode Data Source / Purpose 0x1800170B9 0x17078-0x172CA 'wt' Serialize ImGui window positions/sizes to ini file (ImGui_ImplDX11 save) 0x180030750 0x30620-0x307A0 'wt' Write g_Config state to JSON file on module disable/exit (via fread) 0x302D2-0x30348 'rb' Read JSON config on startup, populate g_Config fields 0x18000EA1B 0xE9F4-0xEA33 n/a fwrite to stdout/console (debug output, size=1)

6.4 Config Write Function (0x180030620)

void SaveConfig(ConfigState* state) { // Check state->enabled_flag [rbx+0x2900] // Load state->file_path pointer [rbx+0x50] // Call sub_0x180030A90 (build file path string) // Call OpenConfigFile(path, 'wt') → returns FILE* fp // Serialize config to string via sub_0x180012050 // fwrite(config_string, 1, string_length, fp) // fclose(fp) // Also handles periodic auto-save: // xmm0 = [rbx+0x2904] (auto-save timer) // if (timer > 0) { timer -= delta_time } // When timer expires: rebuild path, re-open, write again }

7. WndProc Handler and Hotkey Dispatch

The WndProc callback is registered at VA 0x1800826A0 during window class creation (RegisterClassExW). It is the Win32 message handler for the overlay window and handles three specific messages before deferring all others to ImGui's built-in handler.

7.1 WndProc Function (0x1800826A0)

Signature: LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Step 1: Pass ALL messages to ImGui first if (g_ImGuiCtx != NULL) { // ImGui_ImplWin32_WndProcHandler(hwnd, msg, wParam, lParam) // [rsp+0x20] = g_ImGuiCtx+0x30 LRESULT r = ImGui_ImplWin32_WndProcHandler(hwnd, msg, wParam, lParam); if (r != 0) return 1; // ImGui consumed the message } switch (msg) { case WM_DESTROY (0x0002): PostQuitMessage(0); return 0; case WM_SIZE (0x0005): // Ignore minimize (SIZE_MINIMIZED = 1) if (g_pSwapChain != NULL && wParam != 1) { // Free existing render target if (g_pRenderTargetView) { g_pRenderTargetView->Release(); // vtable[0x10] g_pRenderTargetView = NULL; } // Resize swap chain buffers // pSwapChain->ResizeBuffers(0, LOWORD(lParam), HIWORD(lParam), 0, 0) g_pSwapChain->ResizeBuffers(0, LOWORD(lParam), HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); // vtable[0x68] // Recreate D3D11 resources (render target, shaders, etc.) HookInstall(); // 0x1800825B0 } return 0; case WM_SYSCOMMAND (0x0112): // Suppress SC_KEYMENU (ALT key activating system menu) if ((wParam & 0xFFF0) == SC_KEYMENU) return 0; break; default: // Forward to DefWindowProcW via ImGui_ImplWin32_WndProcHandler return ImGui_ImplWin32_WndProcHandler(hwnd, msg, wParam, lParam); } return 0; }

7.2 Message Dispatch Table

WM_ Code Value Action Notes WM_DESTROY 0x0002 PostQuitMessage(0) Triggers clean shutdown of message loop WM_SIZE 0x0005 ResizeBuffers + HookInstall() recreate Skipped if wParam==SIZE_MINIMIZED(1) WM_SYSCOMMAND 0x0112 Return 0 if SC_KEYMENU (0xF100) Suppresses ALT-key menu flash on overlay (all others)

Defer to ImGui_ImplWin32_WndProcHandler ImGui handles mouse/keyboard/focus/IME

7.3 F12 Hotkey — Panel Toggle

The overlay panel toggle is NOT processed inside WndProc. It is polled via GetAsyncKeyState in the per-frame Present hook loop at VA 0x18008301A, which is part of the ModuleManager main render function (0x180082FC0). // Inside ModuleManager render loop (0x180082FC0), called each Present() frame: // Poll F12 key (VK_F12 = 0x7B) SHORT keyState = GetAsyncKeyState(0x7B); // VK_F12 if (keyState & 0x1) { // Key was pressed since last call — toggle panel visibility // Static init guard pattern (MSVC thread-safe static) // g_showPanel (.data+0x245C) = !g_showPanel g_Config.show_panel ^= 1; // [.data+0x245C] toggle } // Banner string shown in game window title / tray when panel is hidden: // 'EF - Cheeto Press F12 to show panel' (RVA 0x3AF258) Address Description 0x18008301A GetAsyncKeyState(VK_F12=0x7B) call — panel toggle poll .data+0x245C g_showPanel flag (BYTE): 0=hidden, 1=visible RVA 0x3AF258 Banner string 'EF - Cheeto ... Press F12 to show panel' 0x1800826A0 WndProc callback registered via RegisterClassExW 0x180057720 ImGui_ImplWin32_WndProcHandler (handles all ImGui keyboard/mouse) 0x1800825B0 HookInstall / D3D11 resource recreation (called on WM_SIZE)

7.4 Module Hotkeys

A dedicated hotkey error handler exists at 0x1800AECE0, referenced by the string '[ERROR] Failed to process hotkeys for module'. This function is an exception handler — it is called if a module's hotkey processing throws. Individual module hotkey configurations are stored in the per-module state structs and dispatched by the ModuleManager loop, not in WndProc.

8. Hook Manager Internals

The hook manager is a global singleton initialized lazily via an MSVC thread-safe static at 0x180081B00. It manages a flat array of hook entries, a hash table for fast lookup by target address, and a spinlock for thread safety. All four hook API functions (CreateHook, RemoveHook, EnableHook, GetHookInfo) acquire the spinlock at entry and release it on every exit path.

8.1 Singleton Memory Layout

The singleton is stored at .data+0x2470 (VA 0x1803C7470). The structure is 0x90 bytes, zero-initialized on first call. Offset Type Field Description +0x00 QWORD* hook_array Pointer to flat array of hook entries (0x38 bytes each) +0x08 DWORD hook_capacity Allocated slot count for hook_array +0x0C DWORD hook_count Number of active hooks currently installed +0x10 QWORD* hash_buckets Pointer to hash table bucket array (linked list heads) +0x18 DWORD bucket_count Number of hash buckets (power of 2, initial=8) +0x1C DWORD bucket_mask hash_mod mask = bucket_count2 - 1 +0x20 QWORD free_list_head Head of freed/recycled hook slot free list +0x28 float load_factor Hash table load factor threshold (0x3f800000 = 1.0f) +0x30 BYTE initialized Set to 0 after init, prevents double-init .data+0x1E88 DWORD spinlock Global spinlock DWORD; 0=free, 1=held

8.2 Hook Entry Structure (0x38 bytes)

Each entry in the hook_array is 0x38 bytes. The hook array grows dynamically; initial capacity is 0x80 slots allocated via the IAllocator at .data+0x1E90. Offset Type Field Description +0x00 QWORD target_va Virtual address of the hooked IL2CPP function +0x08 QWORD callback_va Virtual address of the replacement/detour function +0x10 QWORD trampoline_va VirtualAlloc'd trampoline (original bytes + JMP back) +0x18 DWORD orig_bytes_0_3 Saved original 4 bytes at target (for restore) +0x1C WORD orig_bytes_4_5 Saved original bytes 4–5 at target +0x1E BYTE orig_byte_6 Saved original byte 6 at target +0x20 BYTE flags Bit 0: has_far_jmp (6-byte JMP); Bit 1: enabled; Bit 2: suspended +0x24 DWORD flags2 Lower nibble: hook type (0=near JMP, 1=far) +0x28 QWORD hash_next Next entry pointer in hash chain (for collision chaining) +0x30 QWORD reserved Padding / future use

8.3 Spinlock (0x1800A9C88)

All four hook API functions call the spinlock acquire function at 0x1800A9C88 on entry. Release is done inline via XCHG [.data+0x1E88], 0 at the end of each function. // Spinlock acquire — 0x1800A9C88 // Uses LOCK CMPXCHG on .data+0x1E88 (global DWORD spinlock) void AcquireSpinlock() { DWORD backoff = 0; while (true) { DWORD expected = 0; // LOCK CMPXCHG [.data+0x1E88], 1 if (InterlockedCompareExchange(&g_spinlock, 1, 0) == 0) return; // acquired // Exponential backoff: if backoff < 32, SwitchToThread(0); else Sleep(1) backoff += 1; if (backoff < 32) SwitchToThread(); // IAT 0x1800B1148 else Sleep(1); } } // Spinlock release — inline in all callers // XCHG [.data+0x1E88], ebx (where ebx=0, atomic store 0)

8.4 CreateHook (0x1800A9CC8)

Installs a new hook. Takes target VA (rcx), callback VA (rdx), and optional out_trampoline pointer (r8). Returns 0 on success, error code otherwise. // CreateHook(void* target, void* callback, void** out_trampoline) -> int // RVA 0x0A9CC8 int CreateHook(void* target, void* callback, void** out_trampoline) { AcquireSpinlock(); // 0x1800A9C88 // Validate hook manager initialized if (g_hookMgr.allocator == NULL) return 2; // MH_ERROR_NOT_INITIALIZED // Validate target and callback are executable if (!IsExecutable(target)) return 7; // MH_ERROR_NOT_EXECUTABLE if (!IsExecutable(callback)) return 7; // Check if hook already exists for this target for (int i = 0; i < g_hookMgr.hook_count; i++) { if (g_hookMgr.hook_array[i].target_va == target) { if (i == -1) continue; return 3; // MH_ERROR_ALREADY_CREATED } } // Allocate a trampoline buffer near the target TrampolineSlot* slot = AllocTrampolineSlot(target); // 0x1800A960C if (!slot) return 9; // MH_ERROR_MEMORY_ALLOC // Build trampoline: copy prologue bytes + write JMP back HookEntry entry = {}; if (!BuildTrampoline(target, callback, slot, &entry)) return 8; // Fill hook entry fields entry.target_va = target; // [r8+0x00] entry.callback_va = callback; // [r8+0x08] (from [rsp+0x28]) entry.trampoline_va = slot->code; // [r8+0x10] // Save original bytes for unhook restore if (entry.flags & 1) { // far JMP (6-byte) entry.orig_bytes_0_3 = (DWORD)(target - 5); entry.orig_bytes_4_5 = (WORD) (target - 1); entry.orig_byte_6 = (BYTE) (target + 1); } else { // near JMP (5-byte) entry.orig_bytes_0_3 = (DWORD)target; entry.orig_byte_6 = (BYTE)(target + 4); } if (out_trampoline) *out_trampoline = slot->code; ReleaseSpinlock(); // XCHG [.data+0x1E88], 0 return 0; // MH_OK }

8.5 RemoveHook (0x1800A9E8C)

Removes an installed hook by target address. If the hook is enabled, it is disabled first (original bytes restored). The entry is removed from the array by swapping with the last element. The array is shrunk by half if utilization drops below 50% and count > 0x20. // RemoveHook(void* target) -> int // RVA 0x0A9E8C int RemoveHook(void* target) { AcquireSpinlock(); if (g_hookMgr.allocator == NULL) return 2; // Linear search for target in hook array (stride 0x38) int idx = -1; for (int i = 0; i < g_hookMgr.hook_count; i++) { if (g_hookMgr.hook_array[i].target_va == target) { idx = i; break; } } if (idx == -1) return 4; // MH_ERROR_NOT_CREATED HookEntry* entry = &g_hookMgr.hook_array[idx]; // If hook is currently enabled, disable it first (restore original bytes) if (entry->flags & 0x2) { GetHookInfo(idx, 0, ...); // 0x1800A96B0 EnableHook(idx, 0); // 0x1800A9A9C — restore original bytes SuspendOtherThreads(...); // 0x1800A9A20 — thread safety } // Free trampoline memory FreeSlot(entry->trampoline_va); // 0x1800AA684 // Compact array: move last entry into freed slot int last = g_hookMgr.hook_count - 1; if (idx < last) { // memmove: copy 0x38 bytes from hook_array[last] to hook_array[idx] // (3x movups xmm0 + movsd for full 0x38-byte copy) hook_array[idx] = hook_array[last]; } g_hookMgr.hook_count--; // Shrink array if count <= capacity/2 and count > 0x20 if (g_hookMgr.hook_capacity / 2 >= 0x20 && g_hookMgr.hook_count <= g_hookMgr.hook_capacity / 2) { realloc(hook_array, (capacity/2) * 0x38); g_hookMgr.hook_capacity /= 2; } ReleaseSpinlock(); return 0; }

8.6 EnableHook / PatchCode (0x1800A9A9C)

Patches or unpatches the target function's first bytes. Suspends all other threads during the write using VirtualProtect + WriteProcessMemory, then resumes them. Handles both near (5-byte E9 JMP) and far (6-byte FF25 indirect JMP) hook types. // EnableHook(int hook_idx, BOOL enable) -> int // RVA 0x0A9A9C int EnableHook(int hook_idx, BOOL enable) { HookEntry* e = &g_hookMgr.hook_array[hook_idx * 0x38]; // Determine patch target and size BOOL far_jmp = e->flags & 0x1; // bit 0: uses 6-byte far JMP void* patch_target = far_jmp ? (e->target_va - 5) : e->target_va; SIZE_T patch_size = far_jmp ? 7 : 5; // [rcx*2 + 5] // VirtualProtect(patch_target, patch_size, PAGE_EXECUTE_READWRITE, &old) VirtualProtect(patch_target, patch_size, 0x40, &old_protect); if (enable) { // Write JMP hook: (BYTE)patch_target = 0xE9; // near JMP opcode (DWORD)(patch_target+1) = (DWORD)(e->callback_va - (QWORD)patch_target - 5); if (far_jmp) { // Also patch 2 bytes before target_va with short JMP back (WORD)(e->target_va) = 0xF9EB; // JMP -5 (back to patch_target) } } else { // Restore original bytes (DWORD)patch_target = e->orig_bytes_0_3; if (far_jmp) { (WORD) (patch_target+4) = e->orig_bytes_4_5; (BYTE) (patch_target+6) = e->orig_byte_6; } else { (BYTE) (patch_target+4) = (BYTE)e->orig_bytes_4_5; } } // Restore page protection VirtualProtect(patch_target, patch_size, old_protect, &old_protect); // Flush instruction cache FlushInstructionCache(GetCurrentProcess(), patch_target, patch_size); // Update flags: set/clear enabled bit (bit 1) and suspended bit (bit 2) // Bit manipulation: (enable<<2) XOR flags, AND 0x2, XOR flags, XOR enable_bit e->flags = (e->flags & ~0x6) | ((enable ? 0x2 : 0x0)); return 0; // MH_OK }

8.7 FNV-1a Hash Implementation

The hash table uses FNV-1a (Fowler–Noll–Vo) 64-bit hashing to map target VA pointers to hash bucket indices. The compiler has unrolled the byte loop into 8 sequential XOR+MUL pairs operating on each byte of the 8-byte pointer. // FNV-1a 64-bit hash of a pointer value (unrolled, 0x18008D555) // r11 = target_va (8 bytes to hash) // r10 = FNV prime = 0x00000100000001B3 // r9 = FNV offset = 0xCBF29CE484222325 (init value) uint64_t FNV1a_64(uint64_t target_va) { uint64_t hash = 0xCBF29CE484222325ULL; // FNV offset basis uint64_t prime = 0x00000100000001B3ULL; // FNV prime // Byte 0 (bits 0-7) hash ^= (uint8_t)(target_va >> 0); hash *= prime; // Byte 1 (bits 8-15) hash ^= (uint8_t)(target_va >> 8); hash *= prime; // Byte 2 (bits 16-23) hash ^= (uint8_t)(target_va >> 16); hash *= prime; // Byte 3 (bits 24-31) hash ^= (uint8_t)(target_va >> 24); hash *= prime; // Byte 4 (bits 32-39) hash ^= (uint8_t)(target_va >> 32); hash *= prime; // Byte 5 (bits 40-47) hash ^= (uint8_t)(target_va >> 40); hash *= prime; // Byte 6 (bits 48-55) hash ^= (uint8_t)(target_va >> 48); hash *= prime; // Byte 7 (bits 56-63) hash ^= (uint8_t)(target_va >> 56); hash = prime; // Map to bucket index uint64_t bucket_idx = hash & bucket_mask; // [r8+0x48] bucket_idx += bucket_idx; // 2 for pointer-sized bucket entries return bucket_idx; } // Bucket lookup in hash chain: // head = hash_buckets[bucket_idx] // [rcx + r98 + 0x00] // sentinel = hash_buckets[bucket_idx + 1] // [rcx + r98 + 0x08] // while (node != sentinel): // if node->target_va == target: return node // node = node->hash_next

8.8 Hook Manager Key Addresses

Address Function / Field Notes 0x1800A9C88 AcquireSpinlock() LOCK CMPXCHG loop with SwitchToThread/Sleep backoff 0x1800A9CC8 CreateHook(target, cb, tramp) Validates, searches array, builds trampoline, patches 0x1800A9E8C RemoveHook(target) Finds by linear search, disables if live, frees trampoline, compacts 0x1800A9A9C EnableHook(idx, enable) VirtualProtect + write JMP/restore + FlushInstructionCache 0x1800A96B0 GetHookInfo(idx, ...) Reads hook entry fields into caller-supplied buffer 0x1800A960C AllocTrampolineSlot(target) Finds or allocates VirtualAlloc page near target 0x1800AA684 FreeTrampolineSlot(tramp) Returns slot to free list .data+0x1E88 g_spinlock (DWORD) Global spinlock; acquired via CMPXCHG, released via XCHG .data+0x1E90 g_allocator (QWORD*) IAllocator vtable pointer used by hook manager .data+0x2470 g_hookMgr (struct, 0x90B) Hook manager singleton base address .data+0x2480 hook_array (QWORD*) Flat array of 0x38-byte hook entries .data+0x27E0 hook_array (mirror ptr) Second reference to hook_array base .data+0x27EC hook_count (DWORD) Number of currently installed hooks 0x18008D555 FNV-1a hash body Unrolled 8-byte XOR/MUL loop, prime=0x100000001B3

9. ESPModule State Layout and Color Table Defaults

The ESPModule state struct is stored at .data+0x1F70 (VA 0x1803C6F70). It is initialized by the lazy singleton at 0x180083E00, which zero-initializes all fields, sets the module name, wires up both vtable pointers, writes boolean defaults for the eight display flags, and loads 12 RGBA color slots from .rdata constants via MOVDQA into 16-byte-aligned slots starting at state+0x40.

9.1 ESPModule State Struct Layout

Offset Type Field Default +0x00 QWORD* vtable[0] (init thunk) 0x1803AF9E0 +0x08 str* module_name (std::string) 'ESPModule' +0x28 BYTE enabled 0 (off) +0x30 DWORD max_dist 0x12C = 300 (integer) +0x34 BYTE show_monsters 1 (true) +0x35 BYTE show_npc 1 (true) +0x36 BYTE show_friendly 1 (true) +0x37 BYTE show_puzzles 1 (true) +0x38 BYTE show_all 0 (false) +0x39 BYTE show_distance 1 (true) +0x3A BYTE show_name 1 (true) +0x3B BYTE show_type 0 (false) +0x3C DWORD (alignment padding)

+0x40 float[4] color[0] RGBA see table below +0x50 float[4] color[1] RGBA see table below +0x60 float[4] color[2] RGBA see table below +0x70 float[4] color[3] RGBA see table below +0x80 float[4] color[4] RGBA see table below +0x90 float[4] color[5] RGBA see table below +0xA0 float[4] color[6] RGBA see table below +0xB0 float[4] color[7] RGBA see table below +0xC0 float[4] color[8] RGBA see table below +0xD0 float[4] color[9] RGBA see table below +0xE0 float[4] color[10] RGBA see table below +0xF0 float[4] color[11] RGBA see table below

9.2 Color Table Defaults (12 slots × 16 bytes)

Each slot is a 128-bit XMMWORD (4× IEEE 754 float, little-endian order R, G, B, A). Values are loaded from .rdata constants at init time via MOVDQA. The color slot-to-entity-type mapping follows the order the show_* flags were written in the initializer. Slot State Offset .rdata RVA R G B A Color Name Entity Type 0 +0x40 0x3B3510 1.000 0.000 0.000 1.000 Red Monsters / Enemies 1 +0x50 0x3B3520 1.000 0.647 0.000 1.000 Orange NPC 2 +0x60 0x3B3540 1.000 1.000 0.000 1.000 Yellow Friendly 3 +0x70 0x3B3530 0.000 1.000 0.000 1.000 Green Puzzles 4 +0x80 0x3B3590 0.000 0.000 1.000 1.000 Blue (spare/all) 5 +0x90 0x3B35A0 0.000 1.000 1.000 1.000 Cyan (spare) 6 +0xA0 0x3B3580 0.580 0.000 0.827 1.000 Purple (spare) 7 +0xB0 0x3B35B0 1.000 1.000 1.000 1.000 White (spare) 8 +0xC0 0x3B3560 1.000 0.078 0.576 1.000 Hot Pink (spare) 9 +0xD0 0x3B3570 1.000 0.753 0.796 1.000 Light Pink (spare) 10 +0xE0 0x3B3500 0.000 0.000 0.000 1.000 Black (spare) 11 +0xF0 0x3B3550 0.502 0.502 0.502 1.000 Gray (spare) All 12 slots have alpha fixed at 1.000 (fully opaque). Slots 0–3 correspond to the four named entity types controlled by show_monsters / show_npc / show_friendly / show_puzzles flags. Slots 4–11 are spare palette entries available for future entity categories; the ImGui color picker in ESPModule::Render exposes all 12 via '##Foreground' color edit widgets.

9.3 Show Flag Default Summary

Flag Offset Default Notes show_monsters +0x34 1 (ON) Draws boxes/labels for monster entities show_npc +0x35 1 (ON) Draws boxes/labels for NPC entities show_friendly +0x36 1 (ON) Draws boxes/labels for friendly entities show_puzzles +0x37 1 (ON) Draws boxes/labels for puzzle objects show_all +0x38 0 (OFF) Override: draw all entity types regardless of flags above show_distance +0x39 1 (ON) Appends distance string to entity label show_name +0x3A 1 (ON) Appends entity name string to label show_type +0x3B 0 (OFF) Appends entity type string to label max_dist +0x30 300 Integer cutoff distance; entities beyond this are not drawn

10. SkillHack Hook Callbacks

SkillHack installs up to six IL2CPP hooks across five callback functions. The hooks intercept game methods that govern skill cooldowns, skill availability checks, and skill costs. All five callbacks share the same guard pattern: call SkillHack singleton init (0x180081300), check enabled flag at [singleton+0x28], and either return the bypass value immediately or fall through to the original method via the hook manager's trampoline dispatcher (0x18008FF00).

10.1 Hook Installation Map

SkillHack::Render (0x18008D1F0) installs hooks in two stages. Three hooks are installed directly via the hook-installer wrapper (0x18008D8A0). Three more are installed by dedicated patch functions called from Render. All six use the same FNV-1a hash lookup pattern and CreateHook call. Hook # Target Ptr Callback VA Patch Function Installed By 1 [g_Config+0x1E60] 0x18008D4B0 (dispatcher)

Render direct → 0x8D8A0 2 [g_Config+0x1E68] 0x18008D4B0 (dispatcher)

Render direct → 0x8D8A0 3 [g_Config+0x1E50] 0x18008D500 (float 100.0) 0x18008E220 Render → 8E220 → CreateHook 4 [g_Config+0x1E58] 0x18008D640 (bool true) 0x18008EBC0 Render → 8EBC0 → CreateHook 5 [g_Config+0x1E40] 0x18008D780 (void return) 0x18008F560 Render → 8F560 → CreateHook 6 [g_Config+0x1E48] 0x18008D4B0 (dispatcher)

Render direct → 0x8D8A0 (tail) The g_Config IL2CPP function pointer slots are populated at runtime from IL2CPP metadata. Their contents are zero/garbage in the static binary on disk.

10.2 Generic Dispatcher — 0x18008D4B0

Used for hooks 1, 2, and 6. When the skill hack is enabled, returns BOOL true (1) immediately to the caller, bypassing any skill gate check. When disabled, passes through to the original IL2CPP function via the trampoline. // Generic dispatcher callback — 0x18008D4B0 // Used for: hooks on [g_Config+0x1E60], [g_Config+0x1E68], [g_Config+0x1E48] // Return type: BOOL (BYTE in al) BOOL Callback_Dispatcher(void* self, void* arg) { // Get SkillHack singleton (lazy init, 0x180081300) auto* sk = SkillHack_GetSingleton(); if (sk->enabled) { // [singleton+0x28] != 0 return 1; // bypass — skill check always passes } // Disabled: look up original function via FNV-1a hash and call trampoline // HookManager::GetOriginal(hookMgr, this_callback_va, self, arg) auto* hookMgr = HookManager_GetSingleton(); // 0x180081B00 return CallOriginal(hookMgr, /callback=/0x18008D4B0, self, arg); // → 0x18008FF00 }

10.3 Variant 1: Float Return — 0x18008D500

Installed by patch function 0x18008E220 on the target at [g_Config+0x1E50]. Intercepts a method that returns a float — most likely GetCooldownPercent() or GetCooldownRemaining(). Returns 100.0 when enabled, indicating the skill is fully cooled down / available. // Cooldown bypass callback — 0x18008D500 // Installed on: [g_Config+0x1E50] (via patch fn 0x18008E220) // Return type: float (xmm0) float Callback_CooldownBypass(void* self, void* arg) { auto* sk = SkillHack_GetSingleton(); if (sk->enabled) { // movss xmm0, [rip+0x325de5] -> RVA 0x3B3308 = 100.0f return 100.0f; // skill cooldown = 100% complete (fully ready) } // Hash self VA via FNV-1a, look up hook entry, call original via trampoline auto* hookMgr = HookManager_GetSingleton(); return CallOriginal_Float(hookMgr, /callback=/0x18008D500, self, arg); } // Note: 0x42C80000 = 100.0 IEEE 754 single-precision (confirmed from .rdata RVA 0x3B3308) // The prior volume summary incorrectly stated this returns 0.0.

10.4 Variant 2: Bool True — 0x18008D640

Installed by patch function 0x18008EBC0 on the target at [g_Config+0x1E58]. Intercepts a method that returns a boolean — most likely IsSkillAvailable() or CanUseSkill(). When enabled, always returns true (1). When disabled, the hash lookup falls through: if the original function is found in the hook table, it is called via tail JMP; otherwise, returns false (0) as a safe default. // Skill availability bypass callback — 0x18008D640 // Installed on: [g_Config+0x1E58] (via patch fn 0x18008EBC0) // Return type: BOOL (BYTE in al) BOOL Callback_SkillAvailable(void* self, void* arg) { auto* sk = SkillHack_GetSingleton(); if (sk->enabled) { return 1; // skill is always available } // Disabled path: FNV-1a hash lookup for original auto* hookMgr = HookManager_GetSingleton(); auto* original = FindOriginalInHashTable(hookMgr, /callback=/0x18008D640); if (original != NULL) { // rex.WB JMP r8 — tail call to original return original(self, arg); } // Hash miss — safe fallback return 0; // xor al,al (0x18008D770) }

10.5 Variant 3: Void Early Return — 0x18008D780

Installed by patch function 0x18008F560 on the target at [g_Config+0x1E40]. Intercepts a void method — most likely ApplySkillCost() or DeductMana(). When enabled, returns immediately without executing the function body, discarding the cost deduction entirely. When disabled, the hash lookup finds the original and tail-calls it. // Skill cost bypass callback — 0x18008D780 // Installed on: [g_Config+0x1E40] (via patch fn 0x18008F560) // Return type: void void Callback_SkillCostBypass(void* self, void* arg) { auto* sk = SkillHack_GetSingleton(); if (sk->enabled) { return; // jne 0x18008D894 — skip to ret immediately // Original cost deduction never executes } // Disabled path: FNV-1a hash lookup for original auto* hookMgr = HookManager_GetSingleton(); auto* original = FindOriginalInHashTable(hookMgr, /callback=/0x18008D780); if (original != NULL) { // call r8 — call original, then return original(self, arg); // 0x18008D891: call r8 } // If hash miss: no-op (safe for void) }

10.6 Common Trampoline Dispatcher — 0x18008FF00

When any callback is disabled and needs to call the original IL2CPP method, it calls 0x18008FF00. This function computes the FNV-1a hash of the callback's own VA, looks up the corresponding hook entry's trampoline_va field (+0x18), and tail-jumps to it. It is effectively the 'call original' helper shared by all SkillHack callbacks. // CallOriginal trampoline dispatcher — 0x18008FF00 // rcx = hookMgr, rdx = callback_va (used as hash key), r8 = self, r9 = arg void* CallOriginal(HookManager* mgr, void* callback_va, void* self, void* arg) { // FNV-1a hash of callback_va -> bucket index uint64_t hash = FNV1a_64(callback_va); // same unrolled loop as 0x18008D555 uint64_t bucket_idx = hash & mgr->bucket_mask; // Walk hash chain to find entry where entry->callback_va == callback_va HookEntry* entry = FindInHashChain(mgr, bucket_idx, callback_va); if (entry && entry->trampoline_va) { // Tail jump to trampoline (original bytes + JMP back) JMP entry->trampoline_va; // rex.WB jmp r8 } // If no entry found: return NULL / no-op }

10.7 Callback Summary Table

VA Name Return Type Enabled Value Disabled Behavior Game Method (inferred) 0x18008D4B0 Dispatcher BOOL 1 (true) Call original via 0x8FF00 Skill gate / permission check 0x18008D500 CooldownBypass float 100.0f Call original via FNV hash + trampoline GetCooldownPercent / GetCooldownRemaining 0x18008D640 SkillAvailable BOOL 1 (true) Original via tail JMP, or return 0 IsSkillAvailable / CanUseSkill 0x18008D780 SkillCostBypass void early ret Original via call r8, or no-op ApplySkillCost / DeductMana

11. DLL Injection Strings — testyip / gatmp.tmp / EF-Cheeto.dll

Three std::string objects are statically pre-initialised in .data and used during the loader's startup sequence. They are not classic injection strings in the sense of being written to a remote process; they are module-path substrings used by the self-presence scanner to confirm that the cheat DLL (or its temp-file loader copy) is already mapped into the target Unity process before the IL2CPP domain is attached.

11.1 String Object Layout in .data

All three are MSVC SSO (small-string-optimised) std::string objects with the inline buffer variant active (length ≤ 15, so no heap allocation). Each occupies 24 bytes: 8-byte inline buffer, 8-byte _Mysize, 8-byte _Myres. String .data offset (base) Inline buf offset Length Capacity Content testyip +0x308 +0x318 7 15 (0x0F) testyip\0 (7 bytes) gatmp.tmp +0x328 +0x338 9 15 (0x0F) gatmp.tmp\0 (9 bytes) EF-Cheeto.dll +0x348 +0x358 13 15 (0x0F) EF-Cheeto.dll\0 (13 bytes) The _Mysize field for testyip reads as zero in the static binary image because the std::string was zero-initialised before the inline buffer was written — the buffer bytes are present but the constructor has not run. At runtime MSVC CRT initialises the object before DllMain executes.

11.2 Module Path Scanner — 0x18008B650

The function at 0x18008B650 receives a process handle (rcx), a pointer array of HMODULE values (rdx), and a count output pointer (r8). For each module handle it calls GetModuleFileNameExW (IAT 0x1800B1168) to obtain the full path as a wide string, then uses the UTF-8→wide converter at 0x18008B4E0 (wrapping MultiByteToWideChar with CP_UTF8 = 0xFDE9) to convert the two search strings, and searches each path with wcsstr. It returns the zero-based array index of the first matching module, or -1 if not found. // ModulePathScanner — 0x18008B650 // Scans a process's loaded module list for paths containing known substrings. // rcx = hProcess rdx = HMODULE[] r8 = DWORD* count_out r9 = extra_arg int ModulePathScanner(HANDLE hProcess, HMODULE* modules, DWORD* count, void* extra) { DWORD module_count = count >> 3; // [rsi] >> 3 = byte-count / sizeof(HMODULE) if (module_count == 0) return 0; // Convert search strings from UTF-8 std::string to std::wstring // 0x18008B4E0: MultiByteToWideChar(CP_UTF8=0xFDE9, 0, src, len, dst, dst_cap) std::wstring w_gatmp = Utf8ToWide("gatmp.tmp"); // .data+0x338 std::wstring w_efdll = Utf8ToWide("EF-Cheeto.dll"); // .data+0x358 int found_count = 0; for (DWORD i = 0; i < module_count; i++) { WCHAR path[0x104] = {}; // GetModuleFileNameExW(hProcess, modules[i], path, 0x104) if (!GetModuleFileNameExW(hProcess, modules[i], path, 0x104)) continue; // skip on failure → je 0x18008BA41 // Convert wide path to std::wstring for wcsstr search std::wstring wpath = WideToString(path); // 0x18000EB10 // Search for 'gatmp.tmp' in the path const wchar_t pos_gatmp = wcsstr(wpath.c_str(), w_gatmp.c_str()); // 0x1800AB6A0: custom wcsstr returning iterator, -1 if not found intptr_t idx_gatmp = (pos_gatmp ? (pos_gatmp - wpath.c_str()) : -1); if (idx_gatmp == -1) { // Search for 'EF-Cheeto.dll' in the path instead → 0x18008B937 const wchar_t* pos_ef = wcsstr(wpath.c_str(), w_efdll.c_str()); intptr_t idx_ef = (pos_ef ? (pos_ef - wpath.c_str()) : -1); if (idx_ef != -1) { // Found — store module handle and record match modules[found_count] = modules[i]; // compact in-place found_count++; } // else: neither string found, skip module } else { // gatmp.tmp match — store module handle modules[found_count] = modules[i]; found_count++; } } *count = (found_count * 8); // write back as byte count return <hook_manager_status>; // propagates from call r10 (original fn) }

11.3 Hook Installer Wrapper — 0x18008BAF0

Called at 0x1800A93CC during the main startup sequence (0x1800A9190), after FindWindow('UnityWndClass') confirms the game window exists. Receives the IL2CPP method pointer for a function to hook (rcx = r14 from [IAT+0x7DA4] = EnumProcessModules or similar resolved pointer). Calls CreateHook (0x1800A9CC8) with 0x18008B650 as the callback, handling error codes with log messages 'Failed to remove existing hook: {}' (0x1803AFB30) and 'Failed to create new hook: {}' (0x1803AFB90). // HookInstallerWrapper — 0x18008BAF0 // Installs ModulePathScanner (0x18008B650) as hook on a target IL2CPP function. // Called from main startup (0x1800A9190) once game window is found. void HookInstallerWrapper(void* target_fn) { auto* hookMgr = HookManager_GetSingleton(); // 0x180081B00 // Check if hook already exists — RemoveHook first if so if (FindExistingHook(hookMgr, target_fn)) { int rc = RemoveHook(target_fn); // 0x1800A9E8C if (rc != 0) { Log("Failed to remove existing hook: {}", FormatError(rc)); // 0x1803AFB30 return; } } // Install new hook with ModulePathScanner as callback void* trampoline = nullptr; int rc = CreateHook(target_fn, /cb=/0x18008B650, &trampoline); // 0x1800A9CC8 if (rc != 0) { Log("Failed to create new hook: {}", FormatError(rc)); // 0x1803AFB90 return; } // trampoline stored at [rbp-0x1] for later EnableHook call }

11.4 Startup Sequence Context — 0x1800A9190

The main DLL startup function at 0x1800A9190 establishes the console, hooks the module scanner, then proceeds to IL2CPP domain attachment. The three injection strings serve as the identity check: if neither 'gatmp.tmp' nor 'EF-Cheeto.dll' appears in any loaded module's path, the scanner returns no matches and the cheat does not proceed. Step Address Action 1 0x1800A91CE AllocConsole — create 'il2cpp Game Console' window 2 0x1800A9267 SetConsoleCP(0xFDE9) — set UTF-8 code page 3 0x1800A92F7 FindWindowA(NULL, 'UnityWndClass') — poll until game window present 4 0x1800A93CC HookInstallerWrapper(EnumProcessModules) — install module scanner 5 0x1800A93E6 Log 'Initializing..' — source: E:\git\Endfield_Cheeto\user\main.cpp:53 6 0x1800A942F Call [g_Config+0x1E80] — IL2CPP domain resolver 7 0x1800A945A Log 'IL2CPP Domain Found: ' if domain non-null 8 0x1800A94C4 Log 'IL2CPP Thread Attached Successfully: ' on attach 9 0x1800A9506 Error branch: Log ‘Failed to Attach IL2CPP Thread!’ (source: main.cpp) 10 0x1800A9545 Error branch: Log ‘IL2CPP Domain Not Found!’ (source: main.cpp) if domain is null 11 0x1800A959F Success path: Log ‘Initialized’ (source: main.cpp); function returns Console initialisation detail (steps 1–2): AllocConsole (IAT[0xB1108]) allocates the console window. Three freopen_s calls (IAT[0xB1878]) redirect stdin, stdout, and stderr to CONIN$ and CONOUT$. SetConsoleOutputCP(0xFDE9) sets the UTF-8 code page. GetConsoleMode (IAT[0xB1120]) reads the current output mode flags and SetConsoleMode (IAT[0xB1128]) adds ENABLE_VIRTUAL_TERMINAL_PROCESSING for ANSI colour support. SetConsoleTitleA (IAT[0xB12A0]) sets the window caption to ‘il2cpp Game Console’. The overlay window thread is then launched (call 0x1800827A0) at step 12 (see Ch. 29), running independently of the IL2CPP attach sequence. The source path 'E:\git\Endfield_Cheeto\user\main.cpp' (RVA 0x3B3148) confirms the project name and local build directory. 'Endfield_Cheeto' matches the cheat's internal identity; the published DLL name 'EF-Cheeto.dll' abbreviates this.

11.5 Injection String Summary

String .data VA Role Search context testyip 0x1803C5318 Alternate temp-file loader name wcsstr scan against each loaded module's full path gatmp.tmp 0x1803C5338 Primary temp-file loader name wcsstr scan — match means loader copy is present EF-Cheeto.dll 0x1803C5358 Published DLL name wcsstr fallback if gatmp.tmp not found in path The naming pattern indicates a two-stage loader: the cheat is first written as a temp file (gatmp.tmp or testyip) via a dropper, then optionally renamed or loaded directly as EF-Cheeto.dll. The module path scanner confirms whichever form is loaded before proceeding with IL2CPP hooking.

12. Module Render() and Update() Implementations

Each module exposes two callable entry points registered with ModuleManager: a Render() function that draws the ImGui tab panel and handles one-shot toggle/config writes, and an Update() callback (stored as a .rdata function pointer) that runs the per-frame game-state mutation. SetDither and the SkillHack 'Free Skill' tab share a no-op stub at 0x18008/3DC0 whose entire job is to free a string and optionally call operator delete on the module object — meaning those two tabs perform all their work at Render time, not per-frame. The seven implementations are documented below.

12.1 Shared g_Config Panel-Width Sequence

All modules that expand their ImGui tab panel write an identical five-instruction sequence at panel-open and invert it at panel-close. This sequence adjusts the panel scroll region width in the global config object g_Config ([.data+0x1c00]). The fields involved are: Field g_Config offset Role panel_ptr +0x15D8 Pointer to the active ImGui panel/window struct scroll_step +0x0E0C Per-frame scroll delta (float, typically a small positive value) scroll_accum +0x194 Accumulated horizontal scroll position (float) scroll_base +0x58 Base horizontal offset for child panels (float) scroll_total +0x198 Total scroll range (float) panel_width +0x150 Rendered panel content width (float, written each frame) // Panel-open sequence (addss — widens panel each frame module is visible) rax = g_Config->panel_ptr; rax->field_0x103 = 1; // mark panel as active/dirty rax = g_Config->panel_ptr; xmm0 = g_Config->scroll_step; // [g_Config+0x0E0C] xmm0 += rax->scroll_accum; // [panel+0x194] rax->scroll_accum = xmm0; xmm0 += rax->scroll_base; // [panel+0x58] xmm0 += rax->scroll_total; // [panel+0x198] rax->panel_width = xmm0; // [panel+0x150] — expand // Panel-close sequence (subss — narrows panel each frame module is hidden) rax = g_Config->panel_ptr; rax->field_0x103 = 1; rax = g_Config->panel_ptr; xmm0 = rax->scroll_accum; // [panel+0x194] xmm0 -= g_Config->scroll_step; // [g_Config+0x0E0C] rax->scroll_accum = xmm0; xmm0 += rax->scroll_base; xmm0 += rax->scroll_total; rax->panel_width = xmm0; // shrink This pattern appears verbatim in every module's Render body and is not repeated in the per-module pseudocode below — it is implied by 'panel-open sequence' and 'panel-close sequence'.

12.2 NoClip

Function RVA Role NoClip::RegisterTab 0x180081300 One-time tab registration (Render stub #1) NoClip::Render 0x1800813D0 ImGui tab panel — checkbox + Move Speed slider NoClip::Update 0x180089B50 Per-frame: CharacterController.enabled toggle + speed slider NoClip::Update stub 0x180089B00 Tab-manager destructor/cleanup wrapper NoClip disables/re-enables the Unity CharacterController component on matching entities each frame. When enabled the controller's collision is suppressed, allowing the player to pass through geometry. A Move Speed integer slider ([module+0x30], range 1–10, step 1) controls movement rate while noclip is active. // NoClip::Render RVA 0x1800813D0 // rcx = NoClip* this void NoClip::Render() { // Panel-open sequence (g_Config+0x1c00, +0x15D8/0xE0C/0x194/0x58/0x198/0x150) std::string title = MakeString("NoClip", 6); // 0x18000FCB0 std::string tmp; bool open = TabManager_BeginTab([.data+0x27B0], &tmp, &title); // 0x18009D7D0 // resolve std::string to char* via SSO check (cmp [rax+0x18], 0xF) bool clicked = ImGui_Toggle(buf, false); // 0x180070820 — returns true if clicked // free tmp, title if (!clicked) { panel-close sequence; return; } // Panel-open sequence // second tab header: 'ON / OFF' bool on_off_clicked = TabManager_BeginTab([.data+0x27B0], &tmp, &title); // resolve buf, call 0x180085320 (CheckboxToggle) with &this->enabled [+0x28] // CheckboxToggle: if edx (new_val) != rdx (current), flip and update // Panel-open/close based on [this+0x28] if ([this+0x28] enabled) { // 'Move Speed' DragInt slider: [this+0x30], range [1,10], step 1, format '%d' // 0x180066750 — ImGui::DragInt4-variant panel-open sequence; } else { panel-close sequence; } } // NoClip::Update RVA 0x180089B50 // Called per-frame by ModuleManager hook void NoClip::Update() { // Same 'NoClip' tab header + ON/OFF checkbox pattern as Render if (!clicked) return; panel-open sequence (if enabled) 'Move Speed' DragInt slider — same as Render, writes [this+0x30] // Entity iterator loop (0x180089DC0) bool noclip_on = [this+0x28]; void entity_mgr = g_Config->GetEntityManager(); // [g_Config+0x1D28] — IL2CPP call if (!entity_mgr) return; void* list = entity_mgr->GetComponentList(); // [entity_mgr+0x10]->field_0x10 int count = list->count; // [list+0x20] void** arr = list->items; // [list+0x10][+0x10] arr += 0x20; // skip header slots for (int i = 0; i < count; i++, arr++) { void* component = arr; if (!component) continue; void ctrl = GetCharacterController(component); // [g_Config+0x1E20] IL2CPP call if (!ctrl) continue; // CharacterController.set_enabled(!noclip_on, 0) // [g_Config+0x1E08]: IL2CPP setter — dl = !noclip_on, r8d = 0 bool enable_cc = !noclip_on; SetEnabled(ctrl, enable_cc, 0); // 0x1803C6E08 } // Move Speed DragInt — panel sequence at close }

12.3 FreeCam

Function RVA Role FreeCam::RegisterFpsTab 0x1800814C0 Registers FPS Monitor overlay tab FreeCam::RegisterMainTab 0x180081590 Registers FreeCam main tab (0xD8-byte zeroed state) FreeCam::FpsUpdate stub 0x180087150 FPS overlay destructor wrapper; tab cleanup FreeCam::Update 0x1800871A0 Per-frame: camera override, WASD+mouse input, speed sliders FreeCam overrides the game camera's transform each frame when enabled. RegisterMainTab zeroes a 0xD8-byte state block in .data ([.data+0x2200]) and writes hard-coded default key bindings (0x44415357 = 'WASD', 0x6D6BA220, 0x2725, 0x60) and clears floats for pitch/yaw/roll/FOV accumulators. It also clears an 8-byte 'active camera' pointer and related state. Move Speed defaults to 30.0f (0x41F00000 IEEE 754), step 0.1f (0x3DCCCCCD). Look Sensitivity defaults to 100.0f (0x42C80000), step 0.1f (0x3DCCCCCD). Roll Speed ([this+0x34]) and FOV Speed ([this+0x38]) have dedicated sliders with format '%.3f'. // FreeCam::RegisterMainTab RVA 0x180081590 // Runs once at DLL init; zeroes FreeCam state block and writes defaults void FreeCam::RegisterMainTab() { // Zero [.data+0x2200] block (0xD8 bytes via memset-like call 0x1800AC86A) std::string tab = MakeString("FreeCam", 7); // register tab with TabManager (0x18000F7D0), clear active flag, free strings // Write update fn ptr: [.data+0x2200] = 0x1803AFE10 → FreeCam::Update // Write default key bindings to [.data+0x2230..0x225E]: // movdqa [+0x2230] = [0x1803B34F0] (key config block 1) // movdqa [+0x2240] = [0x1803B35C0] (key config block 2) // [+0x2250] = 0x3F800000 (1.0f — FOV multiplier default) // [+0x2254] = 0x44415357 ('WASD' key code mask) // [+0x2258] = 0x6D6BA220 (additional keybind data) // [+0x225C] = 0x2725 (two-byte keybind) // [+0x225E] = 0x60 (backtick key code) // Zero floats: pitch/yaw/roll/FOV [+0x2260..0x22A8], camera ptr [+0x22B0..0x22D0] } // FreeCam::Update RVA 0x1800871A0 void FreeCam::Update() { std::string hdr = MakeString("Free Camera", 11); bool open = TabManager_BeginTab(&tmp, &hdr); bool clicked = ImGui_Toggle(buf, false); if (!clicked) { panel-close sequence; return; } panel-open sequence; // ON/OFF checkbox → [this+0x28] bool on_off = TabManager_BeginTab(...); CheckboxToggle(&this->enabled, ...); // 0x180085320 if (!this->enabled) { // Disable camera override: clear active cam ptr [this+0x70] and [this+0x68] // [g_Config+0x1DB8]: IL2CPP Camera.set_enabled(false/true calls) Camera_SetEnabled([this+0x70], false, 0); // 0x1803C6DB8 Camera_SetEnabled([this+0x68], true, 0); [this+0xB8] = 0; // clear 'cam override active' flag panel-close sequence; return; } // Move Speed float slider: [this+0x30], max 500.0f, min 0.1f, fmt '%.3f' // 0x180065570 — ImGui::SliderFloat8 variant (8 = DragFloat with extra params) // [rsp+0x40]=500.0f (max), [rsp+0x48]=0.1f (min), xmm3=step // Roll Speed float slider: [this+0x34], max 100.0f (0x42C80000), min 0.1f // Look Sensitivity float slider: [this+0x38]? (identified from 'FOV Speed' string) // (Three consecutive float sliders: Move Speed, Roll Speed, FOV Speed) // Key input + camera transform written via IL2CPP calls on camera component // (Camera.get_main, Transform.set_position, Transform.set_rotation via vtable) }

12.4 FpsUnlocker

Function RVA Role FpsUnlocker::RegisterTab 0x180081730 Registers 'Fps Unlocker' tab; writes default fps=300 ([.data+0x21E8]) FpsUnlocker::Render 0x180085B90 ImGui panel: checkbox + Fps Value DragInt, calls Application.targetFrameRate FpsUnlocker::Update stub 0x180085B40 Tab destructor/cleanup wrapper; cleanup size 0x38 FpsUnlocker calls the IL2CPP Application.set_targetFrameRate setter ([.data+0x1D48]) on every Render call (not per-frame Update). When the checkbox is off, it passes 60 (0x3C) as the frame rate. When on, it passes [this+0x30] — the user's chosen value. A Fps Value DragInt slider ([this+0x30], max 500, min 30, step 1, format '%d') is displayed in a second tab header. RegisterTab writes a default of 300 (0x12C) to the .data slot backing [this+0x30]. // FpsUnlocker::Render RVA 0x180085B90 void FpsUnlocker::Render() { std::string hdr = MakeString("Fps Unlocker", 12); bool open = TabManager_BeginTab([.data+0x27B0], &tmp, &hdr); bool clicked = ImGui_Toggle(buf, false); if (!clicked) { panel-close sequence; return; } panel-open sequence; // First action on open: call Application.set_targetFrameRate // (regardless of enabled state — immediate effect) int fps_val = this->enabled ? this->fps_target : 60; Application_SetTargetFrameRate(fps_val); // [.data+0x1D48] IL2CPP // ON/OFF checkbox → CheckboxToggle([this+0x28]) if (this->enabled) { panel-open sequence; // 'Fps Value' DragInt: [this+0x30], max=500, min=30, step=1, fmt='%d' // 0x180065570 ImGui::DragInt variant // On each interaction: call Application.set_targetFrameRate([this+0x30]) // ... then subss panel-close sequence } else { // panel-close sequences x2 (one per BeginTab call) } }

12.5 SetDither

Function RVA Role SetDither::RegisterTab 0x180081810 Registers 'SetDither' tab; stores update ptr 0x1803B01B0 → stub 0x180083DC0 SetDither::Render 0x180081810 Identical to RegisterTab (same address — no separate Render body) SetDither::Update 0x180083DC0 No-op stub: frees string [this+0x8], optionally operator delete(this, 0x30) SetDither is the simplest module. Its registration function and Render body coincide at the same RVA — the 'tab' it registers has no interactive widgets beyond the standard tab header registration. The stored update pointer leads to the shared no-op stub at 0x180083DC0. The stub frees a std::string at [rcx+0x8] then, if the dirty bit (bl & 1) is set, calls operator delete on the module pointer with size 0x30. There is no per-frame game-state write associated with SetDither in this binary; the feature is either not yet implemented or was stripped before release. // SetDither::RegisterTab / Render RVA 0x180081810 void SetDither::RegisterTab() { std::string hdr = MakeString("SetDither", 9); // Register tab with TabManager (0x18000F7D0) // Write update fn ptr: [.data+0x2180] = 0x1803B01B0 → 0x180083DC0 (stub) // Cleanup string, return [.data+0x2180] } // Shared no-op Update stub RVA 0x180083DC0 // Used by SetDither, FreeCam FPS overlay, and SkillHack 'Free Skill' tab void* NoOpUpdateStub(void* this_ptr, BOOL dirty) { std::string& s = (std::string)((char*)this_ptr + 8); std::string_destroy(&s); // 0x18000FA60 if (dirty & 1) { operator_delete(this_ptr, 0x30); // 0x1800AB758 } return this_ptr; }

12.5.1 SetDither::RenderOverlay (RVA 0x8C4A0)

SetDither::RenderOverlay is a separate callable entry point distinct from RegisterTab. It is invoked by the ModuleManager render loop on every Present() frame. The function (0x8C4A0–0x8C70D, 621 bytes) draws the “Set Dither” (i18n key RVA 0x3B0198) panel inside the main cheat overlay. Its control flow follows the standard module pattern: // SetDither::RenderOverlay RVA 0x18008C4A0 void SetDither::RenderOverlay(SetDither* this) { // Tab guard: i18n lookup for "Set Dither" key (RVA 0x3B0198, 10 chars) std::string tabName = i18n_lookup("Set Dither"); // 0x18000FCB0 bool open = TabManager_BeginTab(tabName, g_locale); // 0x18009D7D0 if (!open) { string_destroy(tabName); return; } // Panel-open: addss [g_Config+0x15D8]+0x194 with [g_Config+0xE0C] g_Config->panel_state->height += g_Config->dither_panel_height; // expand // "ON / OFF" toggle bound to [this+0x28] (dither_enabled BOOL) std::string label = i18n_lookup("ON / OFF"); // RVA 0x3AF848, 8 chars DitherToggle(label, &this->dither_enabled); // 0x180085320 (rcx=label, rdx=&[rsi+0x28]) // Panel-close: subss restores height g_Config->panel_state->height -= g_Config->dither_panel_height; } The singleton state block for SetDither is accessed via [g_Config+0x15D8] (pointer to the active game state node at runtime). The field [this+0x28] is the dither_enabled BOOL; the DitherToggle helper at 0x180085320 is the same ImGui toggle helper used by other modules. The “ON / OFF” i18n label at RVA 0x3AF848 distinguishes this from the other modules which use a module-name toggle pattern.

12.6 PlayerProfile

Function RVA Role PlayerProfile::RegisterTab 0x1800818E0 Registers tab, zeroes two std::string fields, stores IL2CPP find fn ptrs PlayerProfile::Render 0x1800818E0 Same RVA — tab registration IS the render registration PlayerProfile::Update 0x18008A4F0 Per-frame: UI node traversal, SetText on two TMP labels, Name Changer input PlayerProfile::Update stub 0x18008A4A0 Destructor wrapper: frees [this+0x50], [this+0x30], [this+0x8], delete(0x78) PlayerProfile resolves two Unity UI node paths each frame when enabled. The first path '/UINode/UIRoot/UIDPanelPanel/Main/TextNode/Text' (RVA 0x3AFED0, len 0x2F) finds the UID display TextMeshProUGUI component and overwrites its text with the content of [this+0x30] (an internal std::wstring). The second path '/UINode/WorldUIRoot/WatchPanel/Content/WatchNode/canvas_watch/LeftBottomNode/PlayInfoPosNode/PlayInfoLifengCell(Clone)/PlayerInfo/ManagerName' (RVA 0x3AFFD0, len 0x8D) finds the name label and overwrites it with [this+0x50]. A 'UID text' input box and a 'Name text' input box are shown in the panel. A 'Name changer' checkbox ([this+0x70]) enables the ManagerName write. RegisterTab zeroes both std::string fields via 0x18000FFF0 (wstring init) and stores find-by-path and get-component IL2CPP function pointers. // PlayerProfile::Update RVA 0x18008A4F0 void PlayerProfile::Update() { std::string hdr = MakeString("PlayerProfile", 13); bool open = TabManager_BeginTab(...); bool clicked = ImGui_Toggle(buf, false); if (!clicked) { panel-close sequence; return; } panel-open sequence; CheckboxToggle(&this->enabled, ...); // ON/OFF → [this+0x28] if (this->enabled) { // Resolve UID text node std::string path1 = "/UINode/UIRoot/UIDPanelPanel/Main/TextNode/Text"; void* uid_node = IL2CPP_FindByPath(path1); // 0x18009BCB0 if (uid_node) { // Get TextMeshProUGUI component void* tmp_comp = GetComponent(uid_node, "TextMeshProUGUI"); if (tmp_comp) { // SetText(tmp_comp, 0, this->uid_wstring) — [g_Config+0x1E28] SetText(tmp_comp, 0, &this->uid_str); // 0x1803C6E28 } } // Resolve second name node (for first name label) // Same pattern: path → find → GetComponent → SetText // 'UID text' InputText: writes [this+0x30] (displayed uid string) // call 0x18008AC20 — InputText_wstring wrapper // 'Name text' InputText: writes [this+0x50] (player name buffer) // 'Name changer' checkbox → [this+0x70] if (this->name_changer_enabled) { // [this+0x70] // Resolve ManagerName node via long world path void* name_node = IL2CPP_FindByPath( "/UINode/WorldUIRoot/WatchPanel/.../ManagerName"); if (name_node) { void* tmp_comp = GetComponent(name_node, "TextMeshProUGUI"); if (tmp_comp) { SetText(tmp_comp, 0, &this->name_str); // [this+0x50] wstring } } } } panel-close sequence; }

12.7 Vacuum

Function RVA Role Vacuum::RegisterTab 0x180081A20 Registers 'Vacuum' tab, stores update fn ptr 0x1803B0680 → 0x180085B40 stub Vacuum::Render 0x180093CA0 ImGui panel: 'Vacuum' checkbox + 'Monster' sub-checkbox; panel-width logic Vacuum::PhysicsLoop 0x180093F10 Per-frame Rigidbody.AddForce attraction loop over entity list Vacuum::Update stub 0x180085B40 Destructor wrapper: frees [this+0x8], optionally delete(0x38) Vacuum renders two checkboxes: 'Vacuum' ([this+0x28]) and 'Monster' ([this+0x30]). The physics loop at 0x180093F10 runs each frame when any vacuum flag is active. It obtains the camera's position via IL2CPP (Camera.main → transform → position), then iterates all rigidbody entities and applies an AddForce call that pulls each toward the camera origin. The force vector is computed per-entity as: forceX = (entity.x × attractStrength) + camera.x, forceY similarly, forceZ similarly, where attractStrength (xmm8) is loaded from [.rdata+0x1803B32B4] — a compile-time constant. The 'Monster' flag controls whether monster-type entities are included in the iteration. // Vacuum::Render RVA 0x180093CA0 void Vacuum::Render() { std::string hdr = MakeString("Vacuum", 6); bool open = TabManager_BeginTab(...); bool clicked = ImGui_Toggle(buf, false); if (!clicked) { panel-close sequence; return; } panel-open sequence; // 'Vacuum' checkbox: CheckboxToggle(&this->vacuum_on [+0x28]) // 'Monster' checkbox: CheckboxToggle(&this->monster_on [+0x30]) // — Monster sub-checkbox uses panel-open/subss sequence at 0x180093EAC } // Vacuum::PhysicsLoop RVA 0x180093F10 (called from physics hook each frame) // rcx = Vacuum* this, xmm1 = attract_vector, r8 = entity_array void Vacuum::PhysicsLoop(void* this_ptr, vec3 attract_vec, void** entities) { if (!this->vacuum_on) return; // [this+0x30] // Get camera position void* cam_mgr = g_Config->GetCameraManager(); // [g_Config+0x1D28] if (!cam_mgr) return; void* main_cam = cam_mgr->GetMainCamera(); // [g_Config+0x1CF0] void* cam_rb = main_cam->GetRigidbody(); // [g_Config+0x1D60] void* cam_pos = cam_rb->GetPosition(0); // [g_Config+0x1DC8] // cam_pos struct: {double x, double y, int z_int, ...} double cam_x = cam_pos->x; double cam_y = cam_pos->y; int cam_z = cam_pos->z_int; float attract = (float)0x1803B32B4; // compile-time attraction constant // Iterate entity array (from Vacuum::Update inner call 0x180094000) for each entity in entities { if (!entity) continue; void* rb = GetRigidbody(entity); // [g_Config+0x1DF8] if (!rb) continue; vec3 pos = rb->GetPosition(0); // [g_Config+0x1D18] vec3 force; // Get entity world position void* rb2 = GetEntityRoot(entity); // [g_Config+0x1D60] vec3 rb2pos = rb2->GetWorldPos(0); // [g_Config+0x1DC8] vec3 rb2pos2 = rb2->GetAltPos(0); // [g_Config+0x1DA8] vec3 rb3pos = rb2->GetFwd(0); // [g_Config+0x1D90] // force = attract * rb3pos + camera_pos (component-wise) force.x = rb3pos.x * attract + cam_x; force.y = rb3pos.y * attract + cam_y_component; force.z = rb3pos.z * attract + cam_z_component; // Rigidbody.AddForce(rb, &force, ForceMode=0) [g_Config+0x1E00] AddForce(rb, &force, 0); } }

12.8 SkillHack::Render — Complete Panel Body

Function RVA Role SkillHack::Render 0x18008D1F0 Hook installer entry: installs six IL2CPP hooks, then falls to panel fn SkillHack::RenderPanel 0x18008D240 ImGui panel: 'Free Skill' checkbox + ON/OFF toggle + panel-width sequence SkillHack::Update 0x180083DC0 No-op stub (shared with SetDither — no per-frame game write) SkillHack::Dispatcher 0x18008D4B0 BOOL hook callback: returns 1 when [SkillHack+0x28] is set SkillHack::CooldownBypass 0x18008D500 float hook callback: returns 100.0f when enabled SkillHack::AvailBypass 0x18008D640 BOOL hook callback: returns 1 when enabled SkillHack::CostBypass 0x18008D780 void hook callback: early-return (skip cost deduction) when enabled SkillHack::Render at 0x18008D1F0 is a pure hook-installation function — it does not itself draw any ImGui widgets. It installs the six IL2CPP hooks (documented in Section 10) and then tail-jumps to 0x18008D8A0 (the CreateHook wrapper / EnableHook dispatcher). The actual ImGui panel rendering is at 0x18008D240, referenced via the .rdata tab-callback pointer chain. That panel body contains the standard 'SkillHack'/'Free Skill' tab header pair followed by the ON/OFF checkbox and the full panel-width sequence. // SkillHack::Render RVA 0x18008D1F0 — hook installer, NOT the ImGui panel void SkillHack::Render() { // Install hooks on six IL2CPP function pointers (see Section 10) InstallHook(g_Config->il2cpp_fn[0x1E60], &Dispatcher); // 0x18008D8A0 InstallHook(g_Config->il2cpp_fn[0x1E68], &Dispatcher); InstallHook_CooldownBypass(); // 0x18008E220 → 0x18008D500 InstallHook_AvailBypass(); // 0x18008EBC0 → 0x18008D640 InstallHook_CostBypass(); // 0x18008F560 → 0x18008D780 InstallHook(g_Config->il2cpp_fn[0x1E48], &Dispatcher); // tail jmp } // SkillHack::RenderPanel RVA 0x18008D240 — actual ImGui panel void SkillHack::RenderPanel() { // Tab header: 'Free Skill' (10 chars) via TabManager_BeginTab bool clicked = ImGui_Toggle(buf, false); // 0x180070820 if (!clicked) { panel-close sequence; return; } panel-open sequence; // Second tab: 'ON / OFF' bool on_off = TabManager_BeginTab(..., &tmp_str, ...); CheckboxToggle(&this->enabled, ...); // 0x180085320 → [this+0x28] if (this->enabled) { panel-open sequence; // addss path // (no additional sliders or sub-widgets beyond the toggle) } else { panel-close sequence; // subss path } // All six hook callbacks read [SkillHack_singleton+0x28] at call time // — no deferred write needed here }

12.9 Module Render/Update Address Summary

Module RegisterTab RVA Render RVA Update RVA Update type Key field offsets NoClip 0x181300 0x1813D0 0x189B50 Per-frame entity loop [+0x28] enabled, [+0x30] move_speed (int) FreeCam 0x181590 0x1871A0 0x1871A0 Per-frame camera override [+0x28] enabled, [+0x30] move_speed (float), [+0x34] roll_spd, [+0x38] fov_spd, [+0x68/70] cam ptrs FpsUnlocker 0x181730 0x185B90 stub/none Render-time only [+0x28] enabled, [+0x30] fps_target (int, default 300) SetDither 0x181810 0x181810 stub/none No-op [+0x28] enabled (unused) PlayerProfile 0x1818E0 0x18A4F0 0x18A4F0 Per-frame UI path walk [+0x28] enabled, [+0x30] uid_str, [+0x50] name_str, [+0x70] name_changer Vacuum 0x181A20 0x193CA0 0x193F10 Per-frame AddForce loop [+0x28] vacuum_on, [+0x30] monster_on SkillHack N/A 0x18D1F0 stub/none No-op (hook callbacks handle IL2CPP) [+0x28] enabled (read by all 6 callbacks)

13. Gap Closure Status

Gap Status Volume Resolved Notes Module Update() bodies COMPLETE Ch. 22 ESPModule::Update completed in Ch. 22; all others in Ch. 12 Module Render() bodies COMPLETE Ch. 22 ESPModule::RenderOverlay completed in Ch. 22; all others in Ch. 12 ModuleManager main loop COMPLETE Ch. 15 Present hook + module dispatch; see Ch. 15 GABypass IL2CPP patching COMPLETE Ch. 18 71 function pointers patched; see Ch. 18 Config file I/O COMPLETE Ch. 6 UTF-8→wide→_wfopen, 'rb'/'wt' DLL injection (testyip/gatmp) COMPLETE Ch. 11 Temp file injection pattern; see Ch. 11 Thread enumeration COMPLETE Ch. 3 Toolhelp32 snapshot loop; see Ch. 3 Anti-debug checks COMPLETE Ch. 4 MSVC CRT only, no active anti-debug; see Ch. 4 Shader compilation COMPLETE Ch. 5 Two ImGui HLSL shaders, vs/ps 4_0 SetWindowDisplayAffinity COMPLETE Ch. 21 PreventScreenshot registered module; full analysis in Ch. 21 ImGui integration COMPLETE Ch. 12 Win32+D3D11 backends; see Ch. 12. Overlay window init (DPI, CreateWindowExW, D3D11CreateDeviceAndSwapChain, message loop, FindGameWindow, GetOverlayRect) see Ch. 29 Exception handling COMPLETE Ch. 4 MSVC __security_check_cookie; see Ch. 4 JSON parsing COMPLETE Ch. 19 Full schema, save/load path, and IAT traced; see Ch. 19

14. Definitive Function Address Table

Complete map of all significant functions identified across all twenty-five chapters: Function / Purpose VA Start VA End Key Operations DllMain 0x180001000

Entry point, spawns loader thread LoaderThread 0x180005000

Init IL2CPP, create window, Present hook ModuleManager::RegisterAll 0x18009AE00

11 modules registered via stubs ModuleManager::MainLoop 0x180082000 0x180082300 Present hook, ImGui render loop D3D11Init (shaders) 0x180054DC0 0x1800551E8 2× D3DCompile, create D3D resources ImGui Win32+D3D11 Setup 0x180082500

Backend init, WndProc subclass CollectProcessThreads 0x1800A96B0 0x1800A9A1C Toolhelp32 thread enumeration SuspendOrResumeThreads 0x1800A9A20 0x1800A9A98 OpenThread + Suspend/Resume PatchCode 0x1800A9A9C 0x1800A9BC3 VirtualProtect + write hook bytes HookManager::Install 0x1800A9CC8

Alloc trampoline + FNV hash HookManager::Remove 0x1800A9E8C

Remove and restore bytes HookManager::Enable 0x1800A9A9C

Toggle enabled bit + patch GABypass::Init 0x18009D1E0

CharacterController enable toggle SkillHack::Render 0x18008D1F0

IL2CPP hook installer FreeCam::Render 0x180087150

CinemachineBrain override FpsUnlocker::Render 0x180085B80

Application.targetFrameRate SetDither::Render 0x18008C490

Graphics dither toggle PlayerProfile::Render 0x18008A4A0

Unity UI text manipulation Vacuum::Render 0x180093C90

Monster item collection ESPModule::Render 0x180083F60

See Ch. 22 (§22.1) DamageHack (ghost) N/A (no code)

Ghost feature — no code; see Ch. 23 PreventScreenshot 0x18008B490

SetWindowDisplayAffinity ESPModule::DrawOverlay 0x180083000

See Ch. 22 (§22.2) WndProc 0x1800826A0

Win32 message + WM_SIZE/DESTROY handler; see Ch. 7 SkillHack::Dispatcher 0x18008D4B0

Generic hook dispatcher (2 hooks); see Ch. 10 SkillHack::FloatReturn 0x18008D500

Hook cb: return 100.0f (float skills); see Ch. 10 SkillHack::BoolTrue 0x18008D640

Hook cb: return true (bool checks); see Ch. 10 SkillHack::VoidReturn 0x18008D780

Hook cb: early void return; see Ch. 10 SkillHack::TrampolineDispatch 0x18008FF00

Common trampoline dispatcher; see Ch. 10 ModuleManager::Init 0x18009AC10

Construct + register all modules; see Ch. 15 ModuleManager::DispatchRender 0x18009AE80

Per-frame Render() dispatch loop; see Ch. 15 ModuleManager::DispatchHotkeys 0x18009AEF0

Per-frame hotkey dispatch; see Ch. 15 ModuleManager::DispatchRegInit 0x18009AF60

Registrar init dispatcher; see Ch. 15 ModuleManager::PresentHook 0x180082F00

D3D11 Present hook; calls Render+Hotkey loops; see Ch. 15 ModulePathScanner 0x18008B650

Scans loaded modules for testyip/gatmp/EF-Cheeto; see Ch. 11 HookInstallerWrapper 0x18008BAF0

Wraps CreateHook; validates target ptr; see Ch. 11 StartupSequence 0x1800A9190

DLL loader startup context; see Ch. 11 ESPModule::Init 0x180083E00

Lazy singleton init; sets color defaults; see Ch. 9 ESPModule::RenderOverlay 0x180083FA0 0x18008499E ImGui ESP panel (full); see Ch. 22 ESPModule::Update 0x180084A00 0x1800852A5 Entity label draw loop; see Ch. 22 FPSModule::Initialize 0x1800814C0

once_flag guarded init; see Ch. 20 FPSModule::RenderOverlay 0x180085700 0x180085900 FPS panel + overlay counter; see Ch. 20 PreventScreenshot::Initialize 0x18008AD70

once_flag guarded init; see Ch. 21 PreventScreenshot::Render 0x18008AE60

ImGui checkbox; see Ch. 21 PreventScreenshot::Update 0x18008AFC0

SetWindowDisplayAffinity dispatch; see Ch. 21 PreventScreenshot::OsCheck 0x18008B220

Win10 build check + affinity call; see Ch. 21 UnityExplorer::RegisterTab 0x180090060

Tab init, scene hierarchy setup; see Ch. 16 UnityExplorer::Render 0x180090250

Per-frame scene inspector; see Ch. 16 UnityExplorer::RefreshScenes 0x180090D40

Scene list refresh helper; see Ch. 16 HookManager::Spinlock 0x1800A9C88

Spinlock acquire/release; see Ch. 8 WideToString 0x18000EB10

UTF-8 path to wstring for wcsstr; see Ch. 11 FreeCam::RegisterTab 0x18000F7D0

Registers FreeCam main tab; see Ch. 12 BaseModule::Dtor 0x18000FA60

Shared dtor: destroy name string + optional delete; see Ch. 12 NoClip::RegisterTab 0x18000FCB0

Registers NoClip tab; stores update fn ptr; see Ch. 12 ManagerName::Init 0x18000FFF0

Zeroes std::string fields for ModuleManager name; see Ch. 15 ConfigSerialize 0x180012050

Serialize config struct to string for fwrite; see Ch. 6 ImGui::EndFrame 0x18001C2D0

D3D11/ImGui frame boundary EndFrame call; see Ch. 15 BuildFilePath 0x180030A90

Build config file path string from state+0x50; see Ch. 6 D3D11::CreateBuffers 0x1800551F0

Create vertex/index buffers post shader compile; see Ch. 5 ImGui_ImplWin32_WndProcHandler 0x180057720

ImGui Win32 WndProc message handler; see Ch. 7 FreeCam::SliderFloat 0x180065570

Move Speed SliderFloat (max 500.0f); see Ch. 12 FreeCam::DragInt 0x180066750

Move Speed DragInt (range 1-10); see Ch. 12 TabManager::BeginTab 0x180070820

ImGui tab begin + toggle helper; see Ch. 12 ImGui::Selectable 0x1800708D0

Preset selector; Per-Config preset writer dispatch; see Ch. 17 SkillHack::GetSingleton 0x180081300

Lazy once_flag singleton init for SkillHack; see Ch. 10 NoClip::Render 0x1800813D0

ImGui panel: checkbox + Move Speed slider; see Ch. 12 FPSModule::RegisterTab 0x180081590

Registers FPS Monitor overlay tab; see Ch. 20 FpsUnlocker::RegisterTab 0x180081730

Registers Fps Unlocker tab; see Ch. 12 SetDither::RegisterTab 0x180081810

Registers SetDither tab; stores update ptr; see Ch. 12 PlayerProfile::RegisterTab 0x1800818E0

Registers PlayerProfile tab; see Ch. 12 Vacuum::RegisterTab 0x180081A20

Registers Vacuum tab; stores update fn ptr; see Ch. 12 HookManager::GetSingleton 0x180081B00

Thread-safe static singleton init for HookManager; see Ch. 8 NoOpUpdateStub 0x180083DC0

Shared no-op Update stub (SetDither, SkillHack free); see Ch. 12 ESPModule::CheckboxToggle 0x180085320

Toggle checkbox helper used in ESPModule panel; see Ch. 22 NoClip::EntityIterator 0x180089DC0

Entity iterator loop inner call; see Ch. 12 InputText::WString 0x18008AC20

ImGui InputText wrapper for wstring fields; see Ch. 12 SkillHack::InstallHooks 0x18008D8A0

Installs 3 hooks via HookInstallerWrapper; see Ch. 10 SkillHack::PatchFloat 0x18008E220

Installs FloatReturn hook on [g_Config+0x1E50]; see Ch. 10 SkillHack::PatchBool 0x18008EBC0

Installs BoolTrue hook on [g_Config+0x1E58]; see Ch. 10 SkillHack::PatchVoid 0x18008F560

Installs VoidReturn hook on [g_Config+0x1E40]; see Ch. 10 UnityExplorer::GuardReturn 0x1800901D8

Early return after once_flag sealed; see Ch. 16 ImGui::Begin 0x1800937D0

ImGui::Begin wrapper (Unity Explorer Window); see Ch. 16 UnityExplorer::AutoRefresh 0x180093B10

Auto-refresh timer check for scene list; see Ch. 16 Vacuum::PhysicsLoop 0x180093F10

Per-frame entity attraction physics loop; see Ch. 12 PlayerProfile::FindUINode 0x18009BCB0

IL2CPP_FindByPath for UI text/UID node; see Ch. 12 TabManager::BeginTabFull 0x18009D7D0

Full BeginTab with state+title resolution; see Ch. 12 HookManager::FreeSlot 0x1800AA684

Free trampoline + compact hook array; see Ch. 8 WideStr::wcsstr 0x1800AB6A0

Custom wcsstr for wide path scanning; see Ch. 11 WideStr::Dtor 0x1800AB758

wstring destructor in path scanner; see Ch. 11 HotkeyErrorHandler 0x1800AECE0

Hotkey error handler, logs '[hotkey error]'; see Ch. 7 std::once_flag::Execute 0x1800AFF60

MSVC once_flag _Execute_once; used by UnityExplorer; see Ch. 16 D3D11::Reinit 0x1800825B0

Recreate D3D11 render target+shaders on WM_SIZE; see Ch. 7 ModuleManager::RenderFrame 0x180082FC0

ImGui NewFrame + per-module Render dispatch; see Ch. 15 FpsUnlocker::UpdateStub 0x180085B40

Tab destructor/cleanup wrapper for FpsUnlocker; see Ch. 12 FpsUnlocker::Render 0x180085B90

ImGui panel: FPS cap checkbox + DragInt; see Ch. 12 FreeCam::Update 0x1800871A0

Per-frame: CinemachineBrain camera override; see Ch. 12 NoClip::UpdateStub 0x180089B00

Tab destructor/cleanup wrapper for NoClip; see Ch. 12 NoClip::Update 0x180089B50

Per-frame: CharacterController.enabled toggle; see Ch. 12 PlayerProfile::Update 0x18008A4F0

Per-frame: UI node traversal + text injection; see Ch. 12 UTF8ToWide 0x18008B4E0

MultiByteToWideChar wrapper for path conversion; see Ch. 11 ModulePathScanner::EFSearch 0x18008B937

wcsstr branch: search for EF-Cheeto.dll in path; see Ch. 11 SkillHack::RenderPanel 0x18008D240

ImGui panel body after hook install; see Ch. 10 Vacuum::Render 0x180093CA0

ImGui panel: Vacuum checkbox + monster sub-checkbox; see Ch. 12 Vacuum::EntityIterator 0x180094000

Inner entity array iteration for item vacuum; see Ch. 12 HookManager::AllocTrampoline 0x1800A960C

Allocate trampoline slot near target VA; see Ch. 8 UnityExplorer::MemsetBlock 0x1800AC86A

Memset 0xD8 bytes at [.data+0x2200] during init; see Ch. 16

15. ModuleManager Dispatch Architecture

Source file: E:\git\Endfield_Cheeto\libraries\pipeline\modules\ModuleManager.cpp (string at RVA 0x3B0BC0). The ModuleManager is the central runtime controller responsible for: (1) maintaining the registrar list, (2) constructing module instances during Init, (3) dispatching per-frame Render calls from the D3D11 Present hook, and (4) dispatching per-frame hotkey processing.

15.1 Key Data Structures

ModuleManager object layout (rcx in all dispatch calls): struct ModuleManager { BaseModule** instances_begin; // [+0x00] begin ptr (vector<BaseModule*>) BaseModule** instances_end; // [+0x08] end ptr BaseModule** instances_cap; // [+0x10] capacity ptr bool initialized; // [+0x18] set to 1 after Init() completes // [+0x19..+0x1F] padding // [+0x20..+0x57] registrar list (vector — 0x60-byte stride elements) }; Global singleton pointers in .data: [.data+0x23B8] ModuleManager.instances_begin (registrar slots array begin) [.data+0x23C0] ModuleManager.instances_end [.data+0x23C8] ModuleManager.instances_cap [.data+0x2398] ModuleManager object ptr (passed as rcx to dispatch loops) [.data+0x23A8] secondary ptr (capacity end) BaseModule vtable layout (confirmed from factory stubs at 0x9B660–0x9B7A0 and dispatch call sites): Slot Offset Description Notes [0] +0x00 copy-ctor/factory() placement-new style ctor; writes vtable ptr, returns this [1] +0x08 copy-ctor/factory() same as [0] [2] +0x10 Init()/RegisterTab() jmp stub -> actual RegisterTab fn for the module [3] +0x18 Render() per-frame UI + game-state dispatch — called by Present hook loop [4] +0x20 ~BaseModule() destructor: frees name string, conditional operator delete [5] +0x28 getNamePtr() returns &this->name_string (this+0x08) [6] +0x30 onHotkey() pure virtual (value = 1 sentinel); not implemented in any module [7] +0x38 getLinkedModuleFactory() returns factory ptr for a paired module (e.g. FpsOverlay) BaseModule instance layout (from dispatch loop field access and RegisterTab writes): struct BaseModule { void* vtable; // [+0x00] std::string name; // [+0x08] SSO string (24 bytes) std::string tab_name; // [+0x20] secondary name / tab label bool enabled; // [+0x28] ON/OFF flag — checked by dispatch loops // [+0x29..+0x2F] padding // [+0x30..] module-specific fields (move_speed, fps_target, etc.) };

15.2 Registrar Lambda Registration (startup)

During DLL initialization (before ModuleManager::Init is called), ten registrar lambdas fire. Each calls ModuleManager::AddRegistrar (RVA 0x9B2C0) passing the module name string and a factory std::function. The registrar slots are pushed into the vector at [.data+0x23B8] with stride 0x60 bytes per slot. Registration order (determined from code order in .text): Order Module Name Registrar code RVA Factory .rdata RVA vtable RVA 1 SetDither 0x001C41 0x3B0D58 0x3B0D58 2 FreeCam (fps) 0x001C80 0x3B0E70 0x3B0E70 3 SkillHack 0x001D50 0x3B0EE0 0x3B0EE0 4 PlayerProfile 0x001E20 0x3B0D90 0x3B0D90 5 NoClip 0x001EF0 0x3B0DC8 0x3B0DC8 6 Vacuum 0x001FC0 0x3B0E38 0x3B0E38 7 UnityExplorer 0x002090 0x3B0D28 — 8 FpsUnlocker 0x001B80 0x3B0E00 0x3B0E00 9 FreeCam (main) 0x001AB0 0x3B0E70 0x3B0E70 10 ESPModule 0x001980 — — ModuleManager::AddRegistrar (RVA 0x9B2C0) logic: constructs a std::string from the name argument, calls 0x18000F7D0 (TabManager::RegisterTab), then appends the registrar's std::function wrapper to the instances array. If the vector is full it calls the grow helper at 0x9B3C0.

15.3 ModuleManager::Init (RVA 0x9AC10)

Called once from startup sequence (RVA 0xA9190). Guards against double-init via [rcx+0x18] flag. Log messages: 'Initializing ModuleManager' (0x3B0C08) and 'ModuleManager initialization complete' (0x3B0C60). Asserts at source lines 34 and 52 reference ModuleManager.cpp. Init body: void ModuleManager::Init(ModuleManager* self) { if (self->initialized) { Log('[WARNING] ModuleManager already initialized'); return; } Log('Initializing ModuleManager'); // Assert (line 34 in ModuleManager.cpp) // Move instances_begin ptr to match registrar list rsi = &self->instances_begin; if (self->instances_begin != self->instances_end) rsi = self->instances_begin; // Wait for std::once_flag at [.data+0x23D0] // (once_flag guards module instance allocation) // Iterate registrar array ([.data+0x23B8]..[.data+0x23C0]) // stride = 0x60 bytes per registrar slot for (rbx = registrars_begin; rbx < registrars_end; rbx += 0x60) { std::function factory = rbx->invoke_ptr; // [rbx+0x58] BaseModule* mod = factory->operator()(); // vtable+0x10 // Append to instances list instances_end = mod; instances_end += 0x8; // (grow vector if needed via 0x9B0D0) // Call vtable[+0x8] on module = getName() const char name = mod->vtable+0x8; // Log 'Module {name} initialized' // Log formatted assert (line 45 in ModuleManager.cpp) assert_log(mod->name, ModuleManager_cpp, line=45); } self->initialized = true; Log('ModuleManager initialization complete'); // Assert (line 52 in ModuleManager.cpp) }

15.4 Per-Frame Dispatch Loops

Three dispatch functions iterate the instances array each frame. All share the same structure: guard on initialized flag, pointer-chase loop over [begin..end], null check, enabled flag check at [module+0x28], then vtable call. Dispatch Loop 1 — ModuleManager::DispatchRender (RVA 0x9AE80): // Called from Present hook with rcx = &ModuleManager (at [.data+0x2398]) void ModuleManager::DispatchRender(ModuleManager* self) { if (!self->initialized) return; BaseModule** it = self->instances_begin; BaseModule** end = self->instances_end; while (it != end) { BaseModule* mod = it; if (mod && mod->enabled) // [mod+0x28] != 0 mod->vtable0x18; // Render() it++; } } Dispatch Loop 2 — ModuleManager::DispatchHotkeys (RVA 0x9AEF0): void ModuleManager::DispatchHotkeys(ModuleManager self) { if (!self->initialized) return; for each BaseModule* mod in instances { if (mod && mod->enabled) mod->vtable0x30; // onHotkey() — pure virtual, no-op for all current modules } } Dispatch Loop 3 — ModuleManager::DispatchRegistrarInit (RVA 0x9AF60): // Called at 0x180083348 — initializes ImGui panel layout after first Present void ModuleManager::DispatchRegistrarInit(ModuleManager* self) { if (!self->initialized) return; for each BaseModule* mod in instances { if (mod) mod->vtable0x38; // getLinkedModuleFactory() — installs linked tab } // After loop: copy default panel config block // movups xmm0, [.data+0x1F08]; movups [.data+0x1F28], xmm0 // movups xmm1, [.data+0x1F18]; movups [.data+0x1F38], xmm1 // (16-byte config copy for initial panel state) } 15.4.1 Exception Handling in Dispatch Loops The pseudocode above omits the C++ exception-handling wrappers that the compiler generated around each vtable call. Each dispatch loop body is actually enclosed in a __try/__except block; the MSVC runtime (__CxxFrameHandler4, thunk table at RVA 0xAC840, imported from VCRUNTIME140.dll) is registered as the Structured Exception Handler via the .pdata unwind tables. If a module's virtual method throws, the runtime calls one of three catch-handler functions: 0xAEBC0 logs “[ERROR] Failed to update module ‘’” (associated with DispatchRender / Update), 0xAEC50 logs “[ERROR] Failed to render overlay for module ‘’”, and 0xAECE0 logs “[ERROR] Failed to process hotkeys for module ‘’”. All three handlers call the shared logging helper at 0x18000FDA0 (Log/Print) and then resume normally rather than propagating the exception, so a single misbehaving module cannot crash the entire frame.

15.5 Present Hook Call Site (RVA 0x082F00)

The Present hook callback contains all three dispatch calls plus the ImGui frame boundary calls. Relevant excerpt (from context around RVA 0x083386): // 1. DispatchRegistrarInit (once_flag guarded) — installs linked tabs rcx = &ModuleManager; // [.data+0x2398] call ModuleManager::DispatchRegistrarInit; // 0x18009AF60 // 2. DispatchRender — calls Render() on all enabled modules rcx = &ModuleManager; call ModuleManager::DispatchRender; // 0x18009AE80 // 3. DispatchHotkeys — calls onHotkey() on all enabled modules rcx = &ModuleManager; call ModuleManager::DispatchHotkeys; // 0x18009AEF0 // 4. Continue to D3D11 frame boundary / ImGui EndFrame call 0x18001C2D0;

15.6 Per-Module vtable[+0x10] and vtable[+0x18] Resolved Targets

vtable[+0x10] = Init/RegisterTab (called once during ModuleManager::Init). vtable[+0x18] = Render (called every frame from DispatchRender). Module vtable RVA vtable[+0x10] target vtable[+0x18] target Notes Vacuum 0x3B0E38 0x090060 (RegisterTab) 0x09B640 -> [.data+0x05D0] fn ptr NoClip 0x3B0DC8 0x081A20 (RegisterTab) 0x09B670 -> [.data+0x06D0] fn ptr PlayerProfile 0x3B0D90 0x0813D0 (RegisterTab) 0x09B6A0 -> [.data+0x0580] fn ptr SkillHack 0x3B0EE0 0x0818E0 (RegisterTab) 0x09B6D0 -> [.data+0x0770] fn ptr hook installer FreeCam 0x3B0E70 0x081300 (RegisterTab) 0x09B700 -> [.data+0x07D0] fn ptr SetDither 0x3B0D58 0x081590 (RegisterTab) 0x09B730 -> [.data+0x0630] fn ptr no-op FpsOverlay 0x3B0E00 0x081810 (RegisterTab) 0x09B760 -> [.data+0x0530] fn ptr overlay Note: vtable[+0x18] for each module returns a .data block ptr via a 2-instruction lea/ret stub. This stub serves as the state block accessor used during object cleanup. The actual Render dispatch uses this indirection: the stub returns the module's .data state block, which at offset [+0x00] stores a direct fn ptr to the Render/Update function installed by RegisterTab. The dispatch loop calls the stub (vtable[+0x18]) to get this function pointer, then calls through it.

15.7 ModuleManager Log Strings

String RVA Context '[WARNING] ModuleManager already initialized' 0x3B0B88 Init guard 'Initializing ModuleManager' 0x3B0C08 Init begin 'Module {} initialized' 0x3B0C48 Per-module Init success 'ModuleManager initialization complete' 0x3B0C60 Init end 'Failed to initialize module {}' 0x3B0C28 Init error handler '[ERROR] Failed to update module ' 0x3B0C90 Update error handler '[ERROR] Failed to render overlay for module ' 0x3B0CB8 Render error handler '[ERROR] Failed to process hotkeys for module ' 0x3B0CE8 Hotkey error handler ModuleManager.cpp source path 0x3B0BC0 Assert source file string

16. UnityExplorerModule

UnityExplorerModule is a fully implemented, live developer-tool module embedded inside the cheat. It is registered as the final entry in the module list (registration code at RVA 0x002090) and shares the Vacuum vtable (0x3B0E38), inheriting its factory and base dispatch structure. Its RegisterTab function is at RVA 0x090060, its per-frame Update stub points to the shared no-op destructor at RVA 0x083DC0 (same stub as SetDither and SkillHack). The module is not a stub — it contains a complete ImGui-based runtime Unity scene hierarchy browser and component inspector.

16.1 Registration and Vtable

The registrar lambda at RVA 0x002090 stores Vacuum's vtable pointer (0x1803B0E38) as the factory and passes the string 'UnityExplorerModule' (RVA 0x3B0D28) to ModuleManager::AddRegistrar. This means during ModuleManager::Init, calling vtable[+0x10] on UnityExplorerModule's registrar invokes Vacuum's RegisterTab stub (RVA 0x9B650), which resolves via jmp to UnityExplorerModule::RegisterTab at RVA 0x090060. The vtable[+0x18] dispatch slot returns [.data+0x2610] — the module's state block — and the per-frame render fn ptr is written there during RegisterTab. Registration: RVA 0x002090 (AddRegistrar call; factory = Vacuum vtable 0x3B0E38) RegisterTab: RVA 0x090060 (init; registers tab 'Unity Explorer', zeroes state) Render: RVA 0x090250 (per-frame ImGui scene/inspector panel) Update stub: RVA 0x083DC0 (shared no-op; frees string, optional delete) State block: [.data+0x2610] (0x190 bytes, zero-filled by memset at 0x0900BC) Tab name: 'Unity Explorer' (string RVA 0x3B02D0) Window title: 'Unity Explorer Window' (RVA 0x3B02E0)

16.2 RegisterTab (RVA 0x090060)

RegisterTab is guarded by a std::once_flag at [.data+0x260C]. On first call it: (1) zero-fills the 0x190-byte state block at [.data+0x2610] via memset (0x1800AC86A); (2) constructs the tab name std::string 'Unity Explorer' and calls TabManager::RegisterTab (0x18000F7D0) to register the ImGui tab at [.data+0x2618]; (3) writes the Update fn ptr (0x1803AFA38 → RVA 0x083DC0, shared no-op stub) to [.data+0x2610]; (4) zeroes all state fields (scene list vector, selected index, refresh flags, auto-refresh bool, interval float, search filter buffer, component list, inspector string); (5) calls std::once_flag::_Execute_once (0x1800AFF60) to seal the guard. On subsequent calls the already-initialized guard causes an early return at 0x1800901D8. Key state fields initialized during RegisterTab: [.data+0x2610] update_fn_ptr = 0x083DC0 (no-op stub) [.data+0x2618] tab_string = 'Unity Explorer' (std::string) [.data+0x2638] enabled = 0 (bool, OFF by default) [.data+0x2640] auto_refresh = 0 (bool) [.data+0x2644] refresh_interval = 3.0f (0x40400000) [.data+0x2648] scene_list_begin = 0 (ptr, vector) [.data+0x2650] scene_list_end = 0 [.data+0x2660] scene_list_cap = 0 [.data+0x2670] selected_scene_idx = 0 [.data+0x2680] selected_obj_idx = 0 [.data+0x2684] search_filter[0x100] = 0 (char buffer) [.data+0x2784] inspector_active = 0 (bool) [.data+0x2788] inspected_obj_ptr = 0 [.data+0x2790] inspected_obj_name = 0 (std::string)

16.3 Render / Per-Frame Logic (RVA 0x090250)

The Render function checks enabled ([this+0x28]) and a secondary active flag ([this+0x30]) before drawing. When both are set it calls ImGui::Begin with 'Unity Explorer Window' (RVA 0x3B02E0, via jmp to 0x1800937D0 = ImGui::Begin wrapper). The main function body at RVA 0x0902E0 is a substantial per-frame function that draws the complete inspector UI. Scene panel logic: // Check scene list (vector at [this+0x58]..[this+0x60]) if (scene_list is empty) { ImGui::Text("No scenes available. Click 'Refresh Scenes' to load."); } else { ImGui::Text("Select Scene:"); ImGui::Combo("##SceneCombo", &selected_scene_idx, scene_list, n_scenes); if (combo changed) { LoadScene(selected_scene_idx); } } // Writes g_Config->overlay_flags |= 1 and g_Config->overlay_scale = 300.0f // (at [g_Config+0x1F78] and [g_Config+0x1F90]) when scene panel is active Auto-refresh logic (RVA 0x090250): if (enabled && auto_refresh) { now = GetTime(); // 0x180093B10 elapsed = now - last_refresh_time; max_entries = (float)refresh_interval * SCALE_CONST; if (elapsed_entries >= max_entries) { RefreshScenes(this); // 0x180090D40 last_refresh_time = now; } } GameObject hierarchy panel (drawn when a scene is selected): // Search filter input: ##SearchFilter — writes to search_filter[0x100] buffer // GameObject list: iterates [this+0x40]..[this+0x48] (vector<GameObject*>) // Per entry: prints '[namespace]: ' prefix + name // 'Ins##' button beside each entry -> inspect that object // If list empty: Text('No GameObjects found in this scene.') // 'DontDestroyOnLoad' section: special scene with fallback text if not found Inspector panel (when an object is selected via 'Ins' button): // 'No GameObject selected.' if none // Otherwise shows: // 'Active' checkbox (calls GameObject.SetActive via IL2CPP) // Transform section: Position, Local Position, Rotation, Scale (float3 inputs) // 'Components' section: 'GameObject Class: %s.%s' // 'All Components:' list via IL2CPP GetComponents(UnityEngine.Component) // Per component: '%s.%s' (namespace.classname) // On fetch failure: 'Unknown Component' or 'Unable to get GameObject class information.'

16.4 Complete String Inventory

String RVA Usage 'UnityExplorerModule' 0x3B0D28 Module name (registrar) 'Unity Explorer' 0x3B02D0 Tab label; ImGui::Begin title 'Unity Explorer Window' 0x3B02E0 ImGui window title string 'Search Filter:' 0x3B02F8 Label above search input '##SearchFilter' 0x3B0308 ImGui InputText widget ID 'Inspector' 0x3B0318 Inspector sub-panel label 'GameObjectHierarchy' 0x3B0328 Hierarchy sub-panel label 'No scenes loaded. Click Refresh...' 0x3B0340 Empty scene list message 'Scene: ' 0x3B0390 Scene prefix label 'No GameObjects found in this scene.' 0x3B0398 Empty hierarchy message 'DontDestroyOnLoad' 0x3B03C0 Special DDOL scene label 'DontDestroyOnLoad (Not Found)' 0x3B03D8 DDOL fallback label 'Refresh' 0x3B03F8 Refresh button label 'Auto Refresh' 0x3B0400 Auto-refresh checkbox 'Interval (s)' 0x3B0410 Refresh interval slider label 'Scenes found: %d' 0x3B0420 Scene count display "No scenes available. Click 'Refresh Scenes' to load." 0x3B0438 No-scenes message 'Select Scene:' 0x3B0470 Scene selector label 'Select Scene' 0x3B0480 Combo default text '##SceneCombo' 0x3B0490 ImGui Combo widget ID ']: ' 0x3B04A0 Object list entry separator 'Ins##' 0x3B04A8 Inspect button label prefix 'No GameObject selected.' 0x3B04B8 Inspector empty state "Click 'Ins' button..." 0x3B04D0 Inspector hint text 'Active' 0x3B0508 Active checkbox label 'Transform' 0x3B0510 Transform section header 'Position' 0x3B0520 Position field label 'Local Position' 0x3B0530 Local position field label 'Rotation' 0x3B0540 Rotation field label 'Scale' 0x3B054C Scale field label 'No Transform component found.' 0x3B0558 Transform fallback message 'Components' 0x3B0578 Components section header 'GameObject Class: %s.%s' 0x3B0588 Class display format 'All Components:' 0x3B05A0 Component list header 'UnityEngine.Component, UnityEngine.CoreModule' 0x3B05B0 IL2CPP type name for GetComponents '%s.%s' 0x3B05E0 Component name format 'Unknown Component' 0x3B05E8 Component fallback name 'No components found or failed to get components.' 0x3B0600 Component fetch failure 'Unable to get GameObject class information.' 0x3B0638 Class info failure

16.5 Assessment

UnityExplorerModule is a developer/debug tool that was purpose-built alongside the cheat modules and registered in the same module system. It provides a runtime Unity scene browser — listing loaded scenes, displaying the active GameObject hierarchy with a search filter, and offering a per-object inspector showing Transform (position, rotation, scale), active state, and all attached components retrieved via IL2CPP reflection (GetComponents with 'UnityEngine.Component, UnityEngine.CoreModule' as the type argument). The module is enabled by the same ON/OFF flag ([module+0x28]) as all other modules and is rendered every frame from the same DispatchRender loop. Its auto-refresh timer (default 3.0s interval, bool at [.data+0x2640], float at [.data+0x2644]) periodically re-enumerates loaded scenes via RefreshScenes (RVA 0x090D40). The g_Config writes inside Render ([g_Config+0x1F78] |= 1, [g_Config+0x1F90] = 300.0f) activate the overlay resize logic while the explorer window is open. This is the probable origin of the DLL's filename 'unityexplorer.dll' — the binary was named after this embedded developer tool to serve as cover, making the file appear to be a legitimate Unity debugging utility rather than a game cheat.

17. Per-Config-Preset Writers

The cheat implements four named configuration presets that write distinct sets of skill-timing and distance-threshold constants into g_Config at runtime. These are not game-version or region variants as originally suspected; they are user-selectable combat automation profiles, each named after a science-fiction reference. The active preset name string is stored at [.data+0x00E0] and the integer index at [.data+0x00EC]. On startup the Settings tab reads both the current theme name and the default preset indicator from the config JSON, compares the theme string against each preset name via ImGui::Selectable (0x1800708D0), and calls the matching writer directly — all four calls reside in a single function at RVA 0x09A4F0.

17.1 Dispatch Mechanism

The dispatch logic is in the Settings tab render function at RVA 0x09A4F0. It reads the saved preset name string from the JSON config object (keyed 'Default', 'Evangelion Unit 01', 'Evangelion Unit 02', or 'Matrix'), compares via ImGui::Selectable, stores the matched preset name pointer to [.data+0x00E0], writes the index integer (0–3) to [.data+0x00EC], then calls the corresponding writer immediately. On subsequent frames the startup code at 0x082F02 reads [.data+0x00EC] and re-routes to the same writer if the selection changes: // RVA 0x082F00 version dispatch ecx = g_Config->preset_index; // [.data+0x00EC] switch (ecx) { case 0: WriterDefault(); // RVA 0x0941F0 case 1: WriterEvangelionUnit01(); // RVA 0x094890 case 2: WriterEvangelionUnit02(); // RVA 0x096770 case 3: WriterMatrix(); // RVA 0x098650 }

17.2 Preset Summary

Preset name Index Writer RVA Write count g_Config range 'Default' 0 0x0941F0 168 0xDA4 – 0x12A4 'Evangelion Unit 01' 1 0x094890 23 0xD9C – 0xEBE 'Evangelion Unit 02' 2 0x096770 23 0xD9C – 0xEBE 'Matrix' 3 0x098650 13 0xD9C – 0xE14 'Default' is the master preset and the only one that writes the full skill-timing table (g_Config offsets 0xEC8–0x12A4). The three non-default presets are thin overlays that write only the distance-threshold and encounter-tuning floats at offsets 0xD9C–0xEBE, leaving the skill-timing table zeroed for their entries. When any non-default preset is active the skill-timing table fields written by Default remain at their last-written values (the table is not re-zeroed between preset switches).

17.3 g_Config Field Semantics

The written offsets cluster into two functional groups identified by value range and stride pattern. Distance / encounter thresholds (offsets 0xD9C–0xE30) — written by all four presets. Values are floats in the range 0.0–21.0, representing game-unit distances. Groups of four consecutive dwords repeat the stride [min_x, min_y, range, limit] observed in ESP module configuration. Example values across presets: g_Config offset Default EvaUnit01 EvaUnit02 Matrix Semantic 0x0D9C 0.0 1.0 1.0 1.0 Encounter active flag / base threshold 0x0DA0 0.0 0.60 0.60 0.50 Approach multiplier 0x0DA4 10.0 10.0 10.0 8.0 Max detect range (units) 0x0DA8 10.0 10.0 10.0 8.0 Max engage range (units) 0x0DAC 8.0 4.0 4.0 0.0 Attack range (units) 0x0DB0 0.0 0.0 0.0 1.0 Reserved / extra trigger flag 0x0DDC 8.0 6.0 6.0 5.0 Secondary range A 0x0DE0 6.0 4.0 4.0 3.0 Secondary range B 0x0E0C 21.0 0.0 0.0 0.0 Max AoE range (Default only) 0x0E14 15.0 14.0 14.0 12.0 Long-range threshold Skill timing table (offsets 0xEC8–0x12A4) — written only by the Default preset (168 entries, all zero in the other three presets). Values are floats in the range 0.02–1.0 organized in repeating groups of four dwords: [min_time, max_time, window_end, confidence]. This matches the SkillHack timing parameters documented in Section 8. Each group of four corresponds to one skill slot. The table spans approximately 40 skill slots covering offsets 0xEC8 through 0x1144, with an additional small block at 0x1298–0x12A4. Example timing entries from Default: // g_Config[0xEC8..0xED7]: Skill slot 0 timing (Default) [0xEC8] min_time = 0.85f [0xECC] max_time = 0.85f [0xED0] win_end = 0.85f [0xED4] confidence= 1.00f // g_Config[0xED8..0xEE7]: Skill slot 1 timing (Default) [0xED8] min_time = 0.50f [0xEDC] max_time = 0.50f [0xEE0] win_end = 0.50f [0xEE4] confidence= 1.00f // g_Config[0xEE8..0xEF7]: Skill slot 2 timing (Default) [0xEE8] min_time = 0.05f [0xEEC] max_time = 0.05f [0xEF0] win_end = 0.07f [0xEF4] confidence= 0.90f // ... continues through ~40 skill slots to 0x1144 // g_Config[0x1298..0x12A7]: final 4-entry block [0x1298] min_time = 0.05f [0x129C] max_time = 0.05f [0x12A0] win_end = 0.07f [0x12A4] confidence= 0.73f

17.4 Preset Behavioral Differences

The three non-default presets represent incrementally more conservative tuning. 'Evangelion Unit 01' and 'Evangelion Unit 02' are nearly identical — both reduce attack range from 8.0 to 4.0, reduce long-range threshold from 15.0 to 14.0, and set the secondary detection distance lower than Default. The only distinction between the two Evangelion presets is a small float difference at offset 0xDC0/0xDC4 (both 0.50 in Unit 01 vs. both 0.50 in Unit 02 — functionally identical in the parsed output; any distinction would be in fields that were not written by the respective functions and thus retained from previous state). 'Matrix' is the most conservative preset: it lowers attack range to 0.0 (disabling direct attack trigger), cuts max detect range to 8.0, reduces the long-range threshold to 12.0, and sets the extra trigger flag at 0xDB0 to 1.0, suggesting it relies on a different trigger path. The 'Default' preset is by definition the most aggressive: it provides the only non-zero skill timing table and the widest detection ranges. This is consistent with the binary having version_index = 1 hardcoded at .data+0x00EC at static-init time, meaning 'Evangelion Unit 01' loads on first launch before the user selects a preset from the Settings tab.

17.5 Preset Name Strings

String RVA Role 'Default' 0x3B06F8 (via 0x3B0AF8) Preset name, ImGui label, JSON key; also theme name for Default 'Evangelion Unit 01' 0x3B06D0 (via 0x3B0AD4+) Preset name and JSON key for index 1 'Evangelion Unit 02' 0x3B0AE0 Preset name and JSON key for index 2 'Matrix' 0x3B0B10 Preset name and JSON key for index 3 'Theme' 0x3B0AD4 JSON field name for preset selection 'zh_cn' 0x3B10E8 Locale string; passed to string-construct at 0x9D8A4 (ecx==1 branch) 'en' 0x3B2020 Locale string; passed to string-construct at 0x9D890 (ecx==0/2 branch) The 'zh_cn' and 'en' locale strings at 0x3B10E8 and 0x3B2020 are constructed as std::string values during a JSON key-lookup operation at RVA 0x09D7D0 (called from the Settings tab). The locale is selected by the same integer switch (ecx) that dispatches the preset writers — 0 maps to 'en', 1 maps to 'zh_cn', and 2 falls back to 'en'. This implies the preset index also encodes locale preference: 'Default' (index 0) and the two Evangelion presets and 'Matrix' are treated as CN (index 1) by default, and 'en' is the fallback locale for presets 0 and 2. The locale string is used as the second argument to a JSON object accessor, indicating that config field names are stored locale-keyed in the JSON schema.

18. GABypass

GABypass is the IL2CPP function pointer resolution subsystem. Its sole function is to locate the game's IL2CPP runtime module (GameAssembly.dll) in the process address space, then compute and cache the addresses of 71 specific IL2CPP and Unity API methods that the cheat's modules call at runtime. It does not patch instructions, overwrite vtables, or install hooks — it is a pure address-resolution table initializer. The resolved pointers are stored in .data slots at offsets 0x1C48 through 0x1E80 and are subsequently used by every cheat module that makes IL2CPP calls: ESPModule, NoClip, FreeCam, SkillHack, FpsUnlocker, and the UnityExplorer component.

18.1 Initialization Sequence

GABypass::Patch (RVA 0x09D1E0) is called exactly once during startup from the main DLL thread at RVA 0x0A942A, immediately after the 'Initializing..' console log and before any module Update() or Render() calls. The call sequence is: // RVA 0x0A942A (main.cpp line 53, per embedded source path) Log("Initializing.."); GABypass::Patch(); // RVA 0x09D1E0 — resolve 71 IL2CPP pointers il2cpp_domain = .data+0x1E80; // call il2cpp_domain_get_assemblies immediately if (il2cpp_domain != null) { Log("IL2CPP Domain Found: " + ...); } // ... module init continues Inside GABypass::Patch, execution branches on whether [.data+0x00F0] is already non-null. That slot holds the cached GameAssembly.dll module base address. On first call (cold start), [.data+0x00F0] is zero, so the function calls GetModuleHandleW(L"GameAssembly.dll") via the IAT slot at 0x1800B1290 to obtain the module base, stores it in rdx, then computes all 71 pointers as fixed offsets from that base. On subsequent calls (if Patch is ever called again), [.data+0x00F0] is already populated so the 'GA Bypass successfully!' log and GetModuleHandleW call are skipped and rdx is loaded directly from the cached value before the offset table is re-written. In practice Patch is only called once. // GABypass::Patch (RVA 0x09D1E0) — annotated if ([.data+0x00F0] != 0) { Log("GA Bypass successfully!"); // already cached, log and skip resolve rdx = [.data+0x00F0]; goto write_table; } rdx = GetModuleHandleW(L"GameAssembly.dll"); // first-run: locate module write_table: // 71x: [.data+slot] = rdx + IL2CPP_offset [.data+0x1C70] = rdx + 0x0018AD80; // il2cpp_object_get_class [.data+0x1C78] = rdx + 0x00007480; // il2cpp_class_get_method_from_name [.data+0x1E70] = rdx + 0x00D94C10; // il2cpp_domain_get [.data+0x1E78] = rdx + 0x00D94DA0; // il2cpp_assembly_get_image [.data+0x1E80] = rdx + 0x00D93A60; // il2cpp_domain_get_assemblies // ... 66 additional Unity/game method pointers ret

18.2 The 71-Entry Pointer Table

Each entry is a QWORD at a fixed .data offset. The IL2CPP offset column is the byte distance from the GameAssembly.dll module base to the target function — these are static, computed at compile time from a known game binary version. The table spans two contiguous .data regions: 0x1C48–0x1CF8 (IL2CPP runtime and UnityEngine core) and 0x1D00–0x1E80 (game-specific methods, additional Unity API, UI/camera).

.data offset IL2CPP offset Resolved function Used by 1 0x1C48 +0x09DC0120 GameObject.GetComponentByIndex UnityExplorer inspector 2 0x1C50 +0x0018CEC0 il2cpp_domain_get_assemblies (A) GABypass init / UnityExplorer 3 0x1C58 +0x0B390700 Component.GetComponent UnityExplorer / NoClip 4 0x1C60 +0x0B3A2D20 Transform.get_localScale UnityExplorer inspector 5 0x1C68 +0x0B3A2CB0 Transform.get_rotation UnityExplorer inspector 6 0x1C70 +0x0018AD80 il2cpp_object_get_class UnityExplorer type query 7 0x1C78 +0x00007480 il2cpp_class_get_method_from_name UnityExplorer method lookup 8 0x1C80 +0x0B3A1AE0 Transform.get_localPosition UnityExplorer / NoClip 9 0x1C88 +0x0B3A1A70 Transform.get_position ESP / NoClip 10 0x1C90 +0x0B3A51D0 Transform.set_localPosition NoClip teleport 11 0x1C98 +0x0B398830 GameObject.SetActive UnityExplorer / NameChanger 12 0x1CA0 +0x0B3911F0 GameObject.get_transform ESP / NoClip 13 0x1CA8 +0x0B3A59D0 Transform.set_rotation FreeCam / NoClip 14 0x1CB0 +0x0B391D90 GameObject.get_activeInHierarchy UnityExplorer inspector 15 0x1CB8 +0x0B3B2410 GameObject.get_tag UnityExplorer inspector 16 0x1CC0 +0x0B3B2120 GameObject.get_name UnityExplorer inspector 17 0x1CC8 +0x0B3B40B0 GameObject.get_layer UnityExplorer inspector 18 0x1CD0 +0x0B397980 GameObject.get_scene UnityExplorer inspector 19 0x1CD8 +0x02F3DA80 Game: skill/buff method A SkillHack 20 0x1CE0 +0x00F27E10 Game: skill/buff method B SkillHack 21 0x1CE8 +0x0B329000 Component.GetComponents UnityExplorer component list 22 0x1CF0 +0x0B329D80 Component.GetComponentsInChildren UnityExplorer tree walk 23 0x1CF8 +0x03E9BB50 Game: skill/ability slot method A SkillHack 24 0x1D00 +0x0B383F60 Object.get_name UnityExplorer name display 25 0x1D08 +0x0B33CAB0 Component.GetType (A) UnityExplorer type display 26 0x1D10 +0x0B33CB00 Component.GetType (B) UnityExplorer type display 27 0x1D18 +0x039D1AA0 Game: skill/ability slot method B SkillHack 28 0x1D20 +0x026DE9F0 Game: combat/hit method A SkillHack / combat 29 0x1D28 +0x0478E860 Game: UI show/hide toggle NoClip / FpsUnlocker UI 30 0x1D30 +0x025E2D40 Game: combat/hit method B SkillHack / combat 31 0x1D38 +0x087C2CD0 Game: movement/physics method A NoClip CharacterController 32 0x1D40 +0x03419AF0 Game: movement/physics method B NoClip CharacterController 33 0x1D48 +0x0B322FB0 SceneManagement.Scene.get_name UnityExplorer scene display 34 0x1D50 +0x0B396A20 SceneManager.GetActiveScene UnityExplorer scene query 35 0x1D58 +0x0B397700 CinemachineBrain.get_ActiveVirtualCamera FreeCam hook 36 0x1D60 +0x03766810 Game: entity/actor state method A ESP / SkillHack 37 0x1D68 +0x0B3A2A60 Transform.set_localScale UnityExplorer inspector 38 0x1D70 +0x0B326660 Rigidbody.get_velocity NoClip / Vacuum 39 0x1D78 +0x0B3266B0 Rigidbody.set_velocity NoClip / Vacuum 40 0x1D80 +0x0B383200 Object.Destroy UnityExplorer 41 0x1D88 +0x0B3A1A10 Transform.set_position NoClip teleport / Vacuum 42 0x1D90 +0x0B3A2340 Game: entity/actor state method B ESP 43 0x1D98 +0x0B421800 Input.GetAxis('Mouse X') FreeCam look X 44 0x1DA0 +0x0B3A26D0 Game: player state method A ESP / SkillHack 45 0x1DA8 +0x0B3A1FB0 Game: player state method B ESP / SkillHack 46 0x1DB0 +0x0B32B030 Game: player health/stat accessor ESP health display 47 0x1DB8 +0x0B391240 GameObject.SetActive (CinemachineBrain active flag) FreeCam enable/disable 48 0x1DC0 +0x0B390440 Camera.get_main ESP worldToScreen / FreeCam 49 0x1DC8 +0x0B390F80 GameObject.FindObjectOfType Active scene object scan 50 0x1DD0 +0x0B3A19A0 Transform.get_position (2nd ref) ESP / NoClip 51 0x1DD8 +0x03F85430 Game: skill/action method C SkillHack 52 0x1DE0 +0x0B3A1D30 Transform.set_rotation (2nd ref) FreeCam / NoClip 53 0x1DE8 +0x0B3A1C90 Camera.get_fieldOfView FreeCam FOV control 54 0x1DF0 +0x00E92CF0 Game: entity/actor state method C ESP 55 0x1E00 +0x03DC14C0 Game: skill/action method D SkillHack 56 0x1E08 +0x03E0D2C0 Game: skill/action method E SkillHack 57 0x1E10 +0x03D9DF30 Game: skill/action method F SkillHack 58 0x1E18 +0x00E9E9F0 Game: skill/action method G SkillHack 59 0x1E20 +0x03EA53C0 Game: skill/action method H SkillHack 60 0x1E28 +0x0ACA0EC0 TMPro.TextMeshProUGUI.set_text Name changer UI label 61 0x1E30 +0x0B391D40 UnityEngine.UI.Text.set_text ON/OFF toggle labels / Name changer 62 0x1E38 +0x036AA8F0 Game: skill/action method I SkillHack 63 0x1E40 +0x03EC31C0 Game: skill/action method J SkillHack 64 0x1E48 +0x037F8CD0 Game: entity/actor method D ESP / combat 65 0x1E50 +0x036EA640 Game: skill/action method K SkillHack 66 0x1E58 +0x03EC30E0 Game: skill/action method L SkillHack 67 0x1E60 +0x037F2A40 Game: entity/actor method E ESP / combat 68 0x1E68 +0x037FD7E0 Game: entity/actor method F ESP / combat 69 0x1E70 +0x00D94C10 il2cpp_domain_get UnityExplorer domain probe 70 0x1E78 +0x00D94DA0 il2cpp_assembly_get_image UnityExplorer assembly walk 71 0x1E80 +0x00D93A60 il2cpp_domain_get_assemblies (B) Post-patch domain probe (main.cpp:67)

18.3 Functional Grouping

The 71 entries divide into four functional groups. Six entries (slots 2, 6, 7, 69, 70, 71) are IL2CPP runtime API functions — the low-level metadata accessors that the cheat uses to walk the IL2CPP type system for the UnityExplorer inspector. Their offsets are clustered near the start of GameAssembly.dll (+0x0007480, +0x0018AD80, +0x0018CEC0, +0x00D93A60, +0x00D94C10, +0x00D94DA0), consistent with early-loaded IL2CPP initialization code. Thirty-four entries are UnityEngine managed API methods — Transform, GameObject, Component, Camera, Rigidbody, SceneManager, and Object — that provide the cheat with Unity scene graph access, world-space position manipulation, and object lifecycle control. These are used across all active modules: ESP calls position/camera methods every frame, NoClip writes to Transform.set_position and Rigidbody.set_velocity, FreeCam uses Camera.get_fieldOfView and CinemachineBrain.get_ActiveVirtualCamera, and the UnityExplorer inspector uses the full component introspection set. Twenty-six entries are game-specific methods at offsets deep into GameAssembly.dll (+0x02F3DA80 and above), most concentrated in the 0x03xxxxxx–0x0Bxxxxxx range. Twelve of these are identifiable SkillHack targets (slots 19–20, 23, 27–28, 30, 51, 55–59, 62–66) — the methods responsible for skill cooldown, buff application, and action validation that SkillHack intercepts or spoofs. The remaining game-specific entries cover combat hit methods, movement/physics controllers, entity state accessors, and player stat readers used by the ESP and combat modules. Five entries cover additional UI and camera libraries: Cinemachine (slot 35, CinemachineBrain), TextMeshPro (slot 60, TextMeshProUGUI.set_text), and legacy Unity UI (slot 61, UnityEngine.UI.Text.set_text). These are used exclusively by the Name Changer module and the FreeCam camera management code.

18.4 Version Sensitivity

All 71 IL2CPP offsets are hard-coded at compile time as fixed displacements from the GameAssembly.dll base. There is no runtime method name lookup, no FNV hash scan, and no fallback if an offset is wrong — if the game updates and shifts any of these methods, the corresponding cheat feature silently malfunctions (calling into an arbitrary address). The SkillHack module uses a separate FNV-1a name-hash lookup path (documented in Section 8) as a secondary resolution mechanism for its core hook target, but the 26 game-specific GABypass entries have no such fallback. This architecture implies the binary is built and tested against a specific pinned game version; the version-selector system documented in Section 15 may exist partly to accommodate minor offsets shifts across game build variants, but the offsets themselves are not adjusted per variant.

19. JSON Config Schema and Save/Load System

This chapter resolves the config-schema investigation. The binary does not implement a standalone .json config file. All cheeto settings persistence is handled through ImGui’s built-in .ini settings mechanism, augmented with per-module custom settings handlers registered at runtime.

19.1 IAT — File I/O Functions (Complete Resolution)

The PE import table was fully parsed this session, resolving every previously unidentified IAT slot relevant to file I/O and config: IAT[0xB1268] = GetCurrentThreadId (stack cookie check at 0xAC709, NOT file I/O) IAT[0xB1278] = VirtualFree IAT[0xB1288] = VirtualProtect IAT[0xB1178] = GetConsoleWindow (used in Settings tab Toggle Console) IAT[0xB1628] = ShowWindow (used in Settings tab Toggle Console) IAT[0xB1858] = fread (file read, called ONLY from 0x12121) IAT[0xB1868] = fwrite (called from 0xEA1B, 0x170D6, 0x3033B, 0x3076D) IAT[0xB1870] = fclose (called from 0xEAB0, 0x1212F, 0x121A9, 0x170DF etc.) IAT[0xB1888] = _wfopen (wide-char file open, called ONLY from 0x11F93) IAT[0xB1890] = fseek (called from 0x120BC, 0x120E7) IAT[0xB1898] = ftell (called from 0x120A0, 0x120CD)

19.2 No Standalone JSON Config File

Exhaustive scanning of the binary confirmed no .json filename string exists anywhere in rdata or .data. The config system is the standard ImGui .ini persistence layer. All module settings are serialized through ImGui’s settings-handler API, not a JSON library. The nlohmann::json_abi_v3_12_0 library present in the binary is used exclusively for the i18n translation table, not for config I/O.

19.3 Config File: imgui.ini

The config filename “imgui.ini” (RVA 0x3ABB60) is set at RVA 0x1117A into ImGuiIO+0x20 (the IniFilename field) during ImGuiIO initialization. The log filename “imgui_log.txt” (RVA 0x3ABB70) is set into ImGuiIO+0x28 at the same site. Both are written relative to the process working directory at runtime.

19.4 Save/Load Trigger and Execution Path

Load path (on startup): RVA 0x30661 calls the file-read helper at 0x12050, which executes ftell (0x120A0) → fseek (0x120BC, 0x120E7) → ftell again (0x120CD) → malloc → fread (0x12121) → fclose (0x1212F). The buffer is passed to 0x30840 (ParseIniSettingsFromMemory), which walks the handler list at [ImGuiContext+0x2920] calling each registered handler’s ReadLine callback. Save path (periodic): The render loop checks [ImGuiContext+0x2900] (dirty flag, byte) and [ImGuiContext+0x2904] (float countdown timer). When both conditions are met, RVA 0x30A90 (SaveIniSettingsToDisk) builds the path from [ImGuiContext+0x2910] (custom IniFilename) or falls back to [.data+0x1BEC]. It calls each handler’s WriteAll callback, then passes the buffer to 0x11EA0 (_wfopen wrapper with “wt” mode at RVA 0x1803AD594), fwrite (0x3076D), and fclose (0x30776). The manual save trigger at RVA 0x17072 sets [ImGuiContext+0x2900]=1 and [ImGuiContext+0x2904]=0 to force an immediate write.

19.5 i18n Translation Table (Clarification)

The blob starting at RVA 0x3B10E8 is the compile-time JSON localization table, not the config schema. It is a single JSON object mapping English UI label strings to Chinese (zh_cn) equivalents. At startup (RVA 0x2164), a std::string constructor copies this blob (length 0xEED bytes) into [.data+0x1EB8]. The i18n loader at RVA 0x9D660 selects either “en” or “zh_cn” values based on the language toggle flag. The nlohmann runtime type-error strings (object, array, null, string, number, parse_error etc.) at 0x3B3010–0x3B30D8 confirm nlohmann v3.12.0 is statically linked. The “enabled” string at RVA 0x3B0B28 is one of these UI labels; it is used to display the module on/off state in the GUI and is not a JSON config key.

19.6 Module Settings Handler Architecture

Each module registers a settings handler at [ImGuiContext+0x2920] (a dynamically-grown array of 0x48-byte handler structs). The handler struct layout (from RVA 0x30904): +0x00 TypeName (const char*) — section identifier in .ini file +0x08 TypeHash (u32) — CRC32 of TypeName (computed at 0x3079C–0x30803) +0x18 ReadOpenFn — called when section header encountered +0x38 WriteAllFn — called during save to emit key=value lines The 11 registered module classes identified from RTTI at .data+0x0590–0x0E60 are: ESPModule, FPSModule, FpsUnlocker, FreeCam, NoClip, PlayerProfile, PreventScreenshot, SetDither, SkillHack, Vacuum, UnityExplorerModule.

19.7 ModuleManager Lifecycle

ModuleManager::Init (RVA 0x9ACA4) iterates the module registry at [.data+0x23B8], calls vtable[+0x10] to obtain each module instance, then vtable[+0x08] to initialize it. Each initialized module is logged as “Module {} initialized” (string at RVA 0x3B0C48). Completion is logged as “ModuleManager initialization complete” (RVA 0x3B0C60). The per-frame dispatch methods are vtable[+0x18] (Update, iterated at 0x9AE80) and vtable[+0x30] (RenderOverlay, iterated at 0x9AEF0). Both iterate the same module list checking [module+0x28] (enabled flag) before calling the virtual.

19.8 Settings Tab Behavior

Settings::RenderOverlay (RVA 0x9A4F0–0x9AB98, source E:\git\Endfield_Cheeto\libraries\pipeline\gui\tabs\SettingsTAB.cpp) handles: language toggle via 0x9D660 (reads [.data+0x1EB8] i18n blob, selects “en” or “zh_cn” values); theme color initialization via 0x98650 (parses hex color strings e.g. “00FF41FF” from rdata into [.data+0x1C00+0xD9C..] float RGBA fields); console window toggle via GetConsoleWindow (IAT[0xB1178]) and ShowWindow (IAT[0xB1628]). There are no Save/Load buttons; settings are persisted automatically by the ImGui .ini mechanism on each render frame that detects a dirty flag.

20. FPSModule

FPSModule implements two independent features controlled by the “FPS Monitor” tab in the GUI: an in-game FPS counter overlay and a separate FPS cap unlocker. The RTTI decorated name is .?AVFPSModule@@ (RVA 0x3C5CF8). The module name string “FPS Monitor” resides at RVA 0x3AFA88; “Show FPS Overlay” at 0x3AFA98; the overlay prefix string “FPS: ” at 0x3AFAAC.

20.1 Registration and Vtable

The registrar constructor references the name string at RVA 0x1B71 and calls the module registry at 0x9B2C0. Two vtable blocks are emitted. The lambda vtable (for the registrar’s std::function wrapper) lives at 0x3B0E00; the module instance vtable is at 0x3B0E38. The singleton object is heap-allocated and its pointer cached at [.data+0x22E0] (VA 0x1803C72E0). Instance vtable (0x3B0E38): [+0x00] 0x9B660 dtor [+0x08] 0x9B660 dtor (scalar deleting) [+0x10] 0x9B650 Initialize -> jmp 0x90060 [+0x18] 0x9B640 GetSingleton -> returns [.data+0x05D0] [+0x20] 0x9B620 dtor with size 0x10 [+0x28] 0x9B630 GetSelf -> lea rax,[rcx+8]; ret [+0x38] 0x9B720 vtable setter (returns ptr to 0x3B0E70) [+0x48] 0x9B710 Update -> jmp 0x81300

20.2 Initialize (RVA 0x814C0)

Guarded by a once_flag at [.data+0x2310]. On first call it allocates the module object (0xD8 bytes via 0xAC86A), stores the vtable pointer from 0x3AFA38 into [.data+0x22E0], copies the name string “FPS Monitor” into [.data+0x22E8], sets enabled = 0x0 at [.data+0x2308], then overwrites the vtable slot with the render-function pointer from 0x3AFAC0. If already initialized the singleton pointer is returned early from [.data+0x22E0].

20.3 RenderOverlay — Panel (RVA 0x85660; inner ImGui branch at 0x856F0)

The panel render function is called by ModuleManager::RenderOverlay. It renders two ImGui checkboxes inside the “FPS Monitor” collapsing header. The first checkbox (“FPS Monitor”, bound to [module+0x28]) toggles the FPS counter overlay; on state change it sets [ImGuiContext+0x2900]=1 (dirty flag) and resets the ini-save timer. The second checkbox (“Show FPS Overlay”, RVA 0x3AFA98) is bound to [module+0x28] via 0x85320 (Checkbox with state-ptr helper) and controls display of the overlay window. After both checkboxes, the function calls ImGui::EndDisabled via [ImGuiContext+0x27F0] WORD counter decrement.

20.4 RenderOverlay — FPS Counter Overlay (RVA 0x858D0)

When the FPS overlay is enabled ([module+0x28] != 0), this function draws a frameless ImGui window labelled “##Foreground” (RVA 0x3ABF10) pinned to the top-left of the viewport. It calls [.data+0x1D38] (GetDeltaTime via ImGuiContext) with rcx=0, computes xmm6 = 1.0 / deltaTime (i.e. current FPS), builds the display string “FPS: ” + integer FPS value (via 0x7F5C0), then selects a text color from three XMMWORD constants based on two hard-coded thresholds: fps >= 60 -> color constant at 0x1803B3530 (green) 30 <= fps < 60 -> color constant at 0x1803B3540 (yellow) fps < 30 -> color constant at 0x1803B3510 (red) The colored FPS string is then submitted to the ImGui drawlist via 0x51580 (AddText with explicit color). The overlay window uses ImGui foreground drawlist accessed through [ImGuiContext+0x15D8]+0x40.

20.5 Singleton State Layout

FPSModule singleton base address: [.data+0x22E0] (VA 0x1803C72E0). Object size: 0xD8 bytes. +0x00 vtable ptr (0x3AFA38 / 0x3AFAC0 after init) +0x08 std::string name = "FPS Monitor" ([.data+0x22E8]..[.data+0x2307]) +0x28 BYTE enabled (0 = disabled; written at [.data+0x2308]) +0x30 BYTE show_fps_overlay (checkbox state for "Show FPS Overlay") +0x60 XMMWORD (overlay window position/size, zeroed on init)

21. PreventScreenshot

PreventScreenshot prevents the game window from being captured by screen-recording tools. RTTI: .?AVPreventScreenshot@@ (RVA 0x3C5DA8). GUI label: “Prevent Screenshot” (RVA 0x3B00B8). The module uses the Windows API SetWindowDisplayAffinity (string at .data RVA 0x3C34A6, imported dynamically from user32.dll at RVA 0x3AEC70) with a Windows 10 build check before applying the affinity flag.

21.1 Registration and Vtable

Singleton pointer cached at [.data+0x2358] (VA 0x1803C7358). Object size: 0x48 bytes. Once_flag at [.data+0x2390]. Two boolean state fields: [.data+0x2380] = enabled (BYTE, 0 on init), [.data+0x2388] = second toggle flag (BYTE, 0 on init).

21.2 Initialize (RVA 0x8AD70)

Guarded by a once_flag at [.data+0x2390]. On first call: constructs the std::string name “Prevent Screenshot” at [.data+0x2360], stores base vtable ptr 0x3AFA38 at [.data+0x2358], overwrites with second vtable ptr from 0x3B0110, zeroes both bool fields at [.data+0x2380] and [.data+0x2388].

21.3 RenderOverlay (RVA 0x8AE60)

Calls GetInstance (0x8AD70) to obtain the module pointer. Renders a single ImGui checkbox “Prevent Screenshot” via 0x9D7D0 (toggle-checkbox helper) with state pointer [module+0x28] (enabled bool). The result is passed to 0x61FE0 (ImGui::Checkbox state commit), then ImGui::EndDisabled is called via the [ImGuiContext+0x27F0] WORD counter path (with an assertion for “Calling EndDisabled() too many times!” at 0x3AC160 if the counter is already zero).

21.4 Update — SetWindowDisplayAffinity Dispatch (RVA 0x8AFC0)

Called per-frame by ModuleManager::Update. The logic is:

  1. Call GetInstance (0x8AD70) -> rbp = module object ptr
  2. If [rbp+0x30] already set: skip (module not yet enabled)
  3. If [rbp+0x28] (enabled) set: walk the hook/window list at [.data+0x24D0]
  4. For each node [rbx+0x10]: call 0x8B220 (OS-version-checked affinity setter)
  5. Call 0x81B00 (build HWND list), then 0x869A0 (apply affinity to all HWNDs)

21.5 OS Version Check and SetWindowDisplayAffinity (RVA 0x8B220)

This function loads ntdll.dll (via IAT[0x1800B1290]), resolves “RtlGetVersion” (IAT[0x1800B1088]), and fills a 0x11C-byte OSVERSIONINFOEXW struct on the stack. The OS build number (OSVERSIONINFOEXW.dwBuildNumber) is then cached at [.data+0x24FC] after being memcpy’d into [.data+0x24F0]. On subsequent calls, the cached value is used directly. The affinity call at 0x8B48F reads [rbp+0x28] (enabled bool) and compares the cached build number against 0x4A61 (decimal 19041, Windows 10 Build 19041 = version 20H1). Two code paths result: build < 19041: affinity arg = (enabled ? 1 : 0) (WDA_MONITOR = 1) build >= 19041: affinity arg = (enabled ? 0x11 : 0) (WDA_EXCLUDEFROMCAPTURE = 0x11) The resolved SetWindowDisplayAffinity function pointer is called via IAT[0x1800B1460]. On pre-20H1 builds, WDA_MONITOR (0x1) is used, which prevents the window from appearing in screen captures taken via the PrintScreen key but not via capture APIs. On 20H1 and later, WDA_EXCLUDEFROMCAPTURE (0x11) is used, which prevents capture by all recording tools including OBS and the Windows Game Bar. The “SetWindowDisplayAffinity” string stored at .data RVA 0x3C34A6 is used as the GetProcAddress argument for the dynamic resolve.

21.6 Singleton State Layout

PreventScreenshot singleton base: [.data+0x2358] (VA 0x1803C7358). Object size: 0x48 bytes. +0x00 vtable ptr (0x3AFA38 / 0x3B0110 after init) +0x08 std::string name = "Prevent Screenshot" ([.data+0x2360]..[.data+0x237F]) +0x28 BYTE enabled (checkbox state; drives affinity arg) +0x30 BYTE state_dirty (set=1 when affinity has been applied; guards re-apply) +0x38 BYTE second_flag ([.data+0x2388]; purpose unclear, zeroed on init) The HWND target list at [.data+0x24D0] is a doubly-linked list of window handles to which the affinity is applied. The list is populated by 0x81B00 (enumerate Unity windows) and walked by the Update loop. The count of registered HWNDs is tracked at [.data+0x24D8].

22. ESPModule Render and Update Implementation

Chapter 9 established ESPModule’s state layout and color-table defaults. This chapter documents the two remaining vtable slots not covered there: RenderOverlay (the ImGui control panel) and Update (the per-frame world-space entity label loop), both of which were only identified during the current analysis pass.

22.1 RenderOverlay (RVA 0x83FA0)

RenderOverlay is a large, monolithic function spanning roughly 0x83FA0–0x8499E. It draws the “ESP Features” collapsing header and all subordinate controls using the same once-lock + ImGui state machine pattern documented in FPSModule (Chapter 20). The function uses rsi throughout as the ESPModule singleton pointer (base VA 0x1803C6F70). The function opens a CollapsingHeader titled “ESP Features” (string RVA 0x3AF838) via helper 0x9D7D0 with its state bound to [.data+0x27B0]. If collapsed, execution jumps directly to the epilogue. When expanded, the first control rendered is an “ON / OFF” checkbox (string RVA 0x3AF848) via helper 0x85320; its bool is bound to [rsi+0x28] (enabled). If enabled is false, the remainder of the panel still renders but ImGui’s BeginDisabled path dims and suppresses all interaction. The “Display Types” sub-header (string RVA 0x3AF858) is rendered via 0x6EC20, which is a lightweight CollapsingHeader wrapper that returns false immediately when ImGui’s locked-input flag ([ImGuiContext+0x106]) is set. When expanded, it presents four entity visibility checkboxes, each bound via 0x61FE0 (ImGui::Checkbox commit helper): “Show Monsters” (RVA 0x3AF868) → [rsi+0x34] show_monsters “Show NPC” (RVA 0x3AF878) → [rsi+0x35] show_npc “Show Friendly” (RVA 0x3AF888) → [rsi+0x36] show_friendly “Show Puzzles” (RVA 0x3AF898) → [rsi+0x37] show_puzzles “Show All” (RVA 0x3AF8A8) → [rsi+0x38] show_all After the Show All checkbox, a Separator is emitted via 0x70630 (which also adjusts the cursor Y position). A second sub-header, “Display Info” (RVA 0x3AF8B8), follows the same 0x6EC20 pattern. When expanded, it reveals the per-label visibility checkboxes: “Show Distance” (RVA 0x3AF8C8) → [rsi+0x39] show_distance “Show Name” (RVA 0x3AF8D8) → [rsi+0x3A] show_name “Show Type” (RVA 0x3AF8E8) → [rsi+0x3C] show_type A second Separator call via 0x70630 closes the Display Info block. The function epilogue at 0x84984–0x8499E restores the ImGui cursor Y, pops the saved XMM registers, and returns.

22.2 Update / DrawOverlay (RVA 0x84A00)

Update is the per-frame entity rendering loop. It is guarded at entry (0x8499F) by a two-instruction stub that tests [rcx+0x28] (enabled) and returns immediately if clear, so the entire loop is skipped when the module is disabled. The main body at 0x84A00 proceeds as follows. Initialization: the function calls the GetEntityManager cached pointer ([.data+0x1D28], xor ecx, ecx) and GetEntityList ([.data+0x1D30]), both resolved by GABypass. It also calls GetScreenResolution ([.data+0x1D18]) into a local {float2, int} struct, and GetCameraPosition ([.data+0x1D00]) to build a world-origin vector. If the entity count at [rax+0x20] is zero, execution jumps to the epilogue at 0x852AB. Per-entity loop (0x84B30–0x852A5): for each entity pointer in the array, the function calls GetEntityType ([.data+0x1D20], xor edx edx) and dispatches on the returned type code. The dispatch also loads the per-type color XMMWORD directly from the ESPModule object at a type-dependent offset, and selects the corresponding visibility-flag byte: type 0x08 → color [rdi+0x70] GREEN (0.00, 1.00, 0.00) flag: show_friendly [rdi+0x36] type 0x10 / 0x4010 → color [rdi+0x40] RED (1.00, 0.00, 0.00) flag: show_monsters [rdi+0x34] type 0x20 → color [rdi+0x50] ORANGE (1.00, 0.65, 0.00) flag: show_puzzles [rdi+0x37] type 0x100 → color [rdi+0x80] BLUE (0.00, 0.00, 1.00) flag: show_npc [rdi+0x35] default → color [rdi+0xB0] WHITE (1.00, 1.00, 1.00) flag: show_all [rdi+0x38] Visibility gating: for named types the check is (show_all OR type_flag) != 0; for the default case only show_all is tested. If the entity fails the gate, execution jumps to the loop increment at 0x85289. Screen-space projection: GetScreenPosition ([.data+0x1CF8]) is called with the entity world position and camera origin to produce a {float2, float} screen-coord struct. The resulting screen-space depth is compared against the module’s max_draw_distance field ([rdi+0x30], default 300); entities beyond that distance are culled at 0x84C6B. Label assembly: a temporary std::string is built on the stack (0x84CB0). If show_distance ([rdi+0x39]) is set, the metric distance is formatted as an integer via 0x7F5C0 and prepended with the distance marker string “m” (RVA 0x3AF8F4). If show_name ([rdi+0x3A]) is set, GetEntityName ([.data+0x1CE0]) is called and the result is appended; if show_type ([rdi+0x3C]) is set, the entity type code is looked up against a six-entry table at RVA 0x3AF908 / 0x3AF920 mapping type values to name string pairs: 0xFFFFFFFF → “All” 0x00000001 → “Invalid” 0x00000008 → “Character” 0x00000010 → “Enemy” 0x00000020 → “Interactive” 0x00000040 → “Projectile” If multiple label fields are enabled, segments are joined by “ | ” (RVA 0x3AF900). The assembled label string is then submitted to the ImGui foreground draw list via 0x49820, which positions the text at the projected screen coordinate with a small pixel offset (loaded from RVA 0x3B3224), using the type-selected RGBA color. The foreground draw list is accessed through the “##Foreground” window (RVA 0x3ABF10) as documented in FPSModule. The font for the label is pushed/popped around the call via 0x28C00 and 0x28D70 (BeginFontScope / EndFontScope wrappers). Loop increment: rbx (entity index) is incremented at 0x85289, r15 advances by 8 bytes through the entity pointer array, and the loop repeats from 0x84B30 until rbx reaches the entity count. On exit the stack cookie is verified and the function returns.

22.3 ESPModule Singleton State Layout (Complete)

The following table merges the fields identified in Chapter 9 with the RenderOverlay and Update findings above. Base address: [.data+0x1F70] (VA 0x1803C6F70). All booleans are BYTE; all color slots are XMMWORD (16-byte RGBA float4). Offset .data addr Type Field / Init Value +0x00 [.data+0x1F70] QWORD vtable ptr (0x3AFA38 before init; 0x3AF9E0 after) +0x08 [.data+0x1F78] std::string name = 'ESPModule' (RVA 0x3AF828) +0x28 [.data+0x1F98] BYTE enabled = 0 +0x30 [.data+0x1FA0] DWORD max_draw_distance = 300 (0x12C) +0x34 [.data+0x1FA4] BYTE show_monsters = 1 +0x35 [.data+0x1FA5] BYTE show_npc = 1 +0x36 [.data+0x1FA6] BYTE show_friendly = 1 +0x37 [.data+0x1FA7] BYTE show_puzzles = 1 +0x38 [.data+0x1FA8] BYTE show_all = 0 +0x39 [.data+0x1FA9] BYTE show_distance = 1 +0x3A [.data+0x1FAA] BYTE show_name = 1 +0x3B [.data+0x1FAB] BYTE reserved = 0 +0x3C [.data+0x1FAC] BYTE show_type = 0 +0x40 [.data+0x1FB0] XMMWORD color_enemy RED (1.00, 0.00, 0.00, 1.00) +0x50 [.data+0x1FC0] XMMWORD color_interactive ORANGE (1.00, 0.65, 0.00, 1.00) +0x60 [.data+0x1FD0] XMMWORD color_slot2 YELLOW (1.00, 1.00, 0.00, 1.00) +0x70 [.data+0x1FE0] XMMWORD color_friendly GREEN (0.00, 1.00, 0.00, 1.00) +0x80 [.data+0x1FF0] XMMWORD color_npc BLUE (0.00, 0.00, 1.00, 1.00) +0x90 [.data+0x2000] XMMWORD color_slot5 CYAN (0.00, 1.00, 1.00, 1.00) +0xA0 [.data+0x2010] XMMWORD color_slot6 PURPLE (0.58, 0.00, 0.83, 1.00) +0xB0 [.data+0x2020] XMMWORD color_default WHITE (1.00, 1.00, 1.00, 1.00) +0xC0 [.data+0x2030] XMMWORD color_slot8 PINK (1.00, 0.08, 0.58, 1.00) +0xD0 [.data+0x2040] XMMWORD color_slot9 LPINK (1.00, 0.75, 0.80, 1.00) Color slots 2, 5, 6, 8, and 9 are not assigned to any type code in the Update dispatch and are therefore spare palette entries; they are exposed in the ImGui color-picker widgets but have no current runtime effect on the overlay.

23. DamageHack — Ghost Feature Analysis

The i18n table (RVA 0x3B1484) contains four keys with no corresponding RTTI class, vtable, registrar lambda, registered singleton, or callable code anywhere in the binary: “Damagehack Toggle”, “Damage Multiplier”, “Multiplier Value”, and “Random Damage Type”. This chapter documents what can be determined from the available evidence and establishes what is definitively absent.

23.1 i18n Evidence

The four DamageHack keys appear as a contiguous block in the JSON i18n blob immediately after the “Version: ” key and immediately before “This is free, if you spend money, then you have been deceived”. Each key carries English and Simplified Chinese translations: “Damagehack Toggle” en / zh_cn: 伤害修改 (Damage Modification) “Damage Multiplier” en / zh_cn: 伤害倍数 (Damage Multiplier) “Multiplier Value” en / zh_cn: 倍数値 (Multiplier Value) “Random Damage Type” en / zh_cn: 随机伤害类型 (Random Damage Type) The Chinese translations are idiomatic and consistent with the translations for implemented features in the same blob, indicating they were written at the same time as the rest of the localisation table. The four keys fit the pattern of a planned ImGui panel: one boolean toggle, one float multiplier, a numeric input for the multiplier value, and an enum selector for damage type randomization.

23.2 What Is Absent

A complete binary search for any string containing “Damage”, “damage”, “DamageHack”, or “damagehack” outside the JSON blob returns zero results. The RTTI scan of the .data section (RVA 0x3C5000–0x3C8000) identifies exactly 11 cheat-module class names — ESPModule, FPSModule, FpsUnlocker, FreeCam, NoClip, PlayerProfile, PreventScreenshot, SetDither, SkillHack, Vacuum, UnityExplorerModule — and no DamageHack entry. Similarly, the registrar-lambda RTTI list contains no DamageHack entry. There is no singleton pointer, no once_flag guard, no vtable, and no callable RenderOverlay or Update function anywhere in the image.

23.3 Interpretation

DamageHack was planned but never implemented in this build. The i18n keys were added to the localisation file during feature planning or alongside a partial implementation that was subsequently stripped, but no code corresponding to those keys was ever compiled into the binary. This is consistent with the developer shipping the localisation blob as a whole-file asset while selectively excluding unfinished module source files from the build. The intended design, inferred from the four i18n keys, would have been: a boolean master toggle (“Damagehack Toggle”) gating an intercepted damage-calculation call, a float multiplier applied to the outgoing damage value (“Damage Multiplier” / “Multiplier Value”), and an enum-driven randomisation mode for the damage type field (“Random Damage Type”). The implementation would most likely have operated as an IL2CPP function hook resolved via GABypass, consistent with how SkillHack intercepts cooldown and cost values. From a detection standpoint, the ghost i18n keys are a useful indicator: any version of this cheat that activates DamageHack controls would be a different build from the one analysed here. The presence of these keys in an extracted string dump of a suspect binary is therefore a build-version discriminator, not evidence of active functionality.

25. Sidebar / Main Panel Render (RVA 0x7F8F0)

The top-level overlay panel is rendered by the function at RVA 0x7F8F0 (VA 0x18007F8F0). This function draws the outer “Sidebar” ImGui window that contains all module tab buttons and the About page. It is called from the ModuleManager render loop on every Present() frame and is responsible for the entire visible cheat UI chrome.

25.1 Function Signature and Layout

Entry point: RVA 0x7F8F0, approximately 0x146E bytes (tail-calls into ImGui epilogue at 0x180023E20 via jmp at 0x180080D5E). The function allocates a 0x380-byte stack frame, saves xmm6–xmm8, and takes a single rcx argument (ModuleManager / global context pointer). Key address references: Window title: "Sidebar" (RVA 0x3AF2C8) — used as module lookup key (CRC32 via 0x180011DF0, registry lookup via 0x18003D1A0 and 0x18001D2B0); ImGui::Begin is not called from within 0x7F8F0 itself Banner string: "EF - Cheeto Press F12 to show panel" (RVA 0x3AF258) Disclaimer: "This is free, if you spend money, then you have been deceived" (RVA 0x3AF288) Active tab idx: [.data+0x1F68] (VA 0x1803C6F68; written on click, read by jump table at 0x80B52)

25.2 Tab Navigation and Rendering

The sidebar renders six tab buttons. Each label is looked up from the i18n table via 0x18009D660 (the same translation dispatcher used by all modules). The six tabs, their label RVAs, and the jump-table case bodies dispatched on selection are: Tab 0: "About" (RVA 0x3AF2D0) — sidebar header (banner + disclaimer) + About body sub-function (0x80E80) Tab 1: "Player" (RVA 0x3AF2DC) — NoClip, SkillHack (movement/skill controls) Tab 2: "ESP" (RVA 0x3AF2E8) — ESPModule overlay features Tab 3: "World" (RVA 0x3AF2F0) — Vacuum (world/item interaction) Tab 4: "Visual" (RVA 0x3AF2FC) — FPSMonitor, FreeCam, SetDither, FpsUnlocker, PlayerProfile Tab 5: "Settings" (RVA 0x3ADFD8) — Theme/preset selection via 0x18009A4F0 (language, color theme) The banner string (RVA 0x3AF258) and anti-scam disclaimer (RVA 0x3AF288) are rendered as a Sidebar-level header before the tab bar. Each of the six tab buttons is rendered by calling 0x80D80 (click-state handler, returns bool); if a tab is clicked its index (0–5) is written to [.data+0x1F68] (VA 0x1803C6F68). After all tab buttons are rendered, a jump table at RVA 0x80B52 reads [.data+0x1F68], bounds-checks against 5, and dispatches to the corresponding case via [0x180000000 + rax*4 + 0x80D64]. Case 0 calls sub-function 0x80E80 (About body: game title, version, author). Cases 1–4 call module-getter helpers that return the relevant singleton pointer, then invoke vtable[0x28] (RenderOverlay) for each. Case 5 delegates to 0x18009A4F0 (Settings/Theme renderer).

25.3 Author and Version Display

The About tab body is rendered by sub-function 0x80E80. It displays game context via the format string “%s Game: Endfield CTB3” (RVA 0x3AF350), the version label “Version: ” (RVA 0x3AF368) with value “1.0.0” (RVA 0x3AF374), and the author label “Author: ” (RVA 0x3AF380) with value “gktwo” (RVA 0x3AF38C). These are direct string literals, not i18n-dispatched keys.

25.4 Key Address Summary

RVA 0x7F8F0 Sidebar::RenderMainPanel (this chapter) RVA 0x3AF258 Banner string RVA 0x3AF288 Anti-scam disclaimer RVA 0x3AF2C8 "Sidebar" window title .data+0x1F68 Active tab index (VA 0x1803C6F68; written per-click, dispatched at jump table 0x80B52)

26. Language Selector (Sidebar Unconditional Panel)

The sidebar function (0x7F8F0) renders a language-selection sub-panel unconditionally on every frame, before the jump-table dispatch for tab bodies. The panel appears at VA range 0x180080770–0x180080B50 and is part of the sidebar’s Settings section rather than any individual tab body.

26.1 String Inventory

RVA 0x3AF310 "English" — first Combo item (index 0) RVA 0x3AF318 "简体中文" — second Combo item (index 1) RVA 0x3AF328 " Language" — tab label (5-space indent, 0xD chars) RVA 0x3AF338 "##Language" — ImGui::Combo widget ID

26.2 Execution Flow

The language selector logic follows this sequence: 0x180080895 call 0x18009D660 — locale context init 0x1800808DD lea rsi,[...] # 0x1803AF310 — "English" item ptr 0x1800808E3 lea rbx,[...] # 0x1803AF318 — "简体中文" item ptr 0x1800809A1 lea rdx,[...] # 0x1803AF328 — tab label " Language" 0x1800809C6 call 0x18009D7D0 — BeginTab (render label) 0x180080A03 call 0x180064220 — ImGui::Combo (language dropdown) al = 1 if selection changed, 0 otherwise if English selected: 0x180080A2F mov DWORD PTR [0x1803C77B0], r12d — store 0 (language index = English) if 简体中文 selected: 0x180080A5D mov DWORD PTR [0x1803C77B0], 0x1 — store 1 (language index = ZH-CN) 0x180080A6E call 0x18002A530 — i18n content refresh (reload translations) 0x180080A73 dec DWORD PTR [g_Config+0x2764] — decrement content ref-count 0x180080A80 mov rax,[g_Config+0x15D8] — get active config preset ptr 0x180080A87 mov BYTE PTR [rax+0x103], 0x1 — set dirty flag for config save 0x180080B0B lea rcx,[...] # 0x1803ADFC8 "Content" — module key 0x180080B12 call 0x180011DF0 — CRC32 lookup on "Content" module 0x180080B33 call 0x18003D1A0 — registry lookup 0x180080B4D call 0x18001D2B0 — module notify/update

26.3 Language Index State

VA 0x1803C77B0 language_index (DWORD) 0 = English 1 = 简体中文 (Simplified Chinese) On language change, three things happen: the i18n content is refreshed via 0x18002A530, a config-preset dirty bit is set at [g_Config+0x15D8+0x103], and the “Content” module is notified via the standard CRC32/registry/notify triple (0x180011DF0, 0x18003D1A0, 0x18001D2B0). Two languages are supported in this build: English (default) and Simplified Chinese.

27. FreeCam Key Binding Display Panel (RVA 0x87A70–0x88606)

The documented FreeCam::Update function (RVA 0x871A0, see Ch.12.3) is 0x14C6 bytes long and includes a key-binding display section beginning at approximately 0x87A70 that was not previously described. This section renders four float-value sliders and eleven key-binding label rows using ImGui.

27.1 Float Sliders

Four consecutive DragFloat/SliderFloat controls appear before the key-binding rows, all using the ImGui slider variant at 0x180065570: RVA 0x3AFCB0 "Free Camera" — sub-panel BeginTab label RVA 0x3AF848 "ON / OFF" — toggle checkbox RVA 0x3AFCC0 "Move Speed" — DragFloat, fmt "%.3f" (0x3ADFB0) RVA 0x3AFCD0 "Look Sensitivity" — DragFloat, fmt "%.3f" RVA 0x3AFCE8 "Roll Speed" — DragFloat, fmt "%.3f" RVA 0x3AFCF8 "FOV Speed" — DragFloat, fmt "%.3f" RVA 0x3AFD04 "FOV" — DragFloat, fmt "%.1f" (0x3ADFEC)

27.2 Key Binding Label Rows

Eleven key-binding rows follow. Each row: (1) calls 0x18000FCB0 (MakeString) to format the label via 0x18005FB60 (sprintf-style, substituting the key name), (2) calls 0x18009D7D0 to render the resulting string as a tab-style label. Unbound keys display “NONE” (RVA 0x3AF820). RVA 0x3AFD08 "Forward Key: %s" — VA 0x180087A87 RVA 0x3AFD18 "Backward Key: %s" — VA 0x180087B1A (approx) RVA 0x3AFD30 "Left Key: %s" RVA 0x3AFD40 "Right Key: %s" RVA 0x3AFD50 "Up Key: %s" RVA 0x3AFD60 "Down Key: %s" RVA 0x3AFD70 "IncFOV Key: %s" RVA 0x3AFD80 "DecFOV Key: %s" RVA 0x3AFD90 "LeftRoll Key: %s" RVA 0x3AFDA8 "RightRoll Key: %s" RVA 0x3AFDC0 "ResetRoll Key: %s" RVA 0x3AF820 "NONE" — displayed for any unbound key

27.3 Dispatch Pattern

Each key row uses the same three-call sequence: MakeString (0x18000FCB0) to build the “Key Name: %s” format string, 0x18005FB60 to sprintf the current key name into it, and 0x18009D7D0 to render the result. The key name state block is at [rip+...] # 0x1803C6E98 (the “Pu;” RTTI sentinel in .data indicates the key-binding state array). This panel is visually shown as a collapsible key-rebinding display inside the FreeCam tab when enabled.

28. Settings Tab — Theme Selector and Console Toggle (RVA 0x9A4F0)

The Settings tab body function at RVA 0x18009A4F0 (source: SettingsTAB.cpp, RVA 0x3B0B30) renders a theme selector and a console toggle. It is called from sidebar case 5 (0x80D25). The function ends at approximately RVA 0x9AB31.

28.1 Theme Selector

A “Theme” combo-box (“Theme” at RVA 0x3B0AD4, rendered via ImGui::Combo at 0x180064220) presents four themes. Selecting a theme calls the corresponding palette-applicator function, which writes RRGGBBAA hex color strings from .rdata into the active ImGui color table. Theme name strings: RVA 0x3B0AF8 "Default" — applicator: RVA 0x941F0 (restores ImGui defaults) RVA 0x3B06D0 "Evangelion Unit 01" — applicator: RVA 0x94890 RVA 0x3B0AE0 "Evangelion Unit 02" — applicator: RVA 0x96770 RVA 0x3B0B10 "Matrix" — applicator: RVA 0x98650

28.2 Palette Color Tables

Each non-default theme applicator reads RRGGBBAA hex strings from .rdata and applies them to ImGui style slots. The colors below are listed in the order each applicator writes them (11 colors for Evangelion themes, 10 for Matrix): Evangelion Unit 01 (RVA 0x94890): 0x3B06F8 #FFFFFFFF 0x3B06E8 #7857A7FF 0x3B0718 #19171CFF 0x3B0708 #2A282EFF 0x3B0738 #2A282EE6 0x3B0728 #4DE6A5FF 0x3B0758 #00000000 0x3B0748 #4A455240 0x3B0778 #A38CCF80 0x3B0768 #7857A780 0x3B0798 #4A4552FF Evangelion Unit 02 (RVA 0x96770): 0x3B06F8 #FFFFFFFF 0x3B0898 #D9293BFF 0x3B0888 #1E1E1EFF 0x3B08B8 #3A3A3AFF 0x3B08A8 #3A3A3AE6 0x3B08D8 #F7B302FF 0x3B0758 #00000000 0x3B0748 #4A455240 0x3B08C8 #F7465880 0x3B08F8 #D9293B80 0x3B0798 #4A4552FF Matrix (RVA 0x98650): 0x3B09B8 #00FF41FF 0x3B09A8 #00AA2CFF 0x3B09D8 #000000FF 0x3B09C8 #0A0A0AFF 0x3B09F8 #0A0A0AE6 0x3B09E8 #004400FF 0x3B0758 #00000000 0x3B0A18 #00440040 0x3B0A08 #00881EFF 0x3B0A38 #00FF4180

28.2.1 Per-Slot Color Applicator Helper (RVA 0x94190)

Each individual color push in the three non-default theme applicators (0x94890, 0x96770, 0x98650) is performed by a shared helper at RVA 0x94190. This function reads an RRGGBBAA hex string from .rdata using __stdio_common_vsscanf (IAT[0xB1880]), converts it to a packed RGBA value, then calls ImGui::PushStyleColor (via 0x180010840) with the target style-slot index and the parsed colour. It is called 159 times across the four writer functions (52 times from 0x94890 alone, corresponding to the full 52-slot Default palette).

28.3 Console Toggle

After the theme selector, the function renders a “Toggle Console” checkbox (RVA 0x3B0B00) using CheckboxToggle (0x180085320). The console state is read and displayed via two branches: RVA 0x3B0B00 "Toggle Console" — checkbox label if console enabled: display format "Console {}" (RVA 0x3B0B78) using IAT AllocConsole (0x1800B1178) / GetStdHandle (0x1800B1628) if console disabled: display "enabled" (RVA 0x3B0B28) or "Disabled" (RVA 0x3B0B18)

28.4 Key Address Summary

RVA 0x9A4F0 SettingsTab::Render (this chapter) RVA 0x941F0 Default palette applicator RVA 0x94890 Evangelion Unit 01 palette applicator RVA 0x96770 Evangelion Unit 02 palette applicator RVA 0x98650 Matrix palette applicator RVA 0x3B0AD4 "Theme" combo label RVA 0x3B0B30 E:\git\Endfield_Cheeto...\SettingsTAB.cpp

29. Win32/D3D11 Overlay Window Initialisation (RVA 0x827A0–0x8375C)

The overlay window subsystem is a single large function at 0x827A0 (called from the startup function 0xA9190 at 0xA9585) with two sub-functions: FindGameWindow (0x835D0) and GetOverlayRect (0x836A0). It creates the transparent layered Win32 window, initialises a D3D11 device and swap chain, runs the Win32 message loop, and keeps the overlay aligned to the game window. Ch. 7 documents the WndProc at 0x826A0 (the window procedure registered by this subsystem); Ch. 15.5 documents the Present hook call site at 0x82F00 which lies inside the message loop body.

29.1 DPI Awareness Initialisation (0x827FF–0x82923)

The function opens with a TLS-guarded once_flag block before performing DPI setup. Two DPI APIs are tried in priority order. First, LoadLibraryA(‘user32.dll’) is called (via IAT[0xB10E0]) and GetProcAddress is used to locate SetThreadDpiAwarenessContext; if found, it is called with context value 0xFFFFFFFFFFFFFFFC (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2). If that fails, LoadLibraryA(‘shcore.dll’) and GetProcAddress resolve SetProcessDpiAwareness, which is then called with value 2 (PROCESS_PER_MONITOR_DPI_AWARE). If both dynamic lookups fail, the fallback is SetProcessDPIAware (IAT[0xB15A0]), a legacy API that sets system-DPI awareness. The guard at [.data+0x3C7440] / [.data+0x3C7448] ensures each path runs at most once.

29.2 Game Window Location and Window Class Registration (0x82924–0x82A28)

EnumWindows (IAT[0xB14A0]) is called with FindGameWindow (0x835D0) as the callback to locate the Unity game window. A WNDCLASSEX structure is then populated: CreateSolidBrush(0x7F00) (IAT[0xB1018]) sets the background brush to an opaque olive colour used only as a placeholder; LoadCursorW (IAT[0xB15C8]) provides the standard arrow cursor; two LoadIconW calls (IAT[0xB14E8]) load the small and large application icons. RegisterClassExW (IAT[0xB1638]) registers the class. GetSystemMetrics (IAT[0xB14E0]) is called twice to retrieve the full screen width (SM_CXSCREEN) and height (SM_CYSCREEN) for the initial window geometry.

29.3 Overlay Window and D3D11 Device Creation (0x82A29–0x82BFF)

CreateWindowExW (IAT[0xB1650]) creates the overlay window with WS_EX_LAYERED | WS_EX_TRANSPARENT style flags so it passes mouse input through to the game beneath it. SetLayeredWindowAttributes (IAT[0xB15E0]) sets the colour key and alpha. DwmExtendFrameIntoClientArea (IAT[0xB1918]) extends the DWM glass frame into the entire client area, which together with the layered attributes produces a fully transparent background. D3D11CreateDeviceAndSwapChain (IAT[0xB1908]) is called twice: the first call at 0x82B24 attempts D3D_FEATURE_LEVEL_11_0 with DXGI_FORMAT_R8G8B8A8_UNORM; on failure the second call at 0x82B7E retries with a DXGI_FORMAT_B8G8R8A8_UNORM swap chain as a fallback. After a successful device create, the compiled shader objects from Ch. 5 are bound. The helper 0x825B0 (called at 0x82B8C; documented in Ch. 7 as D3D11::Reinit) sets up the ImGui D3D11 backend. ShowWindow (IAT[0xB1628]) and UpdateWindow (IAT[0xB14D8]) make the window visible. CreateMutexA (IAT[0xB1720]) at 0x82C0D creates a named mutex to prevent duplicate overlay instances.

29.4 Initialisation Log and Message Loop (0x82C01–0x8352F)

Before entering the loop, the string ‘Initialized’ (RVA 0x3AF610) is logged at 0x82F5F from source file E:\git\Endfield_Cheeto\libraries\pipeline\hooks\UI.cpp. The main loop uses the standard Win32 pattern: PeekMessageW (IAT[0xB14D0]) / TranslateMessage (IAT[0xB14C8]) / DispatchMessageW (IAT[0xB14C0]). Each iteration calls FindWindowA(‘UnityWndClass’, NULL) (IAT[0xB14A8] called at 0x8301F) to verify the game process is still running; if the window disappears the loop exits. IsWindow (IAT[0xB1468]) validates the game HWND, GetWindowThreadProcessId (IAT[0xB1498]) retrieves its thread, and GetWindowRect (IAT[0xB1488]) reads its current bounds. SetWindowPos (IAT[0xB1588]) repositions the overlay to match the game window on every frame. GetForegroundWindow (IAT[0xB15F0]) and three GetClassNameA calls (IAT[0xB1490]) detect whether the game is the active foreground window and adjust the overlay visibility state via two SetWindowLongW calls (IAT[0xB15B0]). SwitchToThread (IAT[0xB1148]) at 0x8348A yields the CPU when the game is not in focus. On loop exit, DestroyWindow (IAT[0xB1570]) and UnregisterClassW (IAT[0xB1640]) clean up the overlay window and class.

29.5 FindGameWindow Callback (RVA 0x835D0)

This function is passed as the lpEnumFunc callback to EnumWindows. For each top-level window it calls GetWindowThreadProcessId (IAT[0xB1498]) and GetClassNameA (IAT[0xB1490]), then compares the class name against the literal string ‘UnityWndClass’ (RVA 0x3AF658) using the internal string-compare helper at 0xACA12. On a match it calls SetForegroundWindow (IAT[0xB1518]) to bring the game to the front, records the HWND, and then calls GetOverlayRect (0x836A0) to capture the initial window geometry. A second GetWindowThreadProcessId and AttachThreadInput call at 0x8368E synchronise the overlay thread’s input queue with the game thread.

29.6 GetOverlayRect (RVA 0x836A0)

Called by FindGameWindow and on every frame to compute the overlay rectangle. IsWindowVisible (IAT[0xB1480]) and IsIconic (IAT[0xB1510]) first check that the game window is visible and not minimised. DwmGetWindowAttribute (IAT[0xB1920]) with DWMWA_EXTENDED_FRAME_BOUNDS retrieves the DWM-adjusted window bounds (which exclude the invisible resize borders). GetClientRect (IAT[0xB15A8]) provides the inner client area. Two GetWindowLongPtrW calls (IAT[0xB1470]) read GWL_STYLE and GWL_EXSTYLE to account for window border widths. The function returns the final overlay RECT which SetWindowPos uses to position the overlay exactly over the game viewport.

29.7 Key Address Table

RVA 0x827A0 WinInit top-level entry (called from 0xA9585) RVA 0x827FF DPI init block TLS-guarded; tries SetThreadDpiAwarenessContext then SetProcessDpiAwareness RVA 0x82924 EnumWindows find game HWND via FindGameWindow callback RVA 0x8298B RegisterClassExW overlay window class registration RVA 0x82A29 CreateWindowExW WS_EX_LAYERED overlay window RVA 0x82A60 DwmExtendFrameIntoClientArea full transparent client area RVA 0x82B24 D3D11CreateDeviceAndSwapChain primary attempt (DXGI_FORMAT_R8G8B8A8_UNORM) RVA 0x82B7E D3D11CreateDeviceAndSwapChain fallback (DXGI_FORMAT_B8G8R8A8_UNORM) RVA 0x82C0D CreateMutexA single-instance guard mutex RVA 0x82F5F ‘Initialized’ log source: UI.cpp; emitted after device creation succeeds RVA 0x82F00 Present hook site documented in Ch. 15.5 RVA 0x8348A SwitchToThread yields when game is not in foreground RVA 0x835D0 FindGameWindow EnumWindows callback; locates ‘UnityWndClass’ HWND RVA 0x836A0 GetOverlayRect DwmGetWindowAttribute + GetClientRect; returns overlay RECT RVA 0x826A0 WndProc documented in Ch. 7

24. Final Analysis Summary

EF-Cheeto.dll (internal name, distributed as unityexplorer.dll) is a fully-featured Unity game cheat module for an IL2CPP-based game. The complete analysis across twenty-five chapters reveals the following architecture: Infrastructure Layer: D3D11 Present hook for overlay rendering, Win32 WndProc subclass for hotkeys, Toolhelp32 thread enumeration for safe code patching, MSVC-standard stack cookie security (no active anti-debug), D3DCompile for ImGui shaders, and _wfopen-based config persistence using nlohmann/json serialization. Hook Engine: Custom hook manager with FNV-1a hash table, trampoline allocation via VirtualAlloc, thread-safe patching via Suspend/Resume, and a 71-entry IL2CPP function pointer bypass table (GABypass). Cheat Modules (11 registered + 1 ghost): NoClip (CharacterController bypass), SkillHack (cooldown/cost IL2CPP hooks), FreeCam (CinemachineBrain camera override), FpsUnlocker (targetFrameRate), FPSModule (FPS counter overlay; see Ch. 20), SetDither (render setting), PlayerProfile (UI text injection), Vacuum (monster item pull), ESPModule (entity overlay, 10-color table; see Ch. 22), DamageHack (ghost — i18n only, no code; see Ch. 23), PreventScreenshot (registered; SetWindowDisplayAffinity). Configuration: 172-field g_Config struct at .data+0x1F70, per-version config writers for multiple game versions, auto-save timer at [state+0x2904], ImGui layout persistence via standard ini format. The binary is 3,956,736 bytes (0x3CE000), compiled with MSVC for x86-64 Windows, targeting IL2CPP Unity games. All twenty-five chapters together constitute a complete static reconstruction of the binary with no significant undocumented regions remaining.