【C++】從零開始的CS:GO逆向分析3——寫出一個透視

【C++】從零開始的CS:GO逆向分析3——寫出一個透視本篇內容包括:
1. 透視實現的方法介紹
2. 通過進程名獲取進程id和進程句柄
3. 通過進程id獲取進程中的模塊信息(模塊大小 , 模塊地址 , 模塊句柄)
4. 讀取游戲內存(人物ViewMatrix , 敵人坐標,敵人生命值,敵人陣營)
5. 三維坐標轉二維坐標(游戲內人物坐標轉換成屏幕上的坐標)
6. glfw+imgui 在屏幕上的繪制直線
請先依據前兩篇,對偏移、基址有基本了解 , 并且配置好了glfw+imgui的環境,在上篇創建好的工程中創建CPP文件和同名.h文件

【C++】從零開始的CS:GO逆向分析3——寫出一個透視

文章插圖
實現效果:
【C++】從零開始的CS:GO逆向分析3——寫出一個透視

文章插圖
透視實現的方法介紹一般有兩種方式,一種是外掛,一種是內掛,外掛是在創建一個透明窗口,在透明窗口上畫線,讓鼠標事件透過窗口,透明窗口覆蓋在游戲窗口上 。內掛是通過DLL注入,HOOK游戲中的繪制函數,在游戲繪制人物的時候繪制自己的線 。還剩一種比較少用,但也可以實現,找到人物模型ID,在渲染到人物模型的時候關掉渲染緩沖(應該是叫這個?) , 使人物模型在墻模型前面渲染,導致可以直接看到人物 。本篇文章采用的是外掛的形式 , 根據上篇文章已經可以創建出一個覆蓋在屏幕上的透明窗口 。
先把需要用到的全局變量聲明一下(GetImformation.cpp)變量名起的挺明白的,就不寫注釋了
DWORD g_process_id = NULL;HANDLE g_process_handle = NULL;UINT_PTR g_local_player = NULL;UINT_PTR g_player_list_address = NULL;UINT_PTR g_matrix_address = NULL;UINT_PTR g_angle_address = NULL;HWND g_game_hwnd = NULL;module_information engine_module;module_information client_module;module_information server_module;float g_client_width;float g_client_height;把需要用到的偏移也聲明一下#define dwViewMatrix 0x4DCF254#define dwLocalPlayer 0xDC14CC#define dwClientState 0x58CFDC#define dwEntityList 0x4DDD93C#define dwClientState_ViewAngles 0x4D90#define m_vecOrigin 0x138#define m_bDormant 0xED#define m_lifeState 0x25F#define m_iHealth 0x100#define m_iTeamNum 0xF4再把需要使用到的函數先聲明和實現(GetImformation.cpp),實現思路寫在后面獲取屏幕大??,保磱癸湯局变?/h2>void GetWindowSize(){HDC hdc = GetDC(nullptr);g_client_width = GetDeviceCaps(hdc, DESKTOPHORZRES);g_client_height = GetDeviceCaps(hdc, DESKTOPVERTRES);ReleaseDC(nullptr, hdc);}先寫一個錯誤獲取函數,以方便獲取出錯的信息void error(const char*text){MessageBoxA(nullptr, text, nullptr, MB_OK);exit(-1);}bool is_error(){return GetLastError() != 0;}通過進程名獲取進程id和進程句柄使用CreateToolhelp32Snapshot函數,創建進程快照,遍歷系統快照中的進程名,遍歷到process_name,則返回該進程的進程ID
DWORD get_process_id(const char*process_name){HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (is_error()) error("CreateToolhelp32Snapshot失敗");PROCESSENTRY32 process_info;ZeroMemory(&process_info, sizeof(process_info));process_info.dwSize = sizeof(process_info);char target[1024];ZeroMemory(target, 1024);strncpy_s(target, process_name, strlen(process_name));_strupr(target);bool state = Process32First(snap, &process_info);while (state){if (strncmp(_strupr(process_info.szExeFile), target, strlen(target)) == 0){return process_info.th32ProcessID;}state = Process32Next(snap, &process_info);}CloseHandle(snap);return 0;}通過進程ID獲取進程句柄
HANDLE get_process_handle(DWORD process_id){HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);if (is_error())error("get_process_handle失敗");return process_handle;}通過進程id獲取進程中的模塊信息(模塊大?。?櫚刂?nbsp;, 模塊句柄)可以發現偏移都是由 client.dll+xxxxx 此種形式構成,所以需要獲取模塊的地址
先創建一個模塊結構體,需要獲取模塊的模塊大?。?模塊地址,模塊句柄
class module_information{public:HANDLE module_handle;char module_name[1024];char *module_data;UINT_PTR module_address;int module_size;void alloc(int size){module_size = size;module_data = https://www.huyubaike.com/biancheng/(char *)VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (is_error())error("申請內存失敗");}void release(){if (module_data)VirtualFree(module_data, 0, MEM_RELEASE);module_data = https://www.huyubaike.com/biancheng/nullptr;}};傳入進程ID和需要獲取的模塊名,CreateToolhelp32Snapshot創建模塊快照,遍歷快照,比對模塊名,獲取模塊信息

推薦閱讀