Blog / esp-overlay · · 11 min read · Signed KyTech Research

ESP and Wallhacks: How Cheat Overlays Actually Render Enemy Positions

World-to-screen math, three overlay architectures, and why external rendering wins against modern anti-cheat integrity scans.

ESP, short for Extra-Sensory Perception, is the oldest visible cheat class in competitive gaming and still the most misunderstood. Every box, skeleton, health bar, and snapline you have ever seen in a cheat clip is the same three-step pipeline: read an entity list, project a 3D world coordinate onto the 2D screen, and draw a primitive at that pixel. The interesting engineering is not the drawing. It is where the drawing happens and how it stays off the anti-cheat radar in 2026. This post walks through the math, the three canonical overlay architectures, and the trade-offs that pushed KyTech to standardize on external rendering across every product line.

The pipeline in one paragraph

A cheat needs four things to draw a box around an enemy: the player entity list, a world position for each entity (usually the bone origin or bounding box corners), the game's current view-projection matrix, and a rendering surface to draw on. The entity list and view matrix come from game memory. The projection is pure math. The rendering surface is where the architecture diverges, and it is where anti-cheat wins or loses.

World-to-screen: the math is not optional

Every 3D engine composes a view matrix (camera orientation and position) with a projection matrix (FOV, aspect ratio, near/far planes) into a single 4x4 matrix, commonly called the View-Projection or WVP matrix. To project a world point onto the screen, multiply the point (as a homogeneous 4D vector) by that matrix, perform the perspective divide, and remap NDC coordinates into pixel space.

Below is the exact function shape shipped inside every KyTech ESP module. It matches the row-major layout Source 2, Unreal, and modern Frostbite all expose. Depth check gates the draw so nothing renders behind the camera.

struct Vec3 { float x, y, z; };
struct Vec2 { float x, y; };

// matrix is 16 floats, row-major, as read from the game's view struct
bool WorldToScreen(const Vec3& world,
                   const float matrix[16],
                   int screenW, int screenH,
                   Vec2& out)
{
    // multiply world (as vec4 with w=1) by the row-major VP matrix
    float clipX = world.x * matrix[0] + world.y * matrix[1]
                + world.z * matrix[2]  + matrix[3];
    float clipY = world.x * matrix[4] + world.y * matrix[5]
                + world.z * matrix[6]  + matrix[7];
    float clipW = world.x * matrix[12] + world.y * matrix[13]
                + world.z * matrix[14] + matrix[15];

    if (clipW < 0.001f) return false; // behind the camera

    // perspective divide -> normalized device coords in [-1, 1]
    float ndcX = clipX / clipW;
    float ndcY = clipY / clipW;

    // remap NDC to pixel space, flipping Y (screen origin is top-left)
    out.x = (screenW  * 0.5f) + (ndcX * screenW  * 0.5f);
    out.y = (screenH * 0.5f)  - (ndcY * screenH * 0.5f);
    return true;
}

That is the entire secret of ESP. Every clip you have ever seen of a cheater with glowing boxes calls a variant of this function once per bone per frame. The rest of this post is about where and how the resulting Vec2 gets drawn.

Architecture 1: internal DirectX or Vulkan hook

The classical approach, and the one every public-source cheat used for a decade. The cheat DLL is injected into the game process. It resolves the swapchain's Present vtable slot (index 8 in DXGI, index 10 in D3D11 device context), overwrites the pointer with a detour, and calls the original after drawing its own ImGui or bare-D3D primitives. On Vulkan, maintained by the Khronos Group, the hook lives on vkQueuePresentKHR or a captured VkCommandBuffer.

The read side is trivial because the cheat runs inside the target: no ReadProcessMemory, no IPC, just direct pointer dereferences on the game's own address space.

// simplified DXGI Present hook flow
typedef HRESULT(__stdcall* Present_t)(IDXGISwapChain*, UINT, UINT);
Present_t oPresent = nullptr;

HRESULT __stdcall HookedPresent(IDXGISwapChain* sc, UINT sync, UINT flags)
{
    static bool init = false;
    if (!init) {
        InitImGui(sc);         // create backbuffer RTV, ImGui context
        init = true;
    }
    ImGui_ImplDX11_NewFrame();
    ImGui::NewFrame();
    RenderEsp();               // world-to-screen + ImGui draw lists
    ImGui::Render();
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
    return oPresent(sc, sync, flags);
}

Fast, integrated, low-latency. Also the loudest possible target. Every modern anti-cheat scans loaded modules with NtQuerySystemInformation class 11 (SystemModuleInformation), walks the PEB Ldr list, hashes .text sections of DirectX DLLs, and enumerates thread start addresses via NtQueryInformationThread. EasyAntiCheat (Epic acquired the original Kamu team in 2018) and BattlEye both do all of the above and cross-check against ETW Microsoft-Windows-Kernel-Process events. Riot Vanguard, which mandated TPM 2.0 on League of Legends in early 2024 after already requiring it for Valorant, goes further and hashes the D3D11 ID3D11DeviceContext vtable itself. An internal hook flips at least one of those bytes.

