[5]创建线程获取人物信息
1.创建一个线程获取游戏中的人物数据并存储在自己申请的一块内存空间中(使用VirtualAlloc)
人物信息地址:
寻找自身相应的信息基址
自身基址:pMyBase=client.dll+0x2CC078
自身X坐标:*pMyBase+0x2c8
自身Y坐标:*pMyBase+0x2cc
自身Z坐标:*pMyBase+0x2d0
自身水平转轴:*pMyBase+0x2d4
自身纵向转轴:*pMyBase+0x2d8
寻找其他玩家相应的信息基址
玩家数组基址:pPlayerBase=client.dll+0x2E4FDC
玩家X坐标:*pPlayerBase+0x1f0
玩家Y坐标:*pPlayerBase+0x1f4
玩家Z坐标:*pPlayerBase+0x1f8
玩家血量:*pPlayerBase+0xf70
玩家阵营:*pPlayerBase+0xa0 3 CT/2 T
玩家状态:*pPlayerBase+0x54 23活/0死
CT阵营人数基址
[[[[[client.dll+0x2e3cc8]+0xc]+0x20]+0x8]+0x260]
T阵营人数基址
[[[[[client.dll+0x2e3cc8]+0x8]+0x10]+0x4]+0x26c]
获取模块地址和获取进程差不多,可以互相参考:
/************************************************************************/ /* 功能:获取模块地址 返回值: 模块地址 */ /************************************************************************/ DWORD CprocessInfo::MyGetModuleAddress(DWORD dwPid, PTSTR strMoudleName) { //初始化结构体 HANDLE hand = 0; MODULEENTRY32 ModuInfo = { 0 }; ModuInfo.dwSize = sizeof(MODULEENTRY32); // 创建一个系统快照, 第二个参数如果是模块或者线程的快照,则需要填写该进程的PID,全局返回则填0; //调用成功,返回快照的句柄,调用失败,返回INVALID_HANDLE_VALUE 。 //TH32CS_SNAPPROCESS把系统全部进程拍出来 hand =::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, dwPid); if (hand == INVALID_HANDLE_VALUE) { return 0; } //Module32First是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后, //我们可以利用Module32First函数来获得第一个模块的句柄。 //返回信息全在PMODULEENTRY32结构体当中 //和Module32Next是一个组合,Module32First觉得去哪拿,Module32Next把其他都拿出来 Module32First(hand, &ModuInfo); //通过一个循环使用Module32Next,把所有模块读取出来 do { //通过对比字符串来判断是否当前模块已经获取,szModule模块全名; if (!_tcscmp((PTCHAR)ModuInfo.szModule, strMoudleName)) { return(DWORD) ModuInfo.hModule; } } while (::Module32Next(hand, &ModuInfo)); return 0; }
插入.h,设置自己的人物结构体
#pragma once struct stPlayerInfo { //坐标 FLOAT x; FLOAT y; FLOAT z; //转轴 FLOAT sx; FLOAT zy; //血量 DWORD dwHp; //状态 DWORD dwState; //阵营 DWORD dwCT; };
重新新建一个类定义人物的数据:
#include "stdafx.h" #include "PlayerInfo.h"/************************************************************************/ /* 功能:搜索成员信息 参数: hProcess 游戏进程句柄 dwBaseAddress 模块数据基地址 pPlayerBufferMemory 存储地址 返回值: VOID /************************************************************************/ VOID FindPlayer(HANDLE hProcess, DWORD dwBaseAddress, PTCHAR pPlayerBufferMemory) { //获取阵营人数 DWORD dwCtNum = 0, dwTNum = 0; //CT人数 PTCHAR pNumBase = NULL; ReadProcessMemory(hProcess, (LPVOID)((DWORD)dwBaseAddress + 0x2e3cc8), &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0xc, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x20, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x8, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x260, &pNumBase, 4, NULL); //T人数 ReadProcessMemory(hProcess, (LPVOID)((DWORD)dwBaseAddress + 0x2e3cc8), &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x8, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x10, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x4, &pNumBase, 4, NULL); ReadProcessMemory(hProcess, pNumBase + 0x26c, &pNumBase, 4, NULL); //获取人物数组地址 PTCHAR pPlayerIfoArrBase = (PTCHAR)((DWORD)dwBaseAddress + 0x2E4FDC); PTCHAR pPlayerIfoBase = NULL; //目标基地址 //自身数据地址 PTCHAR pMyIfoArrBase = (PTCHAR)((DWORD)dwBaseAddress + 0x2CC078); PTCHAR pMyIfoBase = NULL; //自身基地址 stPlayerInfo* pstPlayerInfo = (stPlayerInfo*)pPlayerBufferMemory; //定义结构体指针指向存储数据的位置 //获取自身信息 ReadProcessMemory(hProcess, pMyIfoArrBase, &pMyIfoBase, 4, NULL); ReadProcessMemory(hProcess, pMyIfoBase + 0x2c8, &pstPlayerInfo[0].x, 4, NULL); ReadProcessMemory(hProcess, pMyIfoBase + 0x2cc, &pstPlayerInfo[0].y, 4, NULL); ReadProcessMemory(hProcess, pMyIfoBase + 0x2d0, &pstPlayerInfo[0].z, 4, NULL); ReadProcessMemory(hProcess, pMyIfoBase + 0x2d4, &pstPlayerInfo[0].sx, 4, NULL); ReadProcessMemory(hProcess, pMyIfoBase + 0x2d8, &pstPlayerInfo[0].zy, 4, NULL); //获取目标信息 stPlayerInfo stNewData = { 0 }; for (DWORD i = 0; i < dwCtNum + dwTNum; i++)//循环遍历将所有人物信息遍历出来 { //同时判断是否刷新 ReadProcessMemory(hProcess, pPlayerIfoArrBase + i * 0x10, &pPlayerIfoBase, 4, NULL); //每个角色链表数据之间间隔查0x10 ReadProcessMemory(hProcess, pPlayerIfoBase + 0xa0, &pstPlayerInfo[i + 1].dwCT, 4, NULL); //玩家阵营: ReadProcessMemory(hProcess, pPlayerIfoBase + 0x1f0, &stNewData.x, 4, NULL); //玩家X坐标 ReadProcessMemory(hProcess, pPlayerIfoBase + 0x1f4, &stNewData.y, 4, NULL);//玩家y坐标 ReadProcessMemory(hProcess, pPlayerIfoBase + 0x1f8, &stNewData.z, 4, NULL);//玩家z坐标 ReadProcessMemory(hProcess, pPlayerIfoBase + 0xf70, &stNewData.dwHp, 4, NULL);//玩家血量:*pPlayerBase+0xf70 ReadProcessMemory(hProcess, pPlayerIfoBase + 0x54, &pstPlayerInfo[i+1].dwState,4, NULL);//玩家状态:*pPlayerBase+0x54 23活/0死 } }
原创学习随笔心得,请勿转载!