前置知識:5.模仿CheatEngine實現鎖血無敵功能(封裝它的代碼)
封裝功能.cpp文件
#include "封裝功能.h"GAMECheat::GAMECheat(unsigned pid, unsigned _baseAdr, unsigned _readTime)
{readTime = _readTime;baseAdr = _baseAdr;hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}bool GAMECheat::ReadData(unsigned readTick)
{if(!readTick) return false;lastRead = readTick;return ReadProcessMemory(hProcess, (LPCVOID)baseAdr,this, sizeof(JianXiaGameRole), 0);
}JianXiaGameRole& GAMECheat::Data(bool IsCheckTime)
{if (!IsCheckTime)return _data;unsigned dTickNow = GetTickCount();if ((dTickNow - lastRead) > readTime)ReadData(dTickNow);return _data;
}void GAMECheat::SetData(void* dataAdr, void* buffer, SIZE_T length)
{LPVOID destAdr = (LPVOID)((unsigned)dataAdr - (unsigned)this + baseAdr);WriteProcessMemory(hProcess, destAdr, buffer, length, 0);
}
封裝功能.h文件
#pragma once
#include <Windows.h>struct JianXiaGameRole
{int unknown1[4];int hp;int maxHp;int tiLi;int maxTiLi;int mp;int maxMp;int gongJiLi;int fangYu;int shenFa;int dengJi;int unknown2;int jingYan;int shengJi;int yiDongSuDu;int unknown3;int mianXiang;int unknown4[2];int xZuoBiao;int yZuoBiao;int unknown5[36];char name[0x20];
};
class GAMECheat {
public:// 通過構造函數初始化需要的數據,pid是進程id、_baseAdr是游戲中人物屬性結構的首地址、_readTime讀取內存的間隔時間GAMECheat(unsigned pid, unsigned _baseAdr, unsigned _readTime =100);// IsCheckTime為true會讀取內存,false不讀取內存目的提升效率JianXiaGameRole& Data(bool IsCheckTime=false);// 給進程寫數據,也就是設置人物屬性的值void SetData(void * dataAdr, void*buffer, SIZE_T length);
private:// 這個_data必須要放在第一個,如果不放在第一個我們就無法用this來表示 JianXiaGameRole 結構了那樣就要多寫點代碼JianXiaGameRole _data;bool ReadData(unsigned readTick);HANDLE hProcess;unsigned baseAdr;unsigned lastRead;unsigned readTime;};
main代碼:
#include "封裝功能.h"
#include <iostream>#define P(data,x) &data, &x,sizeof(x)int main() {unsigned pid;std::cout << "請輸入游戲進程ID:";std::cin >> pid;GAMECheat gcheat(pid, 0x4CEF08);std::cout << "角色名稱:" << gcheat.Data(1).name << std::endl;std::cout << "血量:" << gcheat.Data().hp << std::endl;int hp = 0;gcheat.SetData(P(gcheat.Data().hp, hp));system("pause");
}