Подписывайтесь на наш Telegram и не пропускайте важные новости! Перейти

Вопрос ESP

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
16 Сен 2025
Сообщения
41
Реакции
1
Через нейронку написал ESP, не рендерится. Дошли до логов:

Код:
Expand Collapse Copy
[*] CS2 Internal loading...

[+] client.dll: 0x7FFD71F20000

[+] Present hooked

[+] Ready. INSERT = menu, G = ESP, F1 = debug

=== DIAG ===

entList=0x3D8E5284800  lc=0x3D968F50600  lp=0x3D9A7090000

-- controllers (1..64) -> pawn handles --

[C04] ctrl=0x3D8E5F4F4CE team=0 ph=0x7453825C idx=604 ch=1 sl=92 pawn=0x0 hp=-1 life=-1 dorm=-1 org=0,0,0 name=remapper

-- chunk pointers used by pawn handles --

  chunk[1] = 0x0

-- localPawn index search (1..0x7FFF) --

localPawn not found in 1..0x7FFF

=== END DIAG ===

=== DIAG ===

entList=0x3D8E5284800  lc=0x3D968F50600  lp=0x3D9A7090000

-- controllers (1..64) -> pawn handles --

[C04] ctrl=0x3D8E5F4F4CE team=0 ph=0x7453825C idx=604 ch=1 sl=92 pawn=0x0 hp=-1 life=-1 dorm=-1 org=0,0,0 name=remapper

-- chunk pointers used by pawn handles --

  chunk[1] = 0x0

-- localPawn index search (1..0x7FFF) --

localPawn not found in 1..0x7FFF

=== END DIAG ===

Сам код дллки:

Код:
Expand Collapse Copy
#undef UNICODE
#undef _UNICODE

#include <Windows.h>
#include <d3d11.h>
#include <string>
#include <vector>
#include <thread>
#include <mutex>

#define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_dx11.h"

#include "framework/headers/includes.h"
#include "framework/gui.cpp"
#include "framework/helpers/config.cpp"
#include "framework/helpers/draw.cpp"
#include "framework/helpers/fonts.cpp"
#include "framework/helpers/popups.cpp"
#include "framework/widgets/helpers.cpp"
#include "framework/widgets/notify.cpp"
#include "framework/widgets/widgets.cpp"
#include "framework/widgets/window.cpp"

#include "memory.hpp"
#include "offsets.hpp"

#pragma comment(lib, "d3d11.lib")

// ---- Types ----
struct Vec3 { float x, y, z; };
struct Vec2 { float x, y; };
struct ViewMatrix { float m[4][4]; };

struct Player {
    Vec3        origin;
    Vec3        head;
    int         health;
    int         team;
    std::string name;
};

// ---- Globals ----
static ID3D11Device*           g_pDevice     = nullptr;
static ID3D11DeviceContext*    g_pCtx        = nullptr;
static ID3D11RenderTargetView* g_pRTV        = nullptr;
static IDXGISwapChain*         g_pSwapChain  = nullptr;
static HWND                    g_hWnd        = nullptr;
static bool                    g_ImGuiReady  = false;
static bool                    g_ShowDebug   = false;
static int                     g_Width       = 1920;
static int                     g_Height      = 1080;

static uintptr_t               g_clientBase  = 0;
static std::vector<Player>     g_players;
static ViewMatrix              g_vm{};
static std::mutex              g_playersMtx;

// ---- Present hook ----
using Present_t = HRESULT(__stdcall*)(IDXGISwapChain*, UINT, UINT);
static Present_t oPresent = nullptr;
static void**    g_pVTable = nullptr;

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM);
void RunDiag();
static WNDPROC g_oWndProc = nullptr;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (g_ImGuiReady) {
        if (msg == WM_KEYDOWN && wParam == VK_INSERT) {
            var->gui.opened = !var->gui.opened;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == 'G') {
            var->esp.enabled = !var->esp.enabled;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == VK_F1) {
            g_ShowDebug = !g_ShowDebug;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == VK_F2) {
            std::thread(RunDiag).detach();
            return true;
        }
        if (var->gui.opened && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
            return true;
    }
    return CallWindowProcA(g_oWndProc, hWnd, msg, wParam, lParam);
}

// ---- World to screen ----
bool W2S(const Vec3& pos, Vec2& out) {
    float w = g_vm.m[3][0]*pos.x + g_vm.m[3][1]*pos.y + g_vm.m[3][2]*pos.z + g_vm.m[3][3];
    if (w < 0.001f) return false;
    float x = g_vm.m[0][0]*pos.x + g_vm.m[0][1]*pos.y + g_vm.m[0][2]*pos.z + g_vm.m[0][3];
    float y = g_vm.m[1][0]*pos.x + g_vm.m[1][1]*pos.y + g_vm.m[1][2]*pos.z + g_vm.m[1][3];
    out.x = (g_Width  * 0.5f) + (g_Width  * 0.5f) * x / w;
    out.y = (g_Height * 0.5f) - (g_Height * 0.5f) * y / w;
    return true;
}

// ---- Read entities ----
static bool IsLikelyPtr(uintptr_t p) {
    return p > 0x10000 && p < 0x7FF000000000ULL;
}

static constexpr int kEntityIndexMask  = 0x7FFF;
static constexpr int kEntityChunkShift = 9;      // 512 entries per chunk
static constexpr int kEntityChunkSize  = 1 << kEntityChunkShift;
static constexpr int kEntityMaxIndex   = kEntityIndexMask;
static constexpr int kMaxControllers   = 64;
static constexpr uintptr_t kEntityStride     = 0x78;

struct EntityTraversalMode {
    const char* name;
    uintptr_t   chunkBaseOffset;
    uintptr_t   slotEntityOffset;
};

static constexpr EntityTraversalMode kEntityModes[] = {
    { "chunk+0x10 slot+0x00", 0x10, 0x00 },
    { "chunk+0x10 slot+0x10", 0x10, 0x10 },
    { "chunk+0x00 slot+0x00", 0x00, 0x00 },
    { "chunk+0x00 slot+0x10", 0x00, 0x10 },
};

static int  g_entityMode = 0;
static bool g_entityModeResolved = false;
static DWORD g_lastEntityModeProbeMs = 0;

static int IndexFromHandle(uint32_t handle) {
    return static_cast<int>(handle & kEntityIndexMask);
}

static int ChunkFromIndex(int index) {
    return (index & kEntityIndexMask) >> kEntityChunkShift;
}

static int SlotFromIndex(int index) {
    return index & (kEntityChunkSize - 1);
}

