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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

012 背包二叉树遍历分析和代码编写

發布時間:2025/3/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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]+0x10

rdx來源于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 背包二叉树遍历分析和代码编写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。