011 数据结构逆向—二叉树
文章目錄
- 前言
- 背包數據嵌套結構
- 背包二叉樹
- 二叉樹分析
- 背包數據結構分析
- 總結
前言
學習完了鏈表的數據結構,我們再通過幻想神域了解一下二叉樹在游戲中的存儲形式。
這一次要逆向的數據是背包中的所有物品,為了能將背包中的數據盡量分析完整,這個游戲建議盡量升到20級。會送兩個背包擴展券,背包越大數據越多,能夠分析到的數據越完整。
我這里是有兩個背包擴展券。,一個20格擴展卷,一個5格擴展券。
背包數據嵌套結構
背包里有很多物品,每一個物品的每一個屬性都可以成為突破口,最簡單的當然是物品數量了。
用CE附加游戲,掃描背包的物品數量,數據類型勾選2字節
再次掃描,剩下三個數值,分別對這三個數值進行修改,然后重新打開背包,就能過濾出真實的地址。
在這個地址下兩個字節的硬件訪問斷點,吃藥讓斷點斷下
此時eax+28的當前物品數量,往上追eax
ecx來源于[ecx+edi*4]
物品數量=[ecx+edi*4]+28這個地方我們發現是一個數組,下斷,觀察edi數組下標的值,這個下標的值有下面幾種變化
0-1D:30 0-4:5 0-13:20三種變化分別對應自帶的20個背包格子數量,5格補充背包和20格補充背包。再來看ecx數組首地址的值,也有三種變化。
這里其實是N+1個數組,N個擴展背包加上一個自帶的背包。ecx代表的是背包對象,edi代表的是背包對象的每一個成員。
背包二叉樹
繼續往上追ecx背包對象
ecx來源于[esi+8],esi來源于[edi+0x10],到這里edi的值依然是變化的
物品數量=[[esi+8]+edi*4]+28 物品數量=[[[edi+0x10]+8]+edi*4]+28edi來源于[eax]。這里下斷觀察eax的值,eax的值每次斷下都是不變的。
從這里不變化再到下面三個值發生變化,說明edi并不是來源于eax,而且代碼不是順序執行的。
這個地方可能是有循環。接著對這段代碼進行分析,找出寄存器變化的來源。
首先找到向上的跳轉,確定循環頭部和循環尾部。但是變化的eax和edi不在這個循環體內,說明這個循環和我們要追的數據沒有關系
這個循環一直在對數組下標+1,那這里應該是數組循環頭部和數組循環尾部
繼續找向上的跳轉,確定循環頭部和循環尾部。
變化的寄存器edi在循環體里面,不變的寄存器eax在循環外,說明這個就是我們要找的循環。
確定好了循環,繼續在循環體內追edi,edi一直到循環頭部沒有來源,繼續在循環體下面的代碼中找edi
edi來源于[ebp-C],
物品數量=[[[[ebp-C]+0x10]+8]+edi*4]+28接著追[ebp-C],[ebp-C]在循環內也沒有來源,而是來源于循環外的edi,說明edi是第一個物品對象。
但是[ebp-C]作為局部變量在循環內沒有來源,不太可能,說明循環內有call改變了[ebp-C]。
在這個位置下斷,觀察[ebp-C]的值,[ebp-C]的值現在是0x21CDE0A0,數據窗口跟隨這個地址,下一個對象是0x21CDE260
步過這個call以后再觀察[ebp-C],變成了0x21CDE260,說明我們追的背包對象的變化是來自于這個call,這個call參數放入一個背包對象,然后返回下一個背包對象。
二叉樹分析
想要得到整個數據結構的數據,有兩種方法,第一種是找到根節點,直接調用call,一直取下一個對象;另外一種是根據這個對象下訪問斷點,找到遍歷的代碼。
這種背包結構在游戲中必定是會有代碼不斷訪問背包數據,所以直接在這個背包對象[ebp-C]下訪問斷點。
對象下斷后斷下的位置,eax是我們想要追的背包對象,并且這塊代碼是一個標準的二叉樹遍歷。 接著我們來分析這塊代碼
首先找到循環頭部和循環尾部。然后我們發現循環里面有兩個跳轉
如果跳轉成功,eax取[eax]]位置的值,如果跳轉不成功,eax取[eax+8]的值。和之前的鏈表循環一樣。區別在于多了一個節點,其正向代碼如下:
struct node {// 左節點node *lc;// 右節點node *rc;// 數據域int data; };[eax]是左節點,[eax+8]是右節點
物品數量=[[[[eax]+0x10]+8]+edi*4]+28eax就是二叉樹的根節點,如果想要寫代碼遍歷的話需要再把eax的基址追到。這次的目的是學習二叉樹,這個過程省略。
另外這個地方比較[eax+0x15]是否為0,不是則繼續遍歷,這個位置是二叉樹的標志位。
左子樹:[eax] 右子樹:[eax+8] 標志位:[eax+0x15]找到這三個東西,再分析出后面的屬性偏移,就能將整個二叉樹的數據遍歷出來。
背包數據結構分析
物品數量=[[[[eax]+0x10]+8]+edi*4]+28再回到之前的偏移表達式,簡單分析一下整個數據結構
- eax作為二叉樹頭節點里面每一個成員都是背包對象
- [[[[eax]+0x10]+8]代表的是N個背包對象數組的首地址
- [[[[eax]+0x10]+8]+edi*4]代表的是背包中每一個物品對象
- [[[[eax]+0x10]+8]+edi*4]+XX代表的是背包中每一個物品對象的屬性
對于屬性的分析就比較佛系了,能看出來多少算多少,各位隨緣吧~
總結
對于二叉樹和鏈表的分析,最關鍵的在于通過觀察寄存器的變化,找到變化源,然后在變化原中找出循環體,并分析循環體內的代碼,從而判斷出程序所使用的數據結構。
最后,附上Github地址,里面有游戲下載鏈接和相關工具,需要請自取:
https://github.com/TonyChen56/GameReverseNote
總結
以上是生活随笔為你收集整理的011 数据结构逆向—二叉树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 010 数据结构逆向—链表
- 下一篇: 012 分析技能冷却二叉树