static uintptr_t GetEntityByIndexMode(uintptr_t entityList, int index, int mode) {
    if (!IsLikelyPtr(entityList)) return 0;
    if (mode < 0 || mode >= (int)(sizeof(kEntityModes) / sizeof(kEntityModes[0])))
        return 0;

    int maskedIndex = index & kEntityIndexMask;
    if (maskedIndex <= 0) return 0;

    const EntityTraversalMode& cfg = kEntityModes[mode];

    uintptr_t listEntry = Read<uintptr_t>(
        entityList + cfg.chunkBaseOffset + sizeof(uintptr_t) * ChunkFromIndex(maskedIndex)
    );
    if (!IsLikelyPtr(listEntry)) return 0;

    uintptr_t entity = Read<uintptr_t>(
        listEntry + kEntityStride * SlotFromIndex(maskedIndex) + cfg.slotEntityOffset
    );
    return IsLikelyPtr(entity) ? entity : 0;
}

static uintptr_t GetEntityByIndex(uintptr_t entityList, int index) {
    return GetEntityByIndexMode(entityList, index, g_entityMode);
}

static int FindEntityIndexByPtr(uintptr_t entityList, uintptr_t target, int mode, int minIndex, int maxIndex) {
    if (!IsLikelyPtr(entityList) || !IsLikelyPtr(target)) return -1;
    for (int i = minIndex; i <= maxIndex; ++i) {
        if (GetEntityByIndexMode(entityList, i, mode) == target)
            return i;
    }
    return -1;
}

static void ProbeEntityTraversalMode(uintptr_t entityList, uintptr_t localCtrl, uintptr_t localPawn, bool verbose) {
    if (!IsLikelyPtr(entityList) || !IsLikelyPtr(localCtrl) || !IsLikelyPtr(localPawn))
        return;

    int bestMode = -1;
    int bestScore = -1;
    int bestCtrlIdx = -1;
    int bestPawnIdx = -1;

    for (int mode = 0; mode < (int)(sizeof(kEntityModes) / sizeof(kEntityModes[0])); ++mode) {
        int ctrlIdx = FindEntityIndexByPtr(entityList, localCtrl, mode, 1, 2048);
        int pawnIdx = FindEntityIndexByPtr(entityList, localPawn, mode, 1, kEntityMaxIndex);
        int score = (ctrlIdx > 0 ? 1 : 0) + (pawnIdx > 0 ? 1 : 0);

        if (verbose) {
            printf("[mode %d] %-22s ctrlIdx=%d pawnIdx=%d score=%d\n",
                mode, kEntityModes[mode].name, ctrlIdx, pawnIdx, score);
        }

        if (score > bestScore) {
            bestScore = score;
            bestMode = mode;
            bestCtrlIdx = ctrlIdx;
            bestPawnIdx = pawnIdx;
        }
    }

    if (bestMode >= 0 && bestScore > 0) {
        g_entityMode = bestMode;
        g_entityModeResolved = true;
        if (verbose) {
            printf("[mode selected] %d (%s) ctrlIdx=%d pawnIdx=%d\n",
                bestMode, kEntityModes[bestMode].name, bestCtrlIdx, bestPawnIdx);
        }
    } else if (verbose) {
        printf("[mode selected] none (all candidates failed)\n");
    }
}

// Iterate player controllers, resolve pawns by m_hPlayerPawn handle.
void UpdatePlayers() {
    std::vector<Player> tmp;

    uintptr_t localCtrl = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    if (!IsLikelyPtr(localCtrl)) return;

    uint8_t   localTeam = Read<uint8_t>(localCtrl + offsets::m_iTeamNum);
    uintptr_t localPawn = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    uintptr_t entList   = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    if (!IsLikelyPtr(entList)) return;

    DWORD now = GetTickCount();
    if (!g_entityModeResolved || now - g_lastEntityModeProbeMs > 3000) {
        ProbeEntityTraversalMode(entList, localCtrl, localPawn, false);
        g_lastEntityModeProbeMs = now;
    }
    if (!g_entityModeResolved) return;

    for (int ctrlIdx = 1; ctrlIdx <= kMaxControllers; ++ctrlIdx) {
        uintptr_t ctrl = GetEntityByIndex(entList, ctrlIdx);
        if (!ctrl || ctrl == localCtrl) continue;

        uint8_t team = Read<uint8_t>(ctrl + offsets::m_iTeamNum);
        if (team != 2 && team != 3) continue;
        if (team == localTeam) continue;

        uint32_t pawnHandle = Read<uint32_t>(ctrl + offsets::m_hPlayerPawn);
        int pawnIdx = IndexFromHandle(pawnHandle);
        if (pawnIdx <= 0) continue;

        uintptr_t pawn = GetEntityByIndex(entList, pawnIdx);
        if (!pawn || pawn == localPawn) continue;

        int hp = Read<int>(pawn + offsets::m_iHealth);
        if (hp <= 0 || hp > 100) continue;
        if (Read<uint8_t>(pawn + offsets::m_lifeState) != 0) continue;

        uintptr_t node = Read<uintptr_t>(pawn + offsets::m_pGameSceneNode);
        if (!IsLikelyPtr(node)) continue;
        if (Read<bool>(node + offsets::m_bDormant)) continue;

        Vec3 origin = Read<Vec3>(node + offsets::m_vecAbsOrigin);

        Vec3 head = { origin.x, origin.y, origin.z + 75.f };
        std::string name = ReadString(ctrl + offsets::m_iszPlayerName, 128);
        tmp.push_back({ origin, head, hp, team, name });
    }

    std::lock_guard<std::mutex> lk(g_playersMtx);
    g_players = std::move(tmp);
}

// ---- Draw ESP ----
void DrawESP(ImDrawList* dl) {
    if (!var->esp.enabled) return;

    std::lock_guard<std::mutex> lk(g_playersMtx);
    for (auto& p : g_players) {
        Vec2 feet, head;
        if (!W2S(p.origin, feet)) continue;
        if (!W2S(p.head,   head))  continue;

        float h = feet.y - head.y;
        if (h < 5.f || h > (float)g_Height) continue;

        float w  = h / 2.f;
        float cx = (feet.x + head.x) * 0.5f;
        float hf = p.health / 100.f;

        ImU32 boxCol = IM_COL32(255, 50,  50,  220);
        ImU32 hpCol  = IM_COL32((int)(255*(1-hf)), (int)(255*hf), 0, 255);
        ImU32 white  = IM_COL32(255, 255, 255, 255);
        ImU32 black  = IM_COL32(0,   0,   0,   180);

        if (var->esp.boxes)
            dl->AddRect({ cx-w/2, head.y }, { cx+w/2, feet.y }, boxCol, 0.f, 0, 1.5f);

        if (var->esp.health_bar) {
            float bx   = cx - w/2 - 6;
            float fill = feet.y - h * hf;
            dl->AddRectFilled({ bx-2, head.y }, { bx+2, feet.y }, black);
            dl->AddRectFilled({ bx-2, fill   }, { bx+2, feet.y }, hpCol);
            if (var->esp.health_num) {
                char buf[8]; sprintf_s(buf, "%d", p.health);
                dl->AddText(nullptr, 11.f, { bx-14, fill-1 }, hpCol, buf);
            }
        }

        if (var->esp.names) {
            const char* n = p.name.empty() ? "unknown" : p.name.c_str();
            dl->AddText(nullptr, 13.f, { cx-w/2+1, head.y-16 }, black,  n);
            dl->AddText(nullptr, 13.f, { cx-w/2,   head.y-17 }, white,  n);
        }
    }
}

