010 数据结构逆向—链表
文章目錄
- 逆向周圍對(duì)象鏈表
- 總結(jié)
之前我們已經(jīng)通過人物的血量找到了人物的屬性數(shù)組,接下來學(xué)習(xí)一下鏈表。
逆向周圍對(duì)象鏈表
這一次要找的目標(biāo)是人物周圍的對(duì)象鏈表,包括人物周圍的NPC和怪物等等。找這個(gè)數(shù)據(jù)結(jié)構(gòu)的突破口有很多,可以通過人物本身,也可以通過NPC和怪物。
這里還是以人物血量為突破口,之前我們已經(jīng)用人物血量去找到了屬性的數(shù)組,但是同一個(gè)突破口通過不同的訪問代碼可以逆向分析出不同的數(shù)據(jù)。
和之前的方式一樣,用CE找到當(dāng)前的人物血量,然后在這個(gè)位置下硬件訪問斷點(diǎn)
點(diǎn)擊當(dāng)前的人物血量
斷點(diǎn)斷下,[eax+8]是人物的血量,追eax的數(shù)據(jù)來源,eax來自[esi+0xC],繼續(xù)往上追esi
血量=[esi+0xC]+8esi來自于ecx,返回上層找ecx
ecx又來源于ebx
血量=[ebx+0xC]+8ebx來源ecx
ecx來自[esi+C]
血量=[[esi+C]+0xC]+8在這里查看一下血量的值,每一次斷點(diǎn)斷下,存儲(chǔ)血量的地址和esi的值都會(huì)不斷發(fā)生變化。
這個(gè)地方的地址一直發(fā)生變化說明是已經(jīng)來到了一個(gè)數(shù)據(jù)結(jié)構(gòu),如果這個(gè)地方單純的存放的是人物血量的話,就是基址+偏移的方式,不會(huì)發(fā)生改變。
繼續(xù)往上追esi
esi來自[eax]
血量=[[[eax]+C]+0xC]+8eax這個(gè)時(shí)候只有兩個(gè)值在發(fā)生變化,而且偏移表達(dá)式的地址,不管斷下多少次都沒有發(fā)生改變。
從這個(gè)地方的變化說明esi的值不來源于eax,也就是說當(dāng)前的代碼不是順序執(zhí)行的,有可能是進(jìn)到了循環(huán)里面。
那么就有必要分析一下當(dāng)前的這段代碼
這里有一個(gè)向上的跳轉(zhuǎn)是當(dāng)前的循環(huán)尾部,jmp跳轉(zhuǎn)的目標(biāo)地址是循環(huán)頭部,中間的代碼相當(dāng)于是循環(huán)體了。
esi不來自循環(huán)體外的eax,也就說明是來自循環(huán)體內(nèi)的[esi],esi再往上找還是沒有發(fā)現(xiàn)來源,說明當(dāng)前的這一句代碼一直在循環(huán)取值。
如果和數(shù)據(jù)結(jié)構(gòu)聯(lián)想到一起的話,很明顯這個(gè)地方是一個(gè)單向鏈表,C++代碼如下
class Node { public:Node<T> *next;T data;上面這段代碼就是通過對(duì)Node節(jié)點(diǎn)的循環(huán)遍歷,來找到想要的目標(biāo)節(jié)點(diǎn)。跳出循環(huán)體外
esi來源于[eax],eax就是當(dāng)前的鏈表頭,這里可以對(duì)當(dāng)前的鏈表進(jìn)行取值
第一個(gè)對(duì)象血量:[[[[eax]]+C]+0xC]+8 第二個(gè)對(duì)象血量:[[[[[eax]]]+C]+0xC]+8 第三個(gè)對(duì)象血量:[[[[[[eax]]]]+C]+0xC]+8我們已經(jīng)找到了鏈表的數(shù)據(jù)結(jié)構(gòu),這個(gè)時(shí)候就沒有必要繼續(xù)往上追了,意義不大。剩余的對(duì)象屬性各位可以自己去分析
總結(jié)
對(duì)于鏈表的逆向來說,需要時(shí)刻關(guān)注追數(shù)據(jù)過程中每一步的數(shù)據(jù)結(jié)構(gòu)變化,特別是變化比較明顯的那一種。識(shí)別鏈表的標(biāo)識(shí)在于是否有匯編代碼在遍歷當(dāng)前的鏈表不斷進(jìn)行取值,例如:
mov eax,[eax];最后,附上Github地址,里面有游戲下載鏈接和相關(guān)工具,需要請自取:
https://github.com/TonyChen56/GameReverseNote
總結(jié)
以上是生活随笔為你收集整理的010 数据结构逆向—链表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 009 数据结构逆向—数组(困难版)
- 下一篇: 011 数据结构逆向—二叉树