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