// ---- Debug overlay ----
void DrawDebug() {
    if (!g_ShowDebug) return;
    ImGui::SetNextWindowBgAlpha(0.85f);
    ImGui::SetNextWindowSize({ 360, 220 }, ImGuiCond_Once);
    ImGui::SetNextWindowPos({ (float)g_Width - 370.f, 10.f }, ImGuiCond_Once);
    ImGui::Begin("Debug [F1]", &g_ShowDebug);
    ImGui::Text("clientBase:  0x%llX", (unsigned long long)g_clientBase);
    uintptr_t el = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    uintptr_t lc = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    uintptr_t lp = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    ImGui::Text("entityList:  0x%llX", (unsigned long long)el);
    ImGui::Text("localCtrl:   0x%llX", (unsigned long long)lc);
    ImGui::Text("localPawn:   0x%llX", (unsigned long long)lp);
    ImGui::Text("entMode:     %s", g_entityModeResolved ? kEntityModes[g_entityMode].name : "unresolved");
    ImGui::Text("vmCheck:     %.4f", g_vm.m[0][0]);
    {
        std::lock_guard<std::mutex> lk(g_playersMtx);
        ImGui::Text("players:     %d", (int)g_players.size());
    }
    ImGui::Text("screen:      %dx%d", g_Width, g_Height);
    ImGui::Separator();
    if (el && lc) {
        uint8_t localTeamDbg = Read<uint8_t>(lc + offsets::m_iTeamNum);
        ImGui::Text("localTeam:   %d", (int)localTeamDbg);

        // Scan for first controller with a valid pawn handle.
        uintptr_t foundCtrl = 0; int foundIdx = -1;
        for (int i = 1; i <= kMaxControllers && !foundCtrl; ++i) {
            uintptr_t c = GetEntityByIndex(el, i);
            if (!c) continue;
            uint32_t ph = Read<uint32_t>(c + offsets::m_hPlayerPawn);
            if (IndexFromHandle(ph) > 0) {
                foundCtrl = c; foundIdx = i;
            }
        }

        ImGui::Text("firstCtrl:   [%d] 0x%llX", foundIdx, (unsigned long long)foundCtrl);
        if (foundCtrl) {
            uint8_t t = Read<uint8_t>(foundCtrl + offsets::m_iTeamNum);
            uint32_t ph = Read<uint32_t>(foundCtrl + offsets::m_hPlayerPawn);
            int pawnIdx = IndexFromHandle(ph);
            uintptr_t pw = GetEntityByIndex(el, pawnIdx);
            ImGui::Text("team:%d ph:0x%X idx:%d ch:%d sl:%d", (int)t, ph, pawnIdx, ChunkFromIndex(pawnIdx), SlotFromIndex(pawnIdx));
            ImGui::Text("pawn:        0x%llX", (unsigned long long)pw);
            if (pw) {
                uintptr_t nd = Read<uintptr_t>(pw + offsets::m_pGameSceneNode);
                Vec3 org = nd ? Read<Vec3>(nd + offsets::m_vecAbsOrigin) : Vec3{};
                ImGui::Text("hp: %d  life: %d  dormant: %d",
                    Read<int>(pw + offsets::m_iHealth),
                    (int)Read<uint8_t>(pw + offsets::m_lifeState),
                    nd ? (int)Read<bool>(nd + offsets::m_bDormant) : -1);
                ImGui::Text("origin: %.1f %.1f %.1f", org.x, org.y, org.z);
            }
        }
    }
    ImGui::End();
}

// ---- ImGui init ----
void InitImGui() {
    if (g_ImGuiReady) return;

    DXGI_SWAP_CHAIN_DESC sd{};
    g_pSwapChain->GetDesc(&sd);
    g_hWnd = sd.OutputWindow;

    g_pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&g_pDevice);
    g_pDevice->GetImmediateContext(&g_pCtx);

    ID3D11Texture2D* pBack = nullptr;
    g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBack);
    if (pBack) {
        D3D11_TEXTURE2D_DESC desc{};
        pBack->GetDesc(&desc);
        g_Width  = (int)desc.Width;
        g_Height = (int)desc.Height;
        g_pDevice->CreateRenderTargetView(pBack, nullptr, &g_pRTV);
        pBack->Release();
    }

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGui::GetIO().IniFilename = nullptr;
    ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
    ImGui_ImplWin32_Init(g_hWnd);
    ImGui_ImplDX11_Init(g_pDevice, g_pCtx);

    // Hook WndProc to get keyboard/mouse input
    g_oWndProc = (WNDPROC)SetWindowLongPtrA(g_hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc);

    cfg->init_config();

    // DPI for 2K
    int sh = GetSystemMetrics(SM_CYSCREEN);
    int dpi = (sh >= 2160) ? 175 : (sh >= 1440) ? 133 : 100;
    var->gui.stored_dpi  = dpi;
    var->gui.dpi_changed = true;
    var->gui.target_w    = var->gui.base_w * dpi / 100.f;
    var->gui.target_h    = var->gui.base_h * dpi / 100.f;

    g_ImGuiReady = true;
}

// ---- Hooked Present ----
static c_gui* g_gui = nullptr;

HRESULT __stdcall hkPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
    if (!g_pSwapChain) g_pSwapChain = pSwapChain;

    InitImGui();
    if (!g_ImGuiReady) return oPresent(pSwapChain, SyncInterval, Flags);

    // Keys handled in WndProc

    // Update VM
    g_vm = Read<ViewMatrix>(g_clientBase + offsets::dwViewMatrix);

    // Update RTV if needed (window resize)
    if (!g_pRTV) {
        ID3D11Texture2D* pBack = nullptr;
        pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBack);
        if (pBack) {
            D3D11_TEXTURE2D_DESC desc{};
            pBack->GetDesc(&desc);
            g_Width  = (int)desc.Width;
            g_Height = (int)desc.Height;
            g_pDevice->CreateRenderTargetView(pBack, nullptr, &g_pRTV);
            pBack->Release();
        }
    }

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    // Fullscreen ESP backdrop
    ImGui::SetNextWindowPos({ 0, 0 });
    ImGui::SetNextWindowSize({ (float)g_Width, (float)g_Height });
    ImGui::SetNextWindowBgAlpha(0.f);
    ImGui::Begin("##esp", nullptr,
        ImGuiWindowFlags_NoTitleBar     | ImGuiWindowFlags_NoResize |
        ImGuiWindowFlags_NoMove         | ImGuiWindowFlags_NoInputs |
        ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoScrollbar
    );
    DrawESP(ImGui::GetWindowDrawList());
    ImGui::End();

    if (g_gui) g_gui->render();
    DrawDebug();

    ImGui::Render();
    g_pCtx->OMSetRenderTargets(1, &g_pRTV, nullptr);
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    return oPresent(pSwapChain, SyncInterval, Flags);
}

