【C++】从零开始的CS:GO逆向分析3——写出一个透视( 三 )



获得屏幕大小储存在全局变量、创建透明窗口

循环遍历敌人对象,通过地址读取到人物的视角矩阵、敌人的位置

在循环中将敌人的位置结合矩阵,转换成2D坐标

再循环中在透明窗口上把算出来的坐标画出来
再写一段伪代码出来帮助理解,代码贴在后面
int main{获取视角矩阵地址、获取本地人物地址、获取敌人对象地址获取屏幕分辨率根据屏幕分辨率创建窗口while(1)消息循环{清除画的线获得视角矩阵 , 因为会变,所以需要不停的获取for(int i=0;i<64;i++)因为游戏人数最大为64{获得自己的阵营获取当前敌人对象根据对象获取人物血量、阵营、生存状态、敌人是否有效如果敌人血量<=0 或者 敌人阵营=自己阵营 或者 无效 或者 敌人对象为空 或者 敌人生存状态则遍历下一个对象获得敌人的位置将敌人的坐标转换为2D坐标画线}}}代码部分GetImformation.h
#pragma oncestruct Vec2{public:float x, y;};struct Vec3{public:float x, y, z;};bool is_error();void error(const char*text);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;}};void init_address(const char*process_name);DWORD get_process_id(const char*process_name);HANDLE get_process_handle(DWORD process_id);void ConvertToRange(Vec2 &Point);bool WorldToScreen(const Vec3& VecOrgin, Vec2& VecScreen, float* Matrix);void get_moduel_info(DWORD process_id, const char *name, OUT module_information&info);DWORD read_memory(HANDLE process, DWORD address, void *recv, int size);templateT ReadMem(HANDLE ProcessHandle, UINT_PTR Address, int size){T Reader;ReadProcessMemory(ProcessHandle, (LPVOID)Address, &Reader, size, NULL);return Reader;}GetImformation.cpp
#include<Windows.h>#include<TlHelp32.h>#include"GetIMformation.h"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//获取模块信息void get_moduel_info(DWORD process_id, const char *name, OUT module_information&info){HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process_id);if (is_error())error("创建快照错误");MODULEENTRY32 module_info;ZeroMemory(&module_info, sizeof(module_info));module_info.dwSize = sizeof(module_info);char target[1024];ZeroMemory(target, 1024);strncpy(target, name, strlen(name));_strupr(target);bool status = Module32First(snap, &module_info);while (status){if (strncmp(_strupr(module_info.szModule), target, sizeof(target)) == 0){info.module_address = (UINT_PTR)module_info.modBaseAddr;info.module_handle = module_info.hModule;info.alloc(module_info.modBaseSize);//DWORD size = read_memory(g_process_handle, info.module_address);//TODODWORD size = read_memory(g_process_handle, info.module_address, info.module_data, info.module_size);//TODOCloseHandle(snap);return;}status = Module32Next(snap, &module_info);}error("未找到模块");return;}void error(const char*text){MessageBoxA(nullptr, text, nullptr, MB_OK);exit(-1);}bool is_error(){return GetLastError() != 0;}DWORD read_memory(HANDLE process, DWORD address, void *recv, int size){DWORD readsize;ReadProcessMemory(process, (LPVOID)address, recv, size, &readsize);return readsize;if (is_error())error("读取内存失败");}HANDLE get_process_handle(DWORD process_id){HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);if (is_error())error("get_process_handle失败");std::cout << "进程句柄为:" << std::hex << process_handle << std::endl;return process_handle;}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){CloseHandle(snap);return process_info.th32ProcessID;}state = Process32Next(snap, &process_info);}CloseHandle(snap);MessageBoxA(NULL, "查找进程id失败", "提示", MB_OK);return 0;}void GetWindowSize(){HDC hdc = GetDC(nullptr);g_client_width = GetDeviceCaps(hdc, DESKTOPHORZRES);g_client_height = GetDeviceCaps(hdc, DESKTOPVERTRES);ReleaseDC(nullptr, hdc);}void init_address(const char*process_name){std::cout << "请先启动游戏"<< std::endl;DWORD process_id = get_process_id(process_name);HANDLE process_handle = get_process_handle(process_id);g_process_id = process_id;//获取模块信息g_process_handle = process_handle;get_moduel_info(process_id, "engine.dll", engine_module);get_moduel_info(process_id, "client.dll", client_module);get_moduel_info(process_id, "server.dll", server_module);//TODO 要写一个特征码寻址,获取视角矩阵信息UINT_PTR temp_address;float Matrix[16];UINT_PTR matrix_address = client_module.module_address + dwViewMatrix;g_matrix_address = matrix_address;//获取 人物视角地址ReadProcessMemory(g_process_handle, (LPVOID)(engine_module.module_address + 0x58CFDC), &temp_address, 4, NULL);//[engine.dll + 58CFDC]+00004D90g_angle_address = temp_address + 0x00004D90;//获取本地人物地址 [client.dll+0xDC04CC]+100 = 生命值ReadProcessMemory(g_process_handle, (LPVOID)(client_module.module_address + dwLocalPlayer), &temp_address, 4, NULL);g_local_player = temp_address; //[g_local_player+100] = 生命值temp_address = 0;//获得ENtitylist地址[client.dll+0x4DDC90C + i *0x10]+100 = 敌人生命值g_player_list_address = client_module.module_address + dwEntityList;}bool WorldToScreen(const Vec3& VecOrgin, Vec2& VecScreen, float* Matrix){VecScreen.x = VecOrgin.x *Matrix[0] + VecOrgin.y*Matrix[1] + VecOrgin.z*Matrix[2] + Matrix[3];VecScreen.y = VecOrgin.x *Matrix[4] + VecOrgin.y*Matrix[5] + VecOrgin.z*Matrix[6] + Matrix[7];float w = VecOrgin.x*Matrix[12] + VecOrgin.y*Matrix[13] + VecOrgin.z*Matrix[14] + Matrix[15];if (w < 0.01f){return false;}Vec2 NDC;NDC.x = VecScreen.x / w;NDC.y = VecScreen.y / w;VecScreen.x = (g_client_width / 2 * NDC.x) + (NDC.x + g_client_width / 2);VecScreen.y = (g_client_height / 2 * NDC.y) + (NDC.y + g_client_height / 2);ConvertToRange(VecScreen);return true;}void ConvertToRange(Vec2 &Point){Point.x /= g_client_width;Point.x *= 2.0f;Point.x -= 1.0f;Point.y /= g_client_height;Point.y *= 2.0f;Point.y -= 1.0f;}

推荐阅读