012 背包二叉树遍历分析和代码编写
文章目錄
- 背包屬性遍歷
- 物品名字庫遍歷
- 數據整理
- 代碼編寫
背包屬性遍歷
從物品數量入手,搜索2字節
篩選出唯一的值
下兩字節的訪問斷點,鼠標移動到物品上面,斷點斷下
物品數量=r14+0x10這里就能得到一個+0x10的偏移。然后記錄下每層的返回地址
r14來源于r9
r9來源于rsi
rsi來源于r9
r9來源于r14
r14來源于rax
rax來源于rbx,rbx來源于上面的call
繼續進call里面追,里面有個循環就是二叉樹
追rax的來源
物品數量=[rax+0x20]+0x10 物品數量=[[rax]+0x20]+0x10 物品數量=[rdx+0x20]+0x10rdx來源于rax,然后這個位置是一個二叉樹
rax來源于rdx+8
rdx來源于一個數組
[[r9+rcx*8+0x9FC]+0x8]r9來源于rcx
rcx來源于一個基地址
[[0x00007FF637D57050+rcx*8+0x9FC]+0x8]繼續追rcx
rcx來源于rax+rax*4
[[0x00007FF637D57050+rax+rax*4*8+0x9FC]+0x8]rax來源于dx
dx來源于[rbp+0x30],這個地址往上追會追到一個常量。這個數值1代表背包,0代表裝備欄
物品名字庫遍歷
接著我們需要去找到物品名稱,一般物品名稱是通過一個call來查找的,這個call會傳入物品ID,返回物品的名稱。我們從物品的名稱入手來找到這個call
直接搜索物品名稱
下斷,讓斷點斷下
返回發現是一個系統函數,我們要追r10的來源。
r10來源于rdx,返回上層
rdx來源于rsi
rsi來源于r8
返回上層,r8來源于[rdi]
rdi來源于rcx
再返回上層,rcx來源于r10
r10來源于rdx
rdx來源于[rcx+0xBC]
[[rcx+0xBC]+0]rcx來源于rax,rax來源于rdx
再返回,rdx來源于r12
r12來源于r8
r8來源于r13
r13來源于rax。接著來分析這個call
這個call有兩個參數,rcx是一個基地址,edx傳入的是物品ID。那么我們就可以通過這個call,來拿到返回值
[[rax+0xBC]+0]然后再通過偏移表達式,拿到物品名稱。
繼續追下rax
rax來源于[rax+0x20],來源于[rax]
來源于rsp+0x8
來源于r8
[[[r8+0x20]+0xBC]+0]r8來源于rax,然后就到了一個二叉樹,rax來源于[r8+0x8],r8來源于[rcx+0x1A14]
然后來源于一個基地址
名稱二叉樹:[[0x00007FF66C047050+0x1A14]+0x8] +0 左子樹 +0x10 右子樹 +0x29 結束標志 +0x18 物品ID +0x20 物品對象名稱偏移:[[[root+0x20]+0xBC]+0]物品的名字可以通過調用call來獲取,也可以通過遍歷拿到整個名字庫
數據整理
mov edx,r15d | lea rcx,qword ptr ds:[0x7FF66C047050] | 名字庫二叉樹基地址 call 0x7FF66A16DDA0 | 通過物品ID取物品名稱-----------------------------背包物品的二叉樹---------------------------- 二叉樹根節點:[[0x00007FF637D57050+rax*5*8+0x9FC]+0x8] 二叉樹基地址偏移:0x2F67050rax是背包序號 0 裝備欄 1 主背包 2 資源包1 3 資源包2 4 資源包3+0 左子樹 +0x10 右子樹 +0x29 結束標志 +0x18 物品的下標物品數量=[root+0x20]+0x10 +0x20 對象 對象+0x10 物品數量 DWORD 對象+0x14 最大數量 DWORD 對象+0xE 物品位置 BYTE 對象+8 物品ID DWORD通過二叉樹拿對象 通過對象拿屬性-----------------------------物品名稱的二叉樹---------------------------- 名稱二叉樹:[[0x00007FF66C047050+0x1A14]+0x8] 偏移:0x2F67050 +0 左子樹 +0x10 右子樹 +0x29 結束標志 +0x18 物品ID +0x20 物品對象名稱偏移:[[[root+0x20]+0xBC]+0] 通過二叉樹拿ID 通過ID拿名稱----------------------------通過物品ID獲取物品名稱---------------------------- mov edx,r15d | lea rcx,qword ptr ds:[0x7FF66C047050] | 名字庫二叉樹基地址 call 0x7FF66A16DDA0 | 通過物品ID取物品名稱名字庫二叉樹基地址偏移:0x2F67050 通過物品ID取物品名稱call偏移:0x108DDA0 名稱:[[rax+0xBC]+0]代碼編寫
背包遍歷的代碼和周圍遍歷很相似,這里直接給出相關代碼
GameData.h
//背包遍歷 _stuObjs GetBagDatas();//進入背包遍歷 void EnterBagDataTree(DWORD dwRoot, _stuObjs& alllist);//獲取每個節點的背包數據 void GetBagDataObjInfo(DWORD dwNode, _stuObjs& alllist);GameData.cpp
//背包遍歷 _stuObjs GetBagDatas() {_stuObjs baglist;//獲取二叉樹根節點(這里只遍歷主背包 1代表主背包)QWORD dwRootAddr = g_GameAddr + AroundAndBagDataTree + 1 * 5 * 8 + 0x9FC;DWORD dwBagTreeToot = ReadDword(dwRootAddr);dwBagTreeToot = ReadDword(dwBagTreeToot + 0x8);//進入背包遍歷EnterBagDataTree(dwBagTreeToot, baglist);return baglist; }//進入背包遍歷 void EnterBagDataTree(DWORD dwRoot, _stuObjs& alllist) {//左子樹DWORD dwLeftNode = ReadDword(dwRoot + 0);//右子樹DWORD dwRightNode = ReadDword(dwRoot + 0x10);//標志位BYTE bFlag = ReadBYTE(dwRoot + 0x29);//標志位為0開始遍歷if (bFlag == 0){//獲取對象里面的數據GetBagDataObjInfo(dwRoot, alllist);//遞歸遍歷左子樹EnterBagDataTree(dwLeftNode, alllist);//遞歸遍歷右子樹EnterBagDataTree(dwRightNode, alllist);} }//獲取每個節點的背包數據 void GetBagDataObjInfo(DWORD dwNode, _stuObjs& alllist) {_stuObj stuBagData;//設置類型stuBagData.m_StuType = Em_Item;//對象stuBagData.m_Obj = ReadDword(dwNode + 0x20);//下標stuBagData.m_Item_Index = ReadDword(dwNode + 0x18);//物品IDstuBagData.m_ID = ReadDword(stuBagData.m_Obj + 0x8);//物品數量stuBagData.m_Item_Nownum = ReadDword(stuBagData.m_Obj + 0x10);//物品名字stuBagData.m_Name = Fn_GetGoodsNameByID(stuBagData.m_ID);//保存到容器alllist.m_data.push_back(stuBagData); }GameFunction.h
//通過物品ID獲取物品名稱 wstring Fn_GetGoodsNameByID(DWORD ID);GameFunction.cpp
//通過物品ID獲取物品名稱 std::wstring Fn_GetGoodsNameByID(DWORD ID) {//1.1 先拿到二叉樹的地址 也就是ECX的地址QWORD GoodsTreeAddr = g_GameAddr + AroundAndBagDataTree;//1.2 再拿到call地址QWORD GetGoodsNameCall = g_GameAddr + GetBagNameCall;//調用callQWORD qGoodObj = GameCall2(GoodsTreeAddr, ID, GetGoodsNameCall);//第一層偏移qGoodObj = ReadDword(qGoodObj + 0xBC);try{//1.5 讀取名字if (qGoodObj){return ReadWChar(qGoodObj);}}catch (...){OutputDebugStringA("讀取名字出錯了");}return L"NULL"; }實際效果如圖:
到這里自動吃藥所需要的數據都已經找齊了,下一節我們來完成自動吃藥的功能。
Github:https://github.com/TonyChen56/GameReverseNote
完整代碼:https://download.csdn.net/download/qq_38474570/79498815
總結
以上是生活随笔為你收集整理的012 背包二叉树遍历分析和代码编写的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 011 吃药call功能分析和代码编写
- 下一篇: 013 自动吃药功能的设计和实现