Code on a screen representing Source 2 cheat development

How to Build an ESP Hack for Counter-Strike 2 Using Source 2 SDK

February 19, 2026 · Counter Strike 2

Building an ESP (Extra Sensory Perception) hack for Counter-Strike 2 is one of the most rewarding projects a cheat developer can tackle. The Source 2 engine introduces significant changes from its predecessor, and understanding its memory layout is essential for creating a reliable, performant wallhack. In this guide, we'll walk through the entire process — from reading game memory to rendering boxes on screen — with real pseudocode, math, and architecture decisions you'll need to make along the way.

Code on a computer screen representing cheat development

If you already sell cheats on CheatBay or you're looking to start, CS2 ESP is a fantastic first product. It's in massive demand, relatively stable across updates, and pairs well with other features like aimbot and triggerbot that you can upsell later.

Understanding the Source 2 Engine Architecture

Source 2 is Valve's second-generation engine, and CS2 is its flagship title. Unlike Source 1 (CS:GO), Source 2 uses a completely different entity system built around a schema-based approach. Here's what matters for cheat development:

Key Modules

  • client.dll — Contains the client-side game classes, entity definitions, and rendering logic. This is your primary target.
  • engine2.dll — The core engine, manages the game loop, networking, and world state.
  • schemasystem.dll — Source 2's reflection/schema system that describes class layouts at runtime.
  • rendersystemdx11.dll / rendersystemvulkan.dll — The rendering backends.

The schema system is a game-changer for reverse engineering. Unlike CS:GO where you had to manually find offsets through signature scanning, Source 2 exposes class metadata through its schema system. Tools like Source2Gen can dump the entire SDK automatically.

Entity System: CEntityInstance and CCSPlayerController

In Source 2, entities are managed through a global entity list. The key structures are:

// Simplified entity list structure
// Base: client.dll + dwEntityList

struct CEntityIdentity {
    CEntityInstance* m_pEntity;    // 0x00
    uint64_t padding[2];
    int m_iHandle;                 // 0x18 - Entity handle (index + serial)
    // ... more fields
};

struct CEntityIdentityList {
    CEntityIdentity* m_pIdentities; // Array of entity identities
};

// To iterate entities:
// 1. Read dwEntityList from client.dll
// 2. For each index 0..63 (max players in CS2):
//    a. Read the identity chunk: entityList + 0x8 * (index >> 9) + 0x10
//    b. Read the entity from chunk: chunk + 0x78 * (index & 0x1FF)

This two-level indirection (chunks of entity identities) is different from CS:GO's flat entity list. Getting this traversal right is the foundation of your ESP.

The CCSPlayerController vs CCSPlayerPawn Split

CS2 separates player data into two objects:

  • CCSPlayerController — Contains metadata: player name, team, score, whether they're alive. Found directly in the entity list.
  • CCSPlayerPawn — Contains the physical player: position, health, armor, bones, velocity. Referenced from the controller via m_hPlayerPawn.
// Getting from controller to pawn:
CCSPlayerController* controller = GetEntityByIndex(i);
uint32_t pawnHandle = Read<uint32_t>(controller + offsets::m_hPlayerPawn);

// Convert handle to entity index
uint32_t pawnIndex = pawnHandle & 0x7FFF;
CCSPlayerPawn* pawn = GetEntityByIndex(pawnIndex);

// Now read position
Vector3 position = Read<Vector3>(pawn + offsets::m_vOldOrigin);
int health = Read<int>(pawn + offsets::m_iHealth);
int team = Read<int>(controller + offsets::m_iTeamNum);

This controller/pawn split trips up a lot of beginners. If you're only reading the entity list and trying to get positions directly from the controller, you'll get garbage data.

Finding Offsets: The Schema System Approach

One of Source 2's gifts to cheat developers is the schema system. Instead of tedious signature scanning for every offset, you can dump them programmatically:

// The schema system exposes class metadata
// SchemaSystem_001 interface from schemasystem.dll

// Each class has a SchemaClassBinding with:
// - Class name (e.g., "CCSPlayerPawn")
// - Parent class
// - Fields array with name, offset, and type

// Community tools like cs2-dumper automatically extract these
// Output example:
// namespace client_dll {
//     namespace CCSPlayerPawn {
//         constexpr uint32_t m_vOldOrigin = 0x1274;
//         constexpr uint32_t m_iHealth = 0x334;
//         constexpr uint32_t m_ArmorValue = 0x1548;
//     }
// }

Projects like cs2-dumper automate this process and publish updated offsets after every CS2 update. As a cheat developer, you should either run the dumper yourself or integrate automatic offset updating into your cheat's loader.

Matrix-style code representing memory analysis

World-to-Screen Projection: The Math Behind ESP

Once you have entity positions in 3D world coordinates, you need to project them onto the player's 2D screen. This is the core math of any ESP hack.

The View Matrix

