日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

003 辅助框架的代码实现

發(fā)布時(shí)間:2025/3/21 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 003 辅助框架的代码实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

      • Stu
      • CPublic公共函數(shù)
      • MemOper 內(nèi)存操作
      • GlobalData 全局?jǐn)?shù)據(jù)

接著上一篇文章,我們來聊關(guān)于整個(gè)輔助框架的代碼實(shí)現(xiàn)

Stu

按照常規(guī)的思路,我們來構(gòu)想一下接下來的開發(fā)過程。首先我們需要找到人物的數(shù)據(jù),然后編寫代碼的時(shí)候設(shè)計(jì)一個(gè)人物數(shù)據(jù)的結(jié)構(gòu)體;接著周圍遍歷的數(shù)據(jù),又要設(shè)計(jì)一個(gè)周圍遍歷的結(jié)構(gòu)體;后續(xù)用到每一個(gè)新的數(shù)據(jù),都要設(shè)計(jì)一個(gè)結(jié)構(gòu)體來存放。

等寫了兩三個(gè)游戲以后就會(huì)發(fā)現(xiàn),很多代碼都在重復(fù)寫。那么這就引出了一個(gè)數(shù)據(jù)管理的問題,怎么樣用最高效的方式去管理這些數(shù)據(jù)。

其實(shí)很多對(duì)象有一部分屬性都是通用的,比如說名字,等級(jí)和ID;這樣我們就可以設(shè)計(jì)一個(gè)通用的對(duì)象結(jié)構(gòu)體,這個(gè)對(duì)象結(jié)構(gòu)體存儲(chǔ)所有的游戲數(shù)據(jù)對(duì)象,然后用一個(gè)type字段來對(duì)對(duì)象進(jìn)行區(qū)分。

對(duì)象結(jié)構(gòu)如下:

struct _stuObj {int m_StuType; //0 人物 //--------------------------------公用-------------------------------------------------wstring m_Name; //名字 DWORD m_Obj; //對(duì)象DWORD m_ID; //ID//輸出調(diào)試信息void OutputDebugInfo(); }
  • m_StuType表示對(duì)象的類型,用這個(gè)字段來區(qū)分不同的對(duì)象
  • m_Name表示對(duì)象的名字,這一部分是公用的屬性,所有對(duì)象都會(huì)有
  • m_Obj表示對(duì)象本身
  • m_ID表示對(duì)象的ID
  • OutputDebugInfo用于輸出調(diào)試信息
  • 先暫時(shí)設(shè)計(jì)這些屬性,后面需要再進(jìn)行添加;再設(shè)置一個(gè)枚舉,用于區(qū)分_stuObj的數(shù)據(jù)類型。

    //stu類型 enum EType {//角色Em_Role,//對(duì)象Em_Object,//物品Em_Item,//地面物品 Em_GroundItem,//技能Em_Skill,//已接任務(wù)Em_GetedTask,//可接任務(wù)Em_CanGetTask, };

    OutputDebugInfo函數(shù)實(shí)現(xiàn)如下:

    //輸出單個(gè)對(duì)象的調(diào)試信息 void _stuObj::OutputDebugInfo() {__try{switch (m_StuType){//輸出角色信息case Em_Role:break;//輸出對(duì)象信息case Em_Object:break;//輸出物品信息case Em_Item:break;//輸出地面物品信息case Em_GroundItem:break;//輸出任務(wù)信息case Em_GetedTask:break;//輸出技能信息case Em_Skill:break;default:break;}}__except (1){OutputDebugStringA("輸出stuobj信息錯(cuò)誤");} }

    現(xiàn)在我們已經(jīng)有了一個(gè)對(duì)象結(jié)構(gòu)體,接著再設(shè)計(jì)一個(gè)對(duì)象結(jié)構(gòu)體的集合。

    //對(duì)象結(jié)構(gòu)體集合 struct _stuObjs {//所有的對(duì)象集合vector<_stuObj> m_data;public:void OutputDebugInfo();//通過名字列表獲取對(duì)象_stuObj GetDataByName(wstring name);//通過名字列表獲取多個(gè)對(duì)象_stuObjs GetDataByNames(vector<wstring> names); };

    vector<_stuObj> m_data這個(gè)對(duì)象結(jié)構(gòu)體的集合用于保存所有的對(duì)象。方便后面數(shù)據(jù)存儲(chǔ)。然后再實(shí)現(xiàn)三個(gè)函數(shù),OutputDebugInfo函數(shù)實(shí)現(xiàn)如下:

    //輸出多個(gè)對(duì)象的調(diào)試信息 void _stuObjs::OutputDebugInfo() {for (auto it = begin(m_data); it != end(m_data); it++){it->OutputDebugInfo();} }

    由于我們已經(jīng)實(shí)現(xiàn)了單個(gè)對(duì)象的OutputDebugInfo函數(shù),所以多個(gè)對(duì)象的OutputDebugInfo只需要調(diào)用單個(gè)對(duì)象的輸出函數(shù)就可以了。

    接著還需要實(shí)現(xiàn)一個(gè)函數(shù),通過名字獲取對(duì)象。