You can hide the hook (allocate the trampoline outside any module, use hardware breakpoints, patch inside a legitimate JIT region), but every mitigation is now a signature. This architecture is legacy for a reason.

Architecture 2: external layered overlay window

The one KyTech uses across Apex, CS2, Overwatch 2, Black Ops 7, Forza Horizon 6, and Roblox. A second process, running independently, creates a transparent click-through window on top of the game and renders its own DirectX 11 scene into it. The read side is a signed kernel driver providing MmCopyVirtualMemory-backed reads out of the target process.

The window itself is the trick. Windows exposes exactly the primitives needed, all documented against SetWindowLong and the extended window styles:

// create the overlay window
HWND hwnd = CreateWindowExW(
    WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,
    L"KyTechOverlayClass", L"", WS_POPUP,
    0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
    nullptr, nullptr, hInstance, nullptr);

// per-pixel alpha via UpdateLayeredWindow, or a colorkey for cheap draws
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);

// hide from WDA_MONITOR / screenshot APIs and from WTS session enumeration
SetWindowDisplayAffinity(hwnd, WDA_EXCLUDEFROMCAPTURE); // Win 10 2004+

WS_EX_LAYERED combined with WS_EX_TRANSPARENT gives a window that composites via DWM and passes every mouse click straight through to the game beneath. WS_EX_NOACTIVATE keeps focus in the game so no alt-tab happens when the overlay updates. SetWindowDisplayAffinity(WDA_EXCLUDEFROMCAPTURE), introduced in Windows 10 build 19041, hides the window from BitBlt, PrintWindow, IDXGIOutputDuplication, and any DWM thumbnail. Anti-cheat screenshot uploads see clean game frames.

On top of that HWND lives a normal Direct3D 11 device with a flip-model swapchain in windowed mode. Drawing is standard ImGui or a hand-rolled primitive batch. The critical property: none of this touches the game process. No CreateRemoteThread, no LoadLibrary, no vtable patch, no allocation inside the game address space. The game process's PEB, its loaded modules, its thread list, its .text hashes are pristine.

Communication with the driver is a single DeviceIoControl per read batch:

struct KyReadRequest {
    uint32_t targetPid;
    uint64_t srcAddress;
    uint64_t dstBuffer;   // in caller's address space
    uint32_t size;
};

DeviceIoControl(hDriver, IOCTL_KY_READ,
                &req, sizeof(req), nullptr, 0, &returned, nullptr);

The driver validates the request, resolves the target EPROCESS via PsLookupProcessByProcessId, and calls MmCopyVirtualMemory with KernelMode access, which the memory manager treats as a legitimate cross-process copy rather than a page-fault-inducing user read. No API imported by the game (ReadProcessMemory, NtReadVirtualMemory) is invoked. From the game's perspective, nobody read its memory.

Architecture 3: DMA and hardware overlay

The truly paranoid split the machine in half. A second PC runs a PCIe DMA card (Squirrel, LeetDMA, various clones of the original Ultra-DMA design) that reads the target machine's RAM without any driver on the target at all. The reader PC does the world-to-screen math and drives a hardware video mixer or a second monitor that overlays graphics onto the game display via HDMI capture-and-composite.

The target machine runs zero cheat software. Not a driver, not a DLL, not a thread. Every kernel-mode anti-cheat scan on the target sees a virgin system. This is the architecture that survived the Windows 11 24H2 MiShowBadMapper rework that killed most physical-memory substrate signed-third-party-driver chains by refusing NonCached aliases on WB kernel pages. DMA hardware bypasses MmMapIoSpace entirely because the read never touches the kernel.

Trade-offs: real money for the DMA card, an entire second computer, HDMI capture latency (typically one to two frames on a hardware mixer, more on a software one), and no aim assist unless you also route mouse input through an Arduino or a KMBox-style HID emulator.

Occlusion: knowing when a wall is in the way

An ESP that draws every enemy regardless of walls is a wallhack. An ESP that only draws visible enemies is called "visible check" and is much harder to spot in demo review. Two ways to get it:

  1. Read the game's own visibility bit. Source 2, Unreal, and idTech all maintain a per-entity "visible to local player" flag updated by the server for network-culling decisions. On CS2 (build 10000+ as of the 2026 armor rework, memory layout covered in our CS2 reverse engineering writeup), the flag lives at a stable offset on the player pawn and flips true when the client's PVS solver believes the entity is drawable.
  2. Client-side raycast. The cheat casts a ray from the local player's eye position to the enemy bone through the game's own trace function (usually exported for the projectile system) and checks the resulting CGameTrace for a solid hit fraction less than 1.0.