The view matrix (also called the view-projection matrix) is a 4x4 matrix that transforms 3D world coordinates to clip space. In CS2, it's located at:

// client.dll + dwViewMatrix
// This is a 4x4 float matrix (16 floats, 64 bytes)

struct ViewMatrix {
    float m[4][4];
};

ViewMatrix vm = Read<ViewMatrix>(clientBase + offsets::dwViewMatrix);

World-to-Screen Function

bool WorldToScreen(Vector3 world, Vector2& screen, ViewMatrix vm, int screenW, int screenH) {
    // Multiply world position by view matrix
    float w = vm.m[3][0] * world.x + vm.m[3][1] * world.y + vm.m[3][2] * world.z + vm.m[3][3];

    // If w is negative or near zero, the point is behind the camera
    if (w < 0.001f)
        return false;

    float invW = 1.0f / w;

    // Calculate normalized device coordinates
    float x = (vm.m[0][0] * world.x + vm.m[0][1] * world.y + vm.m[0][2] * world.z + vm.m[0][3]) * invW;
    float y = (vm.m[1][0] * world.x + vm.m[1][1] * world.y + vm.m[1][2] * world.z + vm.m[1][3]) * invW;

    // Convert to screen coordinates
    screen.x = (screenW / 2.0f) + (x * screenW / 2.0f);
    screen.y = (screenH / 2.0f) - (y * screenH / 2.0f);

    return true;
}

This function is the heart of every ESP. The math comes from standard 3D graphics — the view matrix encodes the camera's position, rotation, and perspective projection all in one. The w component handles perspective division, which is why objects further away appear smaller.

Drawing Bounding Boxes

For a basic ESP box, you need the player's feet position and head position. In CS2:

Vector3 feetPos = Read<Vector3>(pawn + offsets::m_vOldOrigin);
Vector3 headPos = feetPos;
headPos.z += 75.0f; // Approximate standing height

// For crouching players, check the flags:
uint32_t flags = Read<uint32_t>(pawn + offsets::m_fFlags);
if (flags & FL_DUCKING)
    headPos.z = feetPos.z + 54.0f;

Vector2 screenFeet, screenHead;
if (WorldToScreen(feetPos, screenFeet, viewMatrix, screenW, screenH) &&
    WorldToScreen(headPos, screenHead, viewMatrix, screenW, screenH)) {

    float boxHeight = screenFeet.y - screenHead.y;
    float boxWidth = boxHeight * 0.45f; // Approximate aspect ratio

    DrawRect(screenHead.x - boxWidth/2, screenHead.y,
             boxWidth, boxHeight, teamColor);

    // Health bar
    float healthFrac = health / 100.0f;
    DrawFilledRect(screenHead.x - boxWidth/2 - 4, screenHead.y,
                   2, boxHeight * healthFrac, healthColor);
}

Rendering Approaches: External vs Internal

This is one of the most important architectural decisions you'll make. It affects detection risk, performance, and development complexity.

External Overlay

An external ESP runs as a separate process and draws on a transparent overlay window positioned on top of the game:

  • Pros: Doesn't inject into the game process. Harder for anti-cheat to detect via module scanning. Easier to develop and debug.
  • Cons: Higher latency (memory reads across process boundaries). Overlay window can be detected. Some anti-cheats hook window enumeration APIs.
  • Tech stack: DirectX overlay with WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST window styles. Libraries like ImGui + DirectX 11 make this straightforward.
// Basic overlay window setup (Win32)
HWND gameWindow = FindWindowA(NULL, "Counter-Strike 2");
RECT gameRect;
GetWindowRect(gameWindow, &gameRect);

// Create transparent overlay
HWND overlay = CreateWindowExA(
    WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOPMOST,
    "OverlayClass", "",
    WS_POPUP,
    gameRect.left, gameRect.top,
    gameRect.right - gameRect.left,
    gameRect.bottom - gameRect.top,
    NULL, NULL, hInstance, NULL
);

SetLayeredWindowAttributes(overlay, RGB(0,0,0), 0, LWA_COLORKEY);

Internal Rendering (DirectX/Vulkan Hooking)

Internal ESP injects a DLL into the game process and hooks the rendering pipeline directly:

  • Pros: Zero latency. Can access game structures directly (no RPM calls). Smoother rendering.
  • Cons: DLL injection is heavily monitored by anti-cheat. Module in game process is detectable. Crashes can corrupt game state.
  • Approach: Hook IDXGISwapChain::Present (DX11) or vkQueuePresentKHR (Vulkan) to intercept the rendering pipeline and draw your ESP before the frame is presented.
// DX11 Present hook pattern
typedef HRESULT(__stdcall* PresentFn)(IDXGISwapChain*, UINT, UINT);
PresentFn oPresent = nullptr;

