通过进程id获取进程中的模块信息(模块大小,模块地址,模块句柄)可以发现偏移都是由 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创建模块快照,遍历快照,比对模块名,获取模块信息
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, info.module_data, info.module_size);//TODOCloseHandle(snap);return;}status = Module32Next(snap, &module_info);}error("未找到模块");return;}读取游戏内存函数例如之前得到 上下角度 = [[engine.dll+58CFDC]+00004D90],则可以
ReadProcessMemory(g_process_handle, (LPVOID)(engine.dll+58CFDC), recv, size, &readsize);
ReadProcessMemory(g_process_handle, (LPVOID)recv, recv, size, &readsize);
函数的使用方法:ReadProcessMemory(句柄,地址,读到哪里,读多少,具体读了多少);
则可以读到上下角度
通过ReadProcessMemory函数读取内存,对这个函数进行打包,方便使用(好吧,我承认这个打包的很烂,几乎没有方便使用)
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("读取内存失败");}重写了一个我觉得比较好用的,各位可以酌情对其进行改写
template<class T>T ReadMem(HANDLE ProcessHandle, UINT_PTR Address, int size){T Reader;ReadProcessMemory(ProcessHandle, (LPVOID)Address, &Reader, size, NULL);return Reader;}三维坐标转二维坐标创建两个结构体来储存二维坐标,一个用来储存三维坐标
struct Vec2{public:float x, y;};struct Vec3{public:float x, y, z;};传入一个三维坐标和视角矩阵,算出人物在屏幕上的坐标 VecScreen
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;}GLFW画线使用glVertex2f函数,第一个glVertex2f是开始的位置,第二个glVertex2f是结束的位置
经验总结扩展阅读
- 适合隔夜带饭的菜谱
- 雨伞放行李箱托运会被开箱吗
- 台湾的美称
- 夏天乳鸽煲汤用什么材料
- 连州特产有哪些
- 华县大地震是哪一年
- 芋圆材料
- 中药可以托运吗
- 2023年10月13日出货行吗 2023年10月13日出货黄道吉日
- 脱光是什么意思?