// ---- VTable hook ----
bool HookPresent() {
    // Create dummy D3D11 device+swapchain to get vtable
    DXGI_SWAP_CHAIN_DESC sd{};
    sd.BufferCount        = 1;
    sd.BufferDesc.Format  = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow       = GetForegroundWindow();
    sd.SampleDesc.Count   = 1;
    sd.Windowed           = TRUE;
    sd.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;

    ID3D11Device*        pDev  = nullptr;
    ID3D11DeviceContext* pCtx  = nullptr;
    IDXGISwapChain*      pSC   = nullptr;
    D3D_FEATURE_LEVEL    fl;

    if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
        nullptr, 0, D3D11_SDK_VERSION, &sd, &pSC, &pDev, &fl, &pCtx)))
        return false;

    g_pVTable = *reinterpret_cast<void***>(pSC);

    // Unprotect vtable page and patch Present (index 8)
    DWORD old;
    VirtualProtect(&g_pVTable[8], sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
    oPresent = reinterpret_cast<Present_t>(g_pVTable[8]);
    g_pVTable[8] = reinterpret_cast<void*>(hkPresent);
    VirtualProtect(&g_pVTable[8], sizeof(void*), old, &old);

    pSC->Release();
    pDev->Release();
    pCtx->Release();
    return true;
}

// ---- Diagnostic (call on demand) ----
void RunDiag() {
    uintptr_t entList = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    uintptr_t lc      = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    uintptr_t lp      = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    printf("=== DIAG ===\n");
    printf("entList=0x%llX  lc=0x%llX  lp=0x%llX\n", entList, lc, lp);
    if (!IsLikelyPtr(entList)) { printf("entList NULL/invalid\n"); return; }

    bool usedChunks[64] = {};

    // Controllers live in low indices; pawns are resolved from handles.
    printf("-- controllers (1..%d) -> pawn handles --\n", kMaxControllers);
    for (int i = 1; i <= kMaxControllers; ++i) {
        uintptr_t ctrl = GetEntityByIndex(entList, i);
        if (!ctrl) continue;

        uint32_t pawnHandle = Read<uint32_t>(ctrl + offsets::m_hPlayerPawn);
        int pawnIdx = IndexFromHandle(pawnHandle);
        if (pawnIdx <= 0) continue;

        int chunk = ChunkFromIndex(pawnIdx);
        int slot  = SlotFromIndex(pawnIdx);
        if (chunk >= 0 && chunk < 64) usedChunks[chunk] = true;

        uintptr_t pawn = GetEntityByIndex(entList, pawnIdx);
        uint8_t team   = Read<uint8_t>(ctrl + offsets::m_iTeamNum);
        std::string name = ReadString(ctrl + offsets::m_iszPlayerName, 128);

        int hp = -1;
        int life = -1;
        int dorm = -1;
        Vec3 org{};
        if (pawn) {
            hp = Read<int>(pawn + offsets::m_iHealth);
            life = (int)Read<uint8_t>(pawn + offsets::m_lifeState);
            uintptr_t nd = Read<uintptr_t>(pawn + offsets::m_pGameSceneNode);
            if (IsLikelyPtr(nd)) {
                dorm = (int)Read<bool>(nd + offsets::m_bDormant);
                org = Read<Vec3>(nd + offsets::m_vecAbsOrigin);
            }
        }

        printf("[C%02d] ctrl=0x%llX team=%d ph=0x%X idx=%d ch=%d sl=%d pawn=0x%llX hp=%d life=%d dorm=%d org=%.0f,%.0f,%.0f name=%s\n",
            i, ctrl, (int)team, pawnHandle, pawnIdx, chunk, slot, pawn, hp, life, dorm, org.x, org.y, org.z, name.c_str());
    }

    printf("-- chunk pointers used by pawn handles --\n");
    for (int ch = 0; ch < 64; ++ch) {
        if (!usedChunks[ch]) continue;
        uintptr_t le = Read<uintptr_t>(entList + kEntityListOffset + sizeof(uintptr_t) * ch);
        printf("  chunk[%d] = 0x%llX\n", ch, le);
    }

    printf("-- localPawn index search (1..0x%X) --\n", kEntityMaxIndex);
    int localPawnIndex = -1;
    for (int i = 1; i <= kEntityMaxIndex; ++i) {
        if (GetEntityByIndex(entList, i) == lp) {
            localPawnIndex = i;
            break;
        }
    }
    if (localPawnIndex > 0) {
        printf("localPawn idx=%d ch=%d sl=%d\n",
            localPawnIndex, ChunkFromIndex(localPawnIndex), SlotFromIndex(localPawnIndex));
    } else {
        printf("localPawn not found in 1..0x%X\n", kEntityMaxIndex);
    }

    printf("=== END DIAG ===\n");
}

// ---- Entity reader thread ----
void ReaderThread() {
    while (true) {
        if (g_clientBase) UpdatePlayers();
        Sleep(10);
    }
}

// ---- DLL Entry ----
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID) {
    if (reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hInst);

        std::thread([]() {
            AllocConsole();
            FILE* f;
            freopen_s(&f, "CONOUT$", "w", stdout);
            printf("[*] CS2 Internal loading...\n");

            // Wait for client.dll
            while (!(g_clientBase = GetModuleBase("client.dll")))
                Sleep(500);
            printf("[+] client.dll: 0x%llX\n", (unsigned long long)g_clientBase);

            if (!HookPresent()) {
                printf("[-] HookPresent failed\n");
                return;
            }
            printf("[+] Present hooked\n");

            g_gui = new c_gui();

            std::thread(ReaderThread).detach();
            printf("[+] Ready. INSERT = menu, G = ESP, F1 = debug\n");
        }).detach();
    }

    if (reason == DLL_PROCESS_DETACH) {
        // Unhook
        if (g_pVTable && oPresent) {
            DWORD old;
            VirtualProtect(&g_pVTable[8], sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
            g_pVTable[8] = reinterpret_cast<void*>(oPresent);
            VirtualProtect(&g_pVTable[8], sizeof(void*), old, &old);
        }
        if (g_ImGuiReady) {
            if (g_oWndProc) SetWindowLongPtrA(g_hWnd, GWLP_WNDPROC, (LONG_PTR)g_oWndProc);
            ImGui_ImplDX11_Shutdown();
            ImGui_ImplWin32_Shutdown();
            ImGui::DestroyContext();
        }
        if (g_pRTV) g_pRTV->Release();
    }

    return TRUE;
}

Перепробовали много всего. В чем заключается проблема? Умные люди помогите, пожалуйста
 
Через нейронку написал ESP, не рендерится. Дошли до логов:

Код:
Expand Collapse Copy
[*] CS2 Internal loading...

[+] client.dll: 0x7FFD71F20000

[+] Present hooked

[+] Ready. INSERT = menu, G = ESP, F1 = debug

=== DIAG ===