    //通過名字獲取對(duì)象 _stuObj _stuObjs::GetDataByName(wstring name) {for (auto it = begin(m_data); it != end(m_data); it++){if (it->m_Name==name){return *it;}}return _stuObj(); }

    需要實(shí)現(xiàn)這個(gè)函數(shù)的場景是方便我們進(jìn)行某些功能測試。比如我找到了所有的技能遍歷的數(shù)據(jù),然后現(xiàn)在需要測試釋放技能call,釋放技能call一般是傳入技能ID,但如果用ID的話,那么我每次都需要去查看我需要釋放的ID到底是多少,這樣的話就會(huì)顯得比較麻煩。但如果封裝了這個(gè)函數(shù)就可以直接傳入技能名字。

    然后再寫一個(gè)通過名字取多個(gè)對(duì)象的方法

    //通過名字列表獲取多個(gè)對(duì)象 _stuObjs _stuObjs::GetDataByNames(vector<wstring> names) {_stuObjs values;for (auto it = begin(m_data); it != end(m_data); it++){for (auto nit = begin(names); nit != end(names); nit++){if (*nit == it->m_Name){values.m_data.push_back(*it);break;}}}return values; }

    CPublic公共函數(shù)

    這個(gè)類存放整個(gè)項(xiàng)目都需要用到的公共函數(shù),首先是兩個(gè)封裝好的輸出調(diào)試信息

    //************************************************************ // 函數(shù)名稱: __OutputDebugStringW // 函數(shù)說明: 打印調(diào)試信息 // 作 者: GuiShou // 時(shí) 間: 2020/3/11 // 參 數(shù): pstrFormat // 返 回 值: void //************************************************************ void __OutputDebugStringW(const wchar_t* pstrFormat, ...) {TCHAR szBuffer[1024] = { 0 };va_list argList;va_start(argList, pstrFormat);_vstprintf_s(szBuffer, pstrFormat, argList);va_end(argList);OutputDebugString(szBuffer); }//************************************************************ // 函數(shù)名稱: __OutputDebugStringA // 函數(shù)說明: 打印調(diào)試信息 // 作 者: GuiShou // 時(shí) 間: 2020/3/11 // 參 數(shù): pstrFormat // 返 回 值: void //************************************************************ void __OutputDebugStringA(const char* pstrFormat, ...) {CHAR szBuffer[1024] = { 0 };va_list argList;va_start(argList, pstrFormat);vsprintf_s(szBuffer, pstrFormat, argList);va_end(argList);OutputDebugStringA(szBuffer); }