HRESULT __stdcall hkPresent(IDXGISwapChain* swapChain, UINT syncInterval, UINT flags) {
    // Initialize ImGui on first call
    if (!initialized) {
        ID3D11Device* device;
        swapChain->GetDevice(__uuidof(ID3D11Device), (void**)&device);
        device->GetImmediateContext(&context);
        ImGui_ImplDX11_Init(device, context);
        initialized = true;
    }

    // Begin ImGui frame
    ImGui_ImplDX11_NewFrame();
    ImGui::NewFrame();

    // Draw ESP here
    DrawESP();

    ImGui::Render();
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    return oPresent(swapChain, syncInterval, flags);
}

VAC (Valve Anti-Cheat) Considerations

VAC is Valve's proprietary anti-cheat for CS2. Understanding how it works helps you avoid detection:

How VAC Detects Cheats

  • Module scanning: VAC periodically scans loaded modules in the game process. Any unknown DLL is flagged. This is why internal cheats need to either manually map (no PE headers) or erase their module entry from the PEB.
  • Signature scanning: VAC maintains a database of known cheat signatures (byte patterns). Polymorphic code and string encryption help evade this.
  • Memory integrity: VAC can check if game code has been modified (hooks). Using hardware breakpoints or VEH (Vectored Exception Handling) hooks instead of inline hooks avoids this.
  • API monitoring: Calls to ReadProcessMemory, OpenProcess, and similar APIs can be flagged when targeting the game process.

Evasion Strategies

  • External approach with kernel-level memory reading: Use a custom driver to read game memory instead of ReadProcessMemory. This bypasses user-mode API monitoring entirely.
  • Manual mapping: Instead of LoadLibrary, manually map your DLL into the game process. Don't link it in the module list. Zero out PE headers after mapping.
  • Heartbeat spoofing: VAC sends periodic integrity checks. Understanding the heartbeat protocol lets you respond with clean results while your cheat runs.
  • String encryption: Use compile-time string encryption (XOR, AES) so your binary doesn't contain readable strings that could be signature-matched.

Putting It All Together: Architecture of a Production ESP

Here's how a production-grade CS2 ESP should be structured:

// Architecture overview:
//
// [Loader Process]
//   |
//   ├── Authenticates with license server
//   ├── Downloads latest offsets from your update server
//   ├── Maps driver (if kernel-level)
//   └── Launches cheat
//
// [Cheat Process / DLL]
//   |
//   ├── Memory Reader (RPM or kernel driver)
//   ├── Entity Manager
//   │   ├── Iterates entity list every frame
//   │   ├── Filters by team, alive status
//   │   └── Caches entity data (position, health, etc.)
//   ├── Math Engine
//   │   ├── World-to-screen projection
//   │   └── Distance calculations
//   └── Renderer
//       ├── External overlay OR hooked Present
//       ├── Box ESP, name ESP, health bars
//       └── Configurable via in-game menu

Advanced Features to Add

Once your basic ESP is working, these features dramatically increase the value of your product:

  • Skeleton/Bone ESP: Read the bone matrix from CSkeletonInstance and draw lines between joint positions. Much more informative than boxes.
  • Glow/Chams: Modify material properties to make players visible through walls with colored outlines.
  • Dropped weapon ESP: Iterate non-player entities to show weapon locations on the ground.
  • Sound ESP: Visualize footstep directions using the game's sound event system.
  • Radar hack: Draw a minimap overlay showing all player positions from a top-down perspective.

Each of these features can be toggled independently, giving users fine-grained control and helping them stay undetected.

Performance Optimization

A laggy ESP is an unsellable ESP. Key optimizations:

  • Batch memory reads: Instead of calling RPM for every field individually, read entire structures at once. One ReadProcessMemory call for 200 bytes is faster than 10 calls for 20 bytes each.
  • Cache entity data: Only update entity positions every frame. Update names and other static data less frequently.
  • Minimize draw calls: Use instanced rendering or batched draw lists (ImGui handles this well).
  • Thread separation: Run memory reading on a separate thread from rendering. Use double-buffering for entity data.

Selling Your CS2 ESP on CheatBay

Once your ESP is stable, tested, and has a clean detection record, it's time to monetize. CheatBay is the premier marketplace for cheat developers to sell their products:

  • Zero listing fees: List your CS2 ESP with no upfront costs.
  • Crypto payments: CheatBay handles Bitcoin and Lightning Network payments, so you never deal with chargebacks.
  • Subscription management: Set up recurring billing for your cheat — daily, weekly, or monthly plans.
  • Built-in reputation system: Buyers leave reviews, and your detection-free track record builds trust.
  • Instant payouts: Get paid directly to your BTC wallet.

Top CS2 ESP sellers on CheatBay earn consistent monthly income. The key is keeping your cheat updated after game patches (usually within 24-48 hours) and maintaining an active presence in your product's support channel.

Ready to start selling? Create your seller account on CheatBay and list your CS2 ESP today. Join hundreds of developers already earning from their skills.

Ready to Level Up?

Browse verified, undetected cheats on CheatBay — or start selling your own and earn crypto.

Browse Cheats Start Selling