entList=0x3D8E5284800  lc=0x3D968F50600  lp=0x3D9A7090000

-- controllers (1..64) -> pawn handles --

[C04] ctrl=0x3D8E5F4F4CE team=0 ph=0x7453825C idx=604 ch=1 sl=92 pawn=0x0 hp=-1 life=-1 dorm=-1 org=0,0,0 name=remapper

-- chunk pointers used by pawn handles --

  chunk[1] = 0x0

-- localPawn index search (1..0x7FFF) --

localPawn not found in 1..0x7FFF

=== END DIAG ===

=== DIAG ===

entList=0x3D8E5284800  lc=0x3D968F50600  lp=0x3D9A7090000

-- controllers (1..64) -> pawn handles --

[C04] ctrl=0x3D8E5F4F4CE team=0 ph=0x7453825C idx=604 ch=1 sl=92 pawn=0x0 hp=-1 life=-1 dorm=-1 org=0,0,0 name=remapper

-- chunk pointers used by pawn handles --

  chunk[1] = 0x0

-- localPawn index search (1..0x7FFF) --

localPawn not found in 1..0x7FFF

=== END DIAG ===

Сам код дллки:

Код:
Expand Collapse Copy
#undef UNICODE
#undef _UNICODE

#include <Windows.h>
#include <d3d11.h>
#include <string>
#include <vector>
#include <thread>
#include <mutex>

#define IMGUI_DEFINE_MATH_OPERATORS
#include "imgui/imgui.h"
#include "imgui/imgui_impl_win32.h"
#include "imgui/imgui_impl_dx11.h"

#include "framework/headers/includes.h"
#include "framework/gui.cpp"
#include "framework/helpers/config.cpp"
#include "framework/helpers/draw.cpp"
#include "framework/helpers/fonts.cpp"
#include "framework/helpers/popups.cpp"
#include "framework/widgets/helpers.cpp"
#include "framework/widgets/notify.cpp"
#include "framework/widgets/widgets.cpp"
#include "framework/widgets/window.cpp"

#include "memory.hpp"
#include "offsets.hpp"

#pragma comment(lib, "d3d11.lib")

// ---- Types ----
struct Vec3 { float x, y, z; };
struct Vec2 { float x, y; };
struct ViewMatrix { float m[4][4]; };

struct Player {
    Vec3        origin;
    Vec3        head;
    int         health;
    int         team;
    std::string name;
};

// ---- Globals ----
static ID3D11Device*           g_pDevice     = nullptr;
static ID3D11DeviceContext*    g_pCtx        = nullptr;
static ID3D11RenderTargetView* g_pRTV        = nullptr;
static IDXGISwapChain*         g_pSwapChain  = nullptr;
static HWND                    g_hWnd        = nullptr;
static bool                    g_ImGuiReady  = false;
static bool                    g_ShowDebug   = false;
static int                     g_Width       = 1920;
static int                     g_Height      = 1080;

static uintptr_t               g_clientBase  = 0;
static std::vector<Player>     g_players;
static ViewMatrix              g_vm{};
static std::mutex              g_playersMtx;

// ---- Present hook ----
using Present_t = HRESULT(__stdcall*)(IDXGISwapChain*, UINT, UINT);
static Present_t oPresent = nullptr;
static void**    g_pVTable = nullptr;

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND, UINT, WPARAM, LPARAM);
void RunDiag();
static WNDPROC g_oWndProc = nullptr;

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    if (g_ImGuiReady) {
        if (msg == WM_KEYDOWN && wParam == VK_INSERT) {
            var->gui.opened = !var->gui.opened;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == 'G') {
            var->esp.enabled = !var->esp.enabled;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == VK_F1) {
            g_ShowDebug = !g_ShowDebug;
            return true;
        }
        if (msg == WM_KEYDOWN && wParam == VK_F2) {
            std::thread(RunDiag).detach();
            return true;
        }
        if (var->gui.opened && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam))
            return true;
    }
    return CallWindowProcA(g_oWndProc, hWnd, msg, wParam, lParam);
}

// ---- World to screen ----
bool W2S(const Vec3& pos, Vec2& out) {
    float w = g_vm.m[3][0]*pos.x + g_vm.m[3][1]*pos.y + g_vm.m[3][2]*pos.z + g_vm.m[3][3];
    if (w < 0.001f) return false;
    float x = g_vm.m[0][0]*pos.x + g_vm.m[0][1]*pos.y + g_vm.m[0][2]*pos.z + g_vm.m[0][3];
    float y = g_vm.m[1][0]*pos.x + g_vm.m[1][1]*pos.y + g_vm.m[1][2]*pos.z + g_vm.m[1][3];
    out.x = (g_Width  * 0.5f) + (g_Width  * 0.5f) * x / w;
    out.y = (g_Height * 0.5f) - (g_Height * 0.5f) * y / w;
    return true;
}

// ---- Read entities ----
static bool IsLikelyPtr(uintptr_t p) {
    return p > 0x10000 && p < 0x7FF000000000ULL;
}

static constexpr int kEntityIndexMask  = 0x7FFF;
static constexpr int kEntityChunkShift = 9;      // 512 entries per chunk
static constexpr int kEntityChunkSize  = 1 << kEntityChunkShift;
static constexpr int kEntityMaxIndex   = kEntityIndexMask;
static constexpr int kMaxControllers   = 64;
static constexpr uintptr_t kEntityStride     = 0x78;

struct EntityTraversalMode {
    const char* name;
    uintptr_t   chunkBaseOffset;
    uintptr_t   slotEntityOffset;
};

static constexpr EntityTraversalMode kEntityModes[] = {
    { "chunk+0x10 slot+0x00", 0x10, 0x00 },
    { "chunk+0x10 slot+0x10", 0x10, 0x10 },
    { "chunk+0x00 slot+0x00", 0x00, 0x00 },
    { "chunk+0x00 slot+0x10", 0x00, 0x10 },
};

static int  g_entityMode = 0;
static bool g_entityModeResolved = false;
static DWORD g_lastEntityModeProbeMs = 0;

static int IndexFromHandle(uint32_t handle) {
    return static_cast<int>(handle & kEntityIndexMask);
}

static int ChunkFromIndex(int index) {
    return (index & kEntityIndexMask) >> kEntityChunkShift;
}

static int SlotFromIndex(int index) {
    return index & (kEntityChunkSize - 1);
}

static uintptr_t GetEntityByIndexMode(uintptr_t entityList, int index, int mode) {
    if (!IsLikelyPtr(entityList)) return 0;
    if (mode < 0 || mode >= (int)(sizeof(kEntityModes) / sizeof(kEntityModes[0])))
        return 0;

    int maskedIndex = index & kEntityIndexMask;
    if (maskedIndex <= 0) return 0;

    const EntityTraversalMode& cfg = kEntityModes[mode];

    uintptr_t listEntry = Read<uintptr_t>(
        entityList + cfg.chunkBaseOffset + sizeof(uintptr_t) * ChunkFromIndex(maskedIndex)
    );
    if (!IsLikelyPtr(listEntry)) return 0;

    uintptr_t entity = Read<uintptr_t>(
        listEntry + kEntityStride * SlotFromIndex(maskedIndex) + cfg.slotEntityOffset
    );
    return IsLikelyPtr(entity) ? entity : 0;
}