    接著,由于x64只有一種調(diào)用約定,所以我們可以封裝一個(gè)函數(shù)來對(duì)所有的功能call進(jìn)行調(diào)用。例如我們找到的功能call有兩個(gè)參數(shù)時(shí),就可以傳入?yún)?shù)直接調(diào)用下面的函數(shù)

    QWORD GameCall2(QWORD RCX, QWORD RDX, QWORD calladdr) {__try{//定義函數(shù)指針typedef UINT64(*PFnFuncCall)(QWORD RCX, QWORD RDX);PFnFuncCall FuncCall = (PFnFuncCall)(calladdr);return FuncCall(RCX, RDX);}__except (1){__OutputDebugStringA("通用CALL2 出錯(cuò)\n");}return 0; }

    這樣就可以重復(fù)利用,而且不用寫匯編文件。下面封裝的函數(shù)也一樣,適用于不同參數(shù)的call。

    QWORD GameCall3(QWORD RCX, QWORD RDX, QWORD R8, QWORD calladdr) {__try{//定義函數(shù)指針typedef UINT64(*PFnFuncCall)(QWORD RCX, QWORD RDX, QWORD R8);PFnFuncCall FuncCall = (PFnFuncCall)(calladdr);return FuncCall(RCX, RDX, R8);}__except (1){__OutputDebugStringA("通用CALL3 出錯(cuò)\n");}return 0; }QWORD GameCall4(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9, QWORD calladdr) {__try {typedef UINT64(*PFnFuncCall)(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9);PFnFuncCall FuncCall = (PFnFuncCall)(calladdr);return FuncCall(RCX, RDX, R8, R9);}__except (1) {__OutputDebugStringA("通用CALL4 出錯(cuò)\n");}return 0; }QWORD GameCall5(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9, QWORD Rsp20, QWORD calladdr) {__try{typedef UINT64(*PFnFuncCall)(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9, QWORD Rsp20);PFnFuncCall FuncCall = (PFnFuncCall)(calladdr);return FuncCall(RCX, RDX, R8, R9, Rsp20);}__except (1){__OutputDebugStringA("通用CALL5 出錯(cuò)\n");}return 0; }QWORD GameCall6(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9, QWORD Rsp20, QWORD Rsp28, QWORD calladdr) {__try{typedef UINT64(*PFnFuncCall)(QWORD RCX, QWORD RDX, QWORD R8, QWORD R9, QWORD Rsp20, QWORD Rsp28);PFnFuncCall FuncCall = (PFnFuncCall)(calladdr);return FuncCall(RCX, RDX, R8, R9, Rsp20, Rsp28);}__except (1){__OutputDebugStringA("通用CALL6 出錯(cuò)\n");}return 0; }

    MemOper 內(nèi)存操作

    這個(gè)類封裝所有數(shù)據(jù)類型的取內(nèi)容操作,目的是提高代碼可讀性

    #include "pch.h" #include "MemOper.h"BYTE ReadBYTE(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(BYTE)) == 0){return *(BYTE*)pBase;}}__except(1){__OutputDebugStringA("ReadBYTE Error Addr:%x", pBase);}return 0; }BYTE ReadBYTE(DWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(BYTE)) == 0){return *(BYTE*)pBase;}}__except (1){__OutputDebugStringA("ReadBYTE Error Addr:%x", pBase);}return 0; }WORD ReadWord(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(WORD)) == 0){return *(WORD*)pBase;}}__except (1){__OutputDebugStringA("ReadWord Error Addr:%x", pBase);}return 0; }WORD ReadWord(DWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(WORD)) == 0){return *(WORD*)pBase;}}__except (1){__OutputDebugStringA("ReadWord Error Addr:%x", pBase);}return 0; }QWORD ReadQword(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(QWORD)) == 0){return *(QWORD*)pBase;}}__except (1){__OutputDebugStringA("ReadQword Error Addr:%x", pBase);}return 0; }DWORD ReadDword(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(QWORD)) == 0){return *(DWORD*)pBase;}}__except (1){__OutputDebugStringA("ReadDword Error Addr:%x", pBase);return 0;}return 0; }DWORD ReadDword(DWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(DWORD)) == 0){return *(DWORD*)pBase;}}__except (1){__OutputDebugStringA("ReadDword Error Addr:%x", pBase);return 0;}return 0; }int ReadInt(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(int)) == 0){return *(int*)pBase;}}__except (1){__OutputDebugStringA("ReadInt Error Addr:%x", pBase);}return 0; }float ReadFloat(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(float)) == 0){return *(float*)pBase;}}__except(1){__OutputDebugStringA("ReadFloat Error Addr:%x", pBase);}return 0; }float ReadFloat(DWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(float)) == 0){return *(float*)pBase;}}__except (1){__OutputDebugStringA("ReadFloat Error Addr:%x", pBase);}return 0; }void WriteFloat(QWORD pBase,float Value) {__try{if (IsBadWritePtr((void*)pBase, sizeof(float)) == 0){*(float*)pBase = Value;}}__except (1){__OutputDebugStringA("WriteFloat Error Addr:%x", pBase);}}wchar_t* ReadWChar(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(wchar_t)) == 0){return (wchar_t*)pBase;}}__except (1){__OutputDebugStringA("WriteFloat Error Addr:%x", pBase);}return L""; }char* ReadChar(QWORD pBase) {__try{if (IsBadReadPtr((void*)pBase, sizeof(char)) == 0){return (char*)pBase;}}__except (1){__OutputDebugStringA("ReadChar Error Addr:%x", pBase);}return ""; }

    GlobalData 全局?jǐn)?shù)據(jù)

    這個(gè)里面存放游戲需要用到的全局?jǐn)?shù)據(jù)

    .h文件

    //全局的游戲模塊地址 extern QWORD g_GameAddr;

    .cpp文件

    QWORD g_GameAddr = 0;void GetGameModuleAddr() {g_GameAddr = (QWORD)GetModuleHandleA("MMOGame-Win64-Shipping.exe"); }

    然后在界面初始化的時(shí)候調(diào)用一次,后續(xù)就可以一直使用游戲的模塊基地址了。

    剩下的GameData和GameFunction模塊存放游戲數(shù)據(jù)代碼和游戲功能代碼,我們等需要用到的時(shí)候在添加。

    Github:https://github.com/TonyChen56/GameReverseNote

    完整代碼:https://download.csdn.net/download/qq_38474570/79498815
    }
    __except (1)
    {
    __OutputDebugStringA(“ReadChar Error Addr:%x”, pBase);
    }

    return "";

    }

    ### GlobalData 全局?jǐn)?shù)據(jù)這個(gè)里面存放游戲需要用到的全局?jǐn)?shù)據(jù).h文件```c++ //全局的游戲模塊地址 extern QWORD g_GameAddr;

    .cpp文件

    QWORD g_GameAddr = 0;void GetGameModuleAddr() {g_GameAddr = (QWORD)GetModuleHandleA("MMOGame-Win64-Shipping.exe"); }

    然后在界面初始化的時(shí)候調(diào)用一次,后續(xù)就可以一直使用游戲的模塊基地址了。

    剩下的GameData和GameFunction模塊存放游戲數(shù)據(jù)代碼和游戲功能代碼,我們等需要用到的時(shí)候在添加。

    Github:https://github.com/TonyChen56/GameReverseNote

    完整代碼:https://download.csdn.net/download/qq_38474570/79498815

    總結(jié)

    以上是生活随笔為你收集整理的003 辅助框架的代码实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。