外掛學習之路(11)--- 揹包資料的遍歷
查詢資料主要包括:揹包資料遍歷、NPC資料遍歷、怪物資料遍歷、地面物品資料遍歷、技能列表遍歷、周圍玩家資料遍歷、地圖資料的查詢、人物資訊的查詢等等。
本次只討論需要遍歷的資料
為什麼要遍歷資料?
一般來講是給我們找到的call當引數使用的,比如我們找到打怪call,但是這個call需要一個引數是怪物的指標,我們上哪去弄這個指標?我們只能去遍歷怪物資料,這些資料包括怪物指標,怪物的座標,怪物的血量,名字等等資訊,把有用的資訊提取出來,用程式語言寫個資料結構把它存起來供我們使用時候用。
需要遍歷哪些資料?
不同資料需要不同的資訊,如果是提供給call使用的話,我們主要看call需要什麼型別的資料,是怪物的指標啊,還是怪物的ID,當然我們也可以遍歷一些用處比較少的屬性,比如怪物名字
找到的遍歷結果一般是什麼樣子的?
本次不討論連結串列結構和二叉樹結構,只討論陣列結構,比如我們找到的揹包物品個數的陣列的形式可能是:
個數=[[[[[基地址]+a]+b]+格子編號*0x40]+c
這個時候我們就發現[[[[基地址]+a]+b]+格子編號*0x40是某個格子的指標,從而推匯出其他屬性,比如我們可能推匯出
名字=[[[[[基地址]+a]+b]+格子編號*0x40]+d
最大疊放=[[[[[基地址]+a]+b]+格子編號*0x40]+e
使用等級=[[[[[基地址]+a]+b]+格子編號*0x40]+f
物品ID=[[[[[基地址]+a]+b]+格子編號*0x40]+h
………
所謂推到辦法,就是看看揹包資料,再看看記憶體資料比較下,猜測出偏移,再驗證下,驗證方法:修改記憶體,看看物品有沒有相應的更改。
如何遍歷揹包物品資料
好了,不廢話,說說如何查詢這個陣列,首先我們必須有個切入點,揹包物品最好從揹包中某項物品的個數入手,因為很多情況這個數目不止一個,並且可以改變,比如血瓶,右擊一下就減少一瓶。
我們直接有CE搜尋995,使用一瓶搜尋994,搜尋出來兩個結果,
再改變數量發現還是這個兩個地址,這兩個地址都是正確的,但是他們表達的含義不一樣,我們將血瓶移動到第二個格子看看,發現一個值變為0,這就說明這個地址指向的是揹包第一個格子中物品的數量,而不是血瓶數量
我們檢視訪問這個地址的程式碼,然後把血瓶移回第一個格子,看到程式碼
開啟OD,找到程式碼,找到代表物品數量的表示式[eax+14],下面的工作就是找基地址,找這個eax的基地址。
第一個格子中物品的數量=[[[[[[[[15AC044]+10+4]+4]]]+0C+4]+30+4]+ 0*0x28 +0x14]
如何確定這是個陣列呢,以及第二個格子和第一個格子的差別應該差在哪裡?這個一般在尋找基地址時候就會發現,
比如,舉個例子,我們首先得到 第一個格子中物品的數量=[eax+14],我們挪動血瓶發現eax的值每個格子都不一樣,並且是個等差數列,這不就明顯了嗎?哈哈
研究遊戲名字為《龍武》實戰檢測,他的揹包資料很奇葩,有兩個基地址,前32個格子統一基地址,剩餘格子(不足32個)另一個基地址。最終確定格子中物品數量表達式為:
前32個格子:[[[[[[[15AC044]+10+4]+4]]]+0C+4]+30+4]+ 格數*0x28 +0x14 格數範圍0-1f
剩餘格子: [[[[[[15AC044]+10+4]+4]+8]+0C+4]+30+4] + 格數*0x28 + 0x14
尋找資料的思路:
上面就是按照數量的找法,也有看過相關教程按照每個格子的指標找的,即,每個(些)都應該有個指標,格子會盛放這些指標,互相改變格子中的物品,這些指標也應該隨之改變,並且空格子的指標應該為0,按照這個思路用CE找,也可以找到一個數組,一個指標的陣列。但是這些指標是否有用的,如果有call直接使用這些指標的話,這些指標就是游泳的,如果沒有的話,還有需要研究這些指標指向的地址盛放的東西的話,這個研究方式就不太好了,最好是直接下手,需要數量陣列就從數量下手,需要ID陣列就從ID下手,需要名字就從名字下手。
追尋基地址的一些實戰感悟:
感悟1:
毫無疑問如果可以用CE就能找到基地址的話,那實在是太方便了,快速而高效,但是有些時候我們只用CE找不到基地址,這個時候我們只能用OD了,最好是OD和CE結合著用,沒找到一個地址就先用CE試一下。有時純CE找不到基地址原因如下:
1.用CE搜尋一箇中間地址,搜尋搜尋結果為空。(中間地址:非基地址,如:物品個數=[[435C9660+0C+4]+30+4] + 格數*0x28 + 0x14,這其中的不是基地址,我們把它簡稱為中間地址)
2.搜尋到了地址,右鍵檢視訪問程式碼,結果沒有程式碼出現
3.出現了訪問程式碼,最後也找到了一個綠色的地址,突然發現這個綠色地址盛放值是可以變動的,突然為0了等等。
感悟2:
有時候用OD跟蹤找基地址,會發現越來越深,這個時候最好做箇中間記錄,省的一次追不完,下次又得重頭開始追查,比如我們追揹包中物品數量的基地址,可以先做個記錄
物品數量= [[435C9660+0C+4]+30+4]+ 格數*0x28 + 0x14
並且記錄下追到的程式碼地址,下次接著從這塊程式碼入手,
00E07BD1 8B4D EC MOV ECX,DWORD PTRSS:[EBP-14]
00E07BD4 83C1 10 ADD ECX,10 ; ecx=11014270
00E07BD7 E8 A4140000 CALLLWClient.00E09080 ; 關鍵call,在堆疊中寫入435C9660
00E07BDC 8D55 F0 LEA EDX,DWORD PTRSS:[EBP-10]
00E07BDF 52 PUSH EDX
這個結果最好驗證下(驗證方法,dd [[435C9660+0C+4]+30+4] + 格數*0x28 + 0x14,如果435C9660是個堆疊地址需要在程式碼處下斷點再執行命令)
感悟3:
基地址巢狀很深,最後追到基礎地址卻忘了一路是怎麼過來的,不得不模擬走好幾遍才能把最後的表示式寫出來,這時有個方法,很有效,方法如下:
比如我們先追到了一段,記錄下
品數量= [[435C9660+0C+4]+30+4]+ 格數*0x28 + 0x14
接著我們追這個435C9660的地址是怎麼來的,沒遇見一次賦值記錄下來,沒有偏移並且沒有指標就不記錄了,比如move eax,ecx就不用記錄了,追的地址沒變,記錄下每次地址改變值,直接記錄值就可以了,記暫存器名字反倒不方便,記錄如下:
435C9660=[435C9740]
435C9740=[435C9420]
435C9420=[1B757924]
1B757924=1B757920+4
1B757920=[11014280+4]
11014280=11014270+10
11014270=[15AC044]
把這些地址迭代進去就可以得到最終的基地+偏移表示式了
物品數量= [[[[[[[15AC044]+10+4]+4]]]+0C+4]+30+4]+ 格數*0x28 +0x14