static uintptr_t GetEntityByIndex(uintptr_t entityList, int index) {
    return GetEntityByIndexMode(entityList, index, g_entityMode);
}

static int FindEntityIndexByPtr(uintptr_t entityList, uintptr_t target, int mode, int minIndex, int maxIndex) {
    if (!IsLikelyPtr(entityList) || !IsLikelyPtr(target)) return -1;
    for (int i = minIndex; i <= maxIndex; ++i) {
        if (GetEntityByIndexMode(entityList, i, mode) == target)
            return i;
    }
    return -1;
}

static void ProbeEntityTraversalMode(uintptr_t entityList, uintptr_t localCtrl, uintptr_t localPawn, bool verbose) {
    if (!IsLikelyPtr(entityList) || !IsLikelyPtr(localCtrl) || !IsLikelyPtr(localPawn))
        return;

    int bestMode = -1;
    int bestScore = -1;
    int bestCtrlIdx = -1;
    int bestPawnIdx = -1;

    for (int mode = 0; mode < (int)(sizeof(kEntityModes) / sizeof(kEntityModes[0])); ++mode) {
        int ctrlIdx = FindEntityIndexByPtr(entityList, localCtrl, mode, 1, 2048);
        int pawnIdx = FindEntityIndexByPtr(entityList, localPawn, mode, 1, kEntityMaxIndex);
        int score = (ctrlIdx > 0 ? 1 : 0) + (pawnIdx > 0 ? 1 : 0);

        if (verbose) {
            printf("[mode %d] %-22s ctrlIdx=%d pawnIdx=%d score=%d\n",
                mode, kEntityModes[mode].name, ctrlIdx, pawnIdx, score);
        }

        if (score > bestScore) {
            bestScore = score;
            bestMode = mode;
            bestCtrlIdx = ctrlIdx;
            bestPawnIdx = pawnIdx;
        }
    }

    if (bestMode >= 0 && bestScore > 0) {
        g_entityMode = bestMode;
        g_entityModeResolved = true;
        if (verbose) {
            printf("[mode selected] %d (%s) ctrlIdx=%d pawnIdx=%d\n",
                bestMode, kEntityModes[bestMode].name, bestCtrlIdx, bestPawnIdx);
        }
    } else if (verbose) {
        printf("[mode selected] none (all candidates failed)\n");
    }
}

// Iterate player controllers, resolve pawns by m_hPlayerPawn handle.
void UpdatePlayers() {
    std::vector<Player> tmp;

    uintptr_t localCtrl = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    if (!IsLikelyPtr(localCtrl)) return;

    uint8_t   localTeam = Read<uint8_t>(localCtrl + offsets::m_iTeamNum);
    uintptr_t localPawn = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    uintptr_t entList   = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    if (!IsLikelyPtr(entList)) return;

    DWORD now = GetTickCount();
    if (!g_entityModeResolved || now - g_lastEntityModeProbeMs > 3000) {
        ProbeEntityTraversalMode(entList, localCtrl, localPawn, false);
        g_lastEntityModeProbeMs = now;
    }
    if (!g_entityModeResolved) return;

    for (int ctrlIdx = 1; ctrlIdx <= kMaxControllers; ++ctrlIdx) {
        uintptr_t ctrl = GetEntityByIndex(entList, ctrlIdx);
        if (!ctrl || ctrl == localCtrl) continue;

        uint8_t team = Read<uint8_t>(ctrl + offsets::m_iTeamNum);
        if (team != 2 && team != 3) continue;
        if (team == localTeam) continue;

        uint32_t pawnHandle = Read<uint32_t>(ctrl + offsets::m_hPlayerPawn);
        int pawnIdx = IndexFromHandle(pawnHandle);
        if (pawnIdx <= 0) continue;

        uintptr_t pawn = GetEntityByIndex(entList, pawnIdx);
        if (!pawn || pawn == localPawn) continue;

        int hp = Read<int>(pawn + offsets::m_iHealth);
        if (hp <= 0 || hp > 100) continue;
        if (Read<uint8_t>(pawn + offsets::m_lifeState) != 0) continue;

        uintptr_t node = Read<uintptr_t>(pawn + offsets::m_pGameSceneNode);
        if (!IsLikelyPtr(node)) continue;
        if (Read<bool>(node + offsets::m_bDormant)) continue;

        Vec3 origin = Read<Vec3>(node + offsets::m_vecAbsOrigin);

        Vec3 head = { origin.x, origin.y, origin.z + 75.f };
        std::string name = ReadString(ctrl + offsets::m_iszPlayerName, 128);
        tmp.push_back({ origin, head, hp, team, name });
    }

    std::lock_guard<std::mutex> lk(g_playersMtx);
    g_players = std::move(tmp);
}

// ---- Draw ESP ----
void DrawESP(ImDrawList* dl) {
    if (!var->esp.enabled) return;

    std::lock_guard<std::mutex> lk(g_playersMtx);
    for (auto& p : g_players) {
        Vec2 feet, head;
        if (!W2S(p.origin, feet)) continue;
        if (!W2S(p.head,   head))  continue;

        float h = feet.y - head.y;
        if (h < 5.f || h > (float)g_Height) continue;

        float w  = h / 2.f;
        float cx = (feet.x + head.x) * 0.5f;
        float hf = p.health / 100.f;

        ImU32 boxCol = IM_COL32(255, 50,  50,  220);
        ImU32 hpCol  = IM_COL32((int)(255*(1-hf)), (int)(255*hf), 0, 255);
        ImU32 white  = IM_COL32(255, 255, 255, 255);
        ImU32 black  = IM_COL32(0,   0,   0,   180);

        if (var->esp.boxes)
            dl->AddRect({ cx-w/2, head.y }, { cx+w/2, feet.y }, boxCol, 0.f, 0, 1.5f);

        if (var->esp.health_bar) {
            float bx   = cx - w/2 - 6;
            float fill = feet.y - h * hf;
            dl->AddRectFilled({ bx-2, head.y }, { bx+2, feet.y }, black);
            dl->AddRectFilled({ bx-2, fill   }, { bx+2, feet.y }, hpCol);
            if (var->esp.health_num) {
                char buf[8]; sprintf_s(buf, "%d", p.health);
                dl->AddText(nullptr, 11.f, { bx-14, fill-1 }, hpCol, buf);
            }
        }

        if (var->esp.names) {
            const char* n = p.name.empty() ? "unknown" : p.name.c_str();
            dl->AddText(nullptr, 13.f, { cx-w/2+1, head.y-16 }, black,  n);
            dl->AddText(nullptr, 13.f, { cx-w/2,   head.y-17 }, white,  n);
        }
    }
}