Option 1 is cheaper and matches what a legit player could theoretically see. Option 2 is more general but calls into game code, which internal hooks reach trivially and external overlays cannot. External architectures typically reimplement the BSP or nav-mesh trace using the map file loaded independently.

Anti-detection: why external wins in 2026

Here is the comparison that drives every architecture decision.

Detection vector Internal hook External overlay DMA reader
Loaded module scan Fails (DLL is present) Passes Passes
Thread start address enum Fails (hook thread) Passes Passes
DirectX vtable hash Fails Passes Passes
.text section integrity Fails Passes Passes
ReadProcessMemory logging Passes Passes (kernel read) Passes
ETW Threat-Intel provider Handle-open flagged Passes Passes
HVCI / VBS attack surface Direct hit Driver only None on target
Screenshot upload Overlay in frame WDA_EXCLUDEFROMCAPTURE Not on target frame
Hardware attestation (TPM PCR) Passes Passes Passes

The external overlay is the sweet spot. It gives you full ImGui rendering, real-time updates, and a clean game process, without needing a second computer and a DMA card. The kernel driver is the only piece with attack surface, and hardening the driver (no arbitrary MDL mapping, no MmMapIoSpace on kernel-owned pages, strict caller-context checks, session-bound handles) is a solved problem once you accept the Windows 11 24H2 constraints documented across the Windows Driver Kit reference.

Overlay coordinate space, drawn in ASCII

The mental model that trips up most first-time overlay authors:

game monitor (1920 x 1080)
+---------------------------------------------------+
| (0,0)                                             |
|                                                   |
|          o  <- enemy world pos projected          |
|         /|\    to (950, 420) via WorldToScreen    |
|        / | \                                      |
|                                                   |
|   overlay HWND covers the entire desktop,         |
|   transparent, click-through, drawn by a          |
|   separate process. Same D3D swapchain            |
|   resolution as the game's fullscreen mode        |
|   so no scaling math is required.                 |
|                                                   |
|                                (1920, 1080)       |
+---------------------------------------------------+
     ^
     |
     +-- KyTech overlay process (D3D11 flip-model)
         reads entity list via IOCTL to signed driver
         WorldToScreen(entity, gameVP, 1920, 1080) -> Vec2
         ImGui::GetForegroundDrawList()->AddRect(...)

The overlay swapchain must run at the same resolution and refresh rate the game presents at, or the projected pixel coordinates land off by a scaling factor. Borderless fullscreen makes this trivial. Exclusive fullscreen forces the overlay to a lower Z-order and requires either DWM composition tricks or, in the worst case, dropping to a hardware overlay plane via IDCompositionDevice.

Common failure modes

Three bugs every ESP author has shipped at least once:

  1. Boxes floating one frame behind the enemy. The view matrix and the entity positions were read in different memory snapshots. Fix: snapshot both under a single driver IOCTL, or interpolate positions using velocity vectors.
  2. Boxes drawn behind the camera. Missing or wrong clipW sign check. Enemies behind the player project to negative-W clip space and end up mirrored on-screen.
  3. Y-axis flipped. The screen origin is top-left in Windows, bottom-left in OpenGL NDC. The remap step must subtract the Y term, not add it.

How KyTech handles this

Every KyTech product ships the external overlay architecture described in section 2. The choice is deliberate and predates the Windows 11 24H2 kernel mitigations that broke a generation of physical-memory-mapping signed-third-party-driver chains. When we founded KyTech in 2025, the two of us agreed the cheat DLL model was already dead against Vanguard-tier anti-cheat and would be dead against everything else within two years. That call has held up.

The stack we ship: a single signed kernel driver providing MmCopyVirtualMemory-backed reads out of the target process, a per-title user-mode overlay executable that creates a WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE window with WDA_EXCLUDEFROMCAPTURE set, and a shared ImGui rendering layer that draws boxes, skeletons, health bars, and item ESP for Apex Legends (S25 2026), CS2, Overwatch 2, Black Ops 7, Forza Horizon 6, and Roblox. The game process is never touched. Aim assist, when enabled, runs through a separate mouse input path covered in our aim assist internals writeup.

Loader hardening and driver load are managed by our HWID spoofer (currently in Apex-only beta), which handles the vulnerable-driver-blocklist dance and the DSE state check before mapping the KyTech driver. The reference build of this external overlay architecture ships as KyTech Apex, where every rendering primitive discussed above runs in production against Respawn's live anti-cheat stack. Everything else is available on the purchase page. The design brief has not changed since day one: the game's own integrity scans should see a clean process, because they are looking at one.

Signed by KyTech Research

We still play these games and we still push every build in production. If something in here is wrong, and eventually something will be, ping us in Discord and we will fix it.

Enough theory. get in.

The loader is one click away. Ring-0 kernel driver, polymorphic per download, memory-only injection. Six games across VAC, EAC, Ricochet, Byfron, and Warden.

Get in ›