// ---- Debug overlay ----
void DrawDebug() {
    if (!g_ShowDebug) return;
    ImGui::SetNextWindowBgAlpha(0.85f);
    ImGui::SetNextWindowSize({ 360, 220 }, ImGuiCond_Once);
    ImGui::SetNextWindowPos({ (float)g_Width - 370.f, 10.f }, ImGuiCond_Once);
    ImGui::Begin("Debug [F1]", &g_ShowDebug);
    ImGui::Text("clientBase:  0x%llX", (unsigned long long)g_clientBase);
    uintptr_t el = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    uintptr_t lc = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    uintptr_t lp = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    ImGui::Text("entityList:  0x%llX", (unsigned long long)el);
    ImGui::Text("localCtrl:   0x%llX", (unsigned long long)lc);
    ImGui::Text("localPawn:   0x%llX", (unsigned long long)lp);
    ImGui::Text("entMode:     %s", g_entityModeResolved ? kEntityModes[g_entityMode].name : "unresolved");
    ImGui::Text("vmCheck:     %.4f", g_vm.m[0][0]);
    {
        std::lock_guard<std::mutex> lk(g_playersMtx);
        ImGui::Text("players:     %d", (int)g_players.size());
    }
    ImGui::Text("screen:      %dx%d", g_Width, g_Height);
    ImGui::Separator();
    if (el && lc) {
        uint8_t localTeamDbg = Read<uint8_t>(lc + offsets::m_iTeamNum);
        ImGui::Text("localTeam:   %d", (int)localTeamDbg);

        // Scan for first controller with a valid pawn handle.
        uintptr_t foundCtrl = 0; int foundIdx = -1;
        for (int i = 1; i <= kMaxControllers && !foundCtrl; ++i) {
            uintptr_t c = GetEntityByIndex(el, i);
            if (!c) continue;
            uint32_t ph = Read<uint32_t>(c + offsets::m_hPlayerPawn);
            if (IndexFromHandle(ph) > 0) {
                foundCtrl = c; foundIdx = i;
            }
        }

        ImGui::Text("firstCtrl:   [%d] 0x%llX", foundIdx, (unsigned long long)foundCtrl);
        if (foundCtrl) {
            uint8_t t = Read<uint8_t>(foundCtrl + offsets::m_iTeamNum);
            uint32_t ph = Read<uint32_t>(foundCtrl + offsets::m_hPlayerPawn);
            int pawnIdx = IndexFromHandle(ph);
            uintptr_t pw = GetEntityByIndex(el, pawnIdx);
            ImGui::Text("team:%d ph:0x%X idx:%d ch:%d sl:%d", (int)t, ph, pawnIdx, ChunkFromIndex(pawnIdx), SlotFromIndex(pawnIdx));
            ImGui::Text("pawn:        0x%llX", (unsigned long long)pw);
            if (pw) {
                uintptr_t nd = Read<uintptr_t>(pw + offsets::m_pGameSceneNode);
                Vec3 org = nd ? Read<Vec3>(nd + offsets::m_vecAbsOrigin) : Vec3{};
                ImGui::Text("hp: %d  life: %d  dormant: %d",
                    Read<int>(pw + offsets::m_iHealth),
                    (int)Read<uint8_t>(pw + offsets::m_lifeState),
                    nd ? (int)Read<bool>(nd + offsets::m_bDormant) : -1);
                ImGui::Text("origin: %.1f %.1f %.1f", org.x, org.y, org.z);
            }
        }
    }
    ImGui::End();
}

// ---- ImGui init ----
void InitImGui() {
    if (g_ImGuiReady) return;

    DXGI_SWAP_CHAIN_DESC sd{};
    g_pSwapChain->GetDesc(&sd);
    g_hWnd = sd.OutputWindow;

    g_pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&g_pDevice);
    g_pDevice->GetImmediateContext(&g_pCtx);

    ID3D11Texture2D* pBack = nullptr;
    g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBack);
    if (pBack) {
        D3D11_TEXTURE2D_DESC desc{};
        pBack->GetDesc(&desc);
        g_Width  = (int)desc.Width;
        g_Height = (int)desc.Height;
        g_pDevice->CreateRenderTargetView(pBack, nullptr, &g_pRTV);
        pBack->Release();
    }

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGui::GetIO().IniFilename = nullptr;
    ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
    ImGui_ImplWin32_Init(g_hWnd);
    ImGui_ImplDX11_Init(g_pDevice, g_pCtx);

    // Hook WndProc to get keyboard/mouse input
    g_oWndProc = (WNDPROC)SetWindowLongPtrA(g_hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc);

    cfg->init_config();

    // DPI for 2K
    int sh = GetSystemMetrics(SM_CYSCREEN);
    int dpi = (sh >= 2160) ? 175 : (sh >= 1440) ? 133 : 100;
    var->gui.stored_dpi  = dpi;
    var->gui.dpi_changed = true;
    var->gui.target_w    = var->gui.base_w * dpi / 100.f;
    var->gui.target_h    = var->gui.base_h * dpi / 100.f;

    g_ImGuiReady = true;
}

// ---- Hooked Present ----
static c_gui* g_gui = nullptr;

HRESULT __stdcall hkPresent(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
    if (!g_pSwapChain) g_pSwapChain = pSwapChain;

    InitImGui();
    if (!g_ImGuiReady) return oPresent(pSwapChain, SyncInterval, Flags);

    // Keys handled in WndProc

    // Update VM
    g_vm = Read<ViewMatrix>(g_clientBase + offsets::dwViewMatrix);

    // Update RTV if needed (window resize)
    if (!g_pRTV) {
        ID3D11Texture2D* pBack = nullptr;
        pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBack);
        if (pBack) {
            D3D11_TEXTURE2D_DESC desc{};
            pBack->GetDesc(&desc);
            g_Width  = (int)desc.Width;
            g_Height = (int)desc.Height;
            g_pDevice->CreateRenderTargetView(pBack, nullptr, &g_pRTV);
            pBack->Release();
        }
    }

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    // Fullscreen ESP backdrop
    ImGui::SetNextWindowPos({ 0, 0 });
    ImGui::SetNextWindowSize({ (float)g_Width, (float)g_Height });
    ImGui::SetNextWindowBgAlpha(0.f);
    ImGui::Begin("##esp", nullptr,
        ImGuiWindowFlags_NoTitleBar     | ImGuiWindowFlags_NoResize |
        ImGuiWindowFlags_NoMove         | ImGuiWindowFlags_NoInputs |
        ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoScrollbar
    );
    DrawESP(ImGui::GetWindowDrawList());
    ImGui::End();

    if (g_gui) g_gui->render();
    DrawDebug();

    ImGui::Render();
    g_pCtx->OMSetRenderTargets(1, &g_pRTV, nullptr);
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    return oPresent(pSwapChain, SyncInterval, Flags);
}

// ---- VTable hook ----
bool HookPresent() {
    // Create dummy D3D11 device+swapchain to get vtable
    DXGI_SWAP_CHAIN_DESC sd{};
    sd.BufferCount        = 1;
    sd.BufferDesc.Format  = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferUsage        = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow       = GetForegroundWindow();
    sd.SampleDesc.Count   = 1;
    sd.Windowed           = TRUE;
    sd.SwapEffect         = DXGI_SWAP_EFFECT_DISCARD;

    ID3D11Device*        pDev  = nullptr;
    ID3D11DeviceContext* pCtx  = nullptr;
    IDXGISwapChain*      pSC   = nullptr;
    D3D_FEATURE_LEVEL    fl;

    if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0,
        nullptr, 0, D3D11_SDK_VERSION, &sd, &pSC, &pDev, &fl, &pCtx)))
        return false;

    g_pVTable = *reinterpret_cast<void***>(pSC);

    // Unprotect vtable page and patch Present (index 8)
    DWORD old;
    VirtualProtect(&g_pVTable[8], sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
    oPresent = reinterpret_cast<Present_t>(g_pVTable[8]);
    g_pVTable[8] = reinterpret_cast<void*>(hkPresent);
    VirtualProtect(&g_pVTable[8], sizeof(void*), old, &old);

    pSC->Release();
    pDev->Release();
    pCtx->Release();
    return true;
}

// ---- Diagnostic (call on demand) ----
void RunDiag() {
    uintptr_t entList = Read<uintptr_t>(g_clientBase + offsets::dwEntityList);
    uintptr_t lc      = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerController);
    uintptr_t lp      = Read<uintptr_t>(g_clientBase + offsets::dwLocalPlayerPawn);
    printf("=== DIAG ===\n");
    printf("entList=0x%llX  lc=0x%llX  lp=0x%llX\n", entList, lc, lp);
    if (!IsLikelyPtr(entList)) { printf("entList NULL/invalid\n"); return; }

    bool usedChunks[64] = {};

    // Controllers live in low indices; pawns are resolved from handles.
    printf("-- controllers (1..%d) -> pawn handles --\n", kMaxControllers);
    for (int i = 1; i <= kMaxControllers; ++i) {
        uintptr_t ctrl = GetEntityByIndex(entList, i);
        if (!ctrl) continue;

        uint32_t pawnHandle = Read<uint32_t>(ctrl + offsets::m_hPlayerPawn);
        int pawnIdx = IndexFromHandle(pawnHandle);
        if (pawnIdx <= 0) continue;

        int chunk = ChunkFromIndex(pawnIdx);
        int slot  = SlotFromIndex(pawnIdx);
        if (chunk >= 0 && chunk < 64) usedChunks[chunk] = true;

        uintptr_t pawn = GetEntityByIndex(entList, pawnIdx);
        uint8_t team   = Read<uint8_t>(ctrl + offsets::m_iTeamNum);
        std::string name = ReadString(ctrl + offsets::m_iszPlayerName, 128);

        int hp = -1;
        int life = -1;
        int dorm = -1;
        Vec3 org{};
        if (pawn) {
            hp = Read<int>(pawn + offsets::m_iHealth);
            life = (int)Read<uint8_t>(pawn + offsets::m_lifeState);
            uintptr_t nd = Read<uintptr_t>(pawn + offsets::m_pGameSceneNode);
            if (IsLikelyPtr(nd)) {
                dorm = (int)Read<bool>(nd + offsets::m_bDormant);
                org = Read<Vec3>(nd + offsets::m_vecAbsOrigin);
            }
        }

        printf("[C%02d] ctrl=0x%llX team=%d ph=0x%X idx=%d ch=%d sl=%d pawn=0x%llX hp=%d life=%d dorm=%d org=%.0f,%.0f,%.0f name=%s\n",
            i, ctrl, (int)team, pawnHandle, pawnIdx, chunk, slot, pawn, hp, life, dorm, org.x, org.y, org.z, name.c_str());
    }

    printf("-- chunk pointers used by pawn handles --\n");
    for (int ch = 0; ch < 64; ++ch) {
        if (!usedChunks[ch]) continue;
        uintptr_t le = Read<uintptr_t>(entList + kEntityListOffset + sizeof(uintptr_t) * ch);
        printf("  chunk[%d] = 0x%llX\n", ch, le);
    }

    printf("-- localPawn index search (1..0x%X) --\n", kEntityMaxIndex);
    int localPawnIndex = -1;
    for (int i = 1; i <= kEntityMaxIndex; ++i) {
        if (GetEntityByIndex(entList, i) == lp) {
            localPawnIndex = i;
            break;
        }
    }
    if (localPawnIndex > 0) {
        printf("localPawn idx=%d ch=%d sl=%d\n",
            localPawnIndex, ChunkFromIndex(localPawnIndex), SlotFromIndex(localPawnIndex));
    } else {
        printf("localPawn not found in 1..0x%X\n", kEntityMaxIndex);
    }

    printf("=== END DIAG ===\n");
}

// ---- Entity reader thread ----
void ReaderThread() {
    while (true) {
        if (g_clientBase) UpdatePlayers();
        Sleep(10);
    }
}

// ---- DLL Entry ----
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID) {
    if (reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hInst);

        std::thread([]() {
            AllocConsole();
            FILE* f;
            freopen_s(&f, "CONOUT$", "w", stdout);
            printf("[*] CS2 Internal loading...\n");

            // Wait for client.dll
            while (!(g_clientBase = GetModuleBase("client.dll")))
                Sleep(500);
            printf("[+] client.dll: 0x%llX\n", (unsigned long long)g_clientBase);

            if (!HookPresent()) {
                printf("[-] HookPresent failed\n");
                return;
            }
            printf("[+] Present hooked\n");

            g_gui = new c_gui();

            std::thread(ReaderThread).detach();
            printf("[+] Ready. INSERT = menu, G = ESP, F1 = debug\n");
        }).detach();
    }

    if (reason == DLL_PROCESS_DETACH) {
        // Unhook
        if (g_pVTable && oPresent) {
            DWORD old;
            VirtualProtect(&g_pVTable[8], sizeof(void*), PAGE_EXECUTE_READWRITE, &old);
            g_pVTable[8] = reinterpret_cast<void*>(oPresent);
            VirtualProtect(&g_pVTable[8], sizeof(void*), old, &old);
        }
        if (g_ImGuiReady) {
            if (g_oWndProc) SetWindowLongPtrA(g_hWnd, GWLP_WNDPROC, (LONG_PTR)g_oWndProc);
            ImGui_ImplDX11_Shutdown();
            ImGui_ImplWin32_Shutdown();
            ImGui::DestroyContext();
        }
        if (g_pRTV) g_pRTV->Release();
    }

    return TRUE;
}

Перепробовали много всего. В чем заключается проблема? Умные люди помогите, пожалуйста
фух, исправил. проблема была в обходе entity list, IsLikelyPtr был сломан и валидные адреса ломал (отбрасывал), изза этого client + dwEntityList вообще не попадал в проверку
 
Назад
Сверху Снизу