针对“扫雷“和“植物大战僵尸“游戏,分析,扫描,阳光值,植物,金币,僵尸的分析逆向
《軟件逆向分析》
2022年9月
目錄 {#目錄 .TOC-Heading}
[一、實驗工具介紹 3](#一實驗工具介紹)
[二、針對"掃雷"游戲 3](#二針對掃雷游戲)
[2.1分析"初級"、"中級"和"高級"的棋盤內存地址范圍
3](#分析初級中級和高級的棋盤內存地址范圍)
[2.2找出"雷數"、"笑臉"和"計時器"的內存地址
9](#找出雷數笑臉和計時器的內存地址)
[2.2.1 "雷數"的內存地址 9](#雷數的內存地址)
[2.2.2 "笑臉"的內存地址 11](#笑臉的內存地址)
[2.2.3 "計時器"的內存地址 15](#計時器的內存地址)
[2.3分析雷存放算法 16](#分析雷存放算法)
[2.4利用思維導圖分析"掃雷"游戲軟件的工作原理(設計原理)
19](#利用思維導圖分析掃雷游戲軟件的工作原理設計原理)
[三、針對"植物大戰僵尸"游戲
21](#三針對植物大戰僵尸游戲)
[3.1安裝"植物大戰僵尸",完成詳細逆向復現報告
21](#安裝植物大戰僵尸完成詳細逆向復現報告)
[3.1.1針對"陽光值" 22](#針對陽光值)
[3.1.2找到陽光值的內存基址,簡述如何分析和找出基址的過程
26](#找到陽光值的內存基址簡述如何分析和找出基址的過程)
[3.1.3畫出陽光值的內存訪問示意圖或工作原理;
37](#畫出陽光值的內存訪問示意圖或工作原理)
[3.1.4分析陽光值功能實現的設計算法
38](#分析陽光值功能實現的設計算法)
[3.1.5分析陽光值的相關匯編語言代碼的工作過程
39](#分析陽光值的相關匯編語言代碼的工作過程)
[3.1.6 畫出逆向分析的思維導圖,并將以說明其逆向原理
40](#畫出逆向分析的思維導圖并將以說明其逆向原理)
[3.1.7 分析該軟件所用內存,并畫圖說明其數據分布
40](#分析該軟件所用內存并畫圖說明其數據分布)
[3.1.8 實現自動收集陽光,并詳細說明原理
42](#實現自動收集陽光并詳細說明原理)
[3.2針對"植物" 50](#針對植物)
[3.3針對"金幣" 54](#針對金幣)
[3.3針對"僵尸" 58](#針對僵尸)
[3.3.1掃描僵尸的數量 58](#掃描僵尸的數量)
[3.5針對"關(級別)" 62](#針對關級別)
一、實驗工具介紹
Cheat
Engine是一款專注于游戲的修改器。它可以用來掃描游戲中的內存,并允許修改它們。Cheat
Engine的用法也不是很復雜,首先是要先打開游戲,然后打開Cheat
Engine,點擊左上角的那個電腦圖標,在彈出來的框中選擇游戲進程,然后選擇掃描類型和數值類型,進行掃描并修改。內存掃描是Cheat
Engine的最主要功能之一,它可以掃描指定數值的內存地址,通過修改這些數值來達到修改游戲數據的目的,從而達到諸如無限生命、時間或彈藥等優勢。
二、針對"掃雷"游戲
2.1分析"初級"、"中級"和"高級"的棋盤內存地址范圍
分析:掃雷有空白和數字,我們可以選擇未知的初始值進行掃描,然后把重置后的數值與之前的進行比較,采用變動的數值/未變動的數值進行掃描
這里我們選擇xp版的掃雷進行這個經典的試驗
取消快速掃描→掃描類型→選擇→未知的初始值→點擊初級棋盤上第一格→進行首次掃描
1.首次掃描后已經有了很多條結果,點擊"游戲",然后新開一局(前排溫馨提示:按f2鍵可快速開啟新局,效率翻倍)
2.觀察第一個格子的內容,發現和上一局一樣是空白
3.選擇"未變動的數值",點"再次掃描"
當遇到第一格有數字的情況時(當出現的數字不一樣時,也代表它發生了變化),證明這一格數據發生了變化
選擇"變動的數值"
再次掃描
一直重復上述步驟,直到出現基址
掃描到結果后將其記錄,用同樣的方法找到最后一格的基址
初級棋盤第一格和最后一個地址:
中級棋盤第一格和最后一個地址:
高級棋盤第一格和最后一個地址:
可得棋盤的地址范圍為:
初級棋盤 0100535E ~ 01005469
中級棋盤 0100535E ~ 01005550
高級棋盤 0100535E ~0100555E
也可以進入內存,找到對應的地址進行查看,如圖所示:
2.2找出"雷數"、"笑臉"和"計時器"的內存地址
2.2.1 "雷數"的內存地址
地雷數在一局中是不會改變的,但是在改變難度的時候雷數會改變(初級:10個
中級:40個
高級:99個),可以在改變難度后搜索變化的值,在難度不變的時候搜索不變的值,最終篩選出基址。
1.點擊"游戲"打開"自定義"
2.查看當前雷數
3.輸入數據,開始掃描
修改雷數數值,繼續搜索,最終留下三個基址,將三個數據一起拉入工作區。
我們可以嘗試先找到旗子的地址。插一個旗子之后,觀察三個基址,發現旗子的地址
因此可以排除上述三個基址中的一個
改變其中一個數據的數值然后新開一局,觀察左上顯示雷數的數值是否變為和輸入的值相同。若是相同,則可以確定該地址為雷數基址(本實驗中三個值查找出的地址都顯示為綠色,即三個地址都是基址,所以不需要再查找每個地址的偏移值。若是查找出的地址為黑色,則必須找到該值真正的基址,通過查找"是什么訪問了這個地址"或者"是什么改變了這個地址"來查找上一級地址,重復多次相同的操作后找到綠色的地址,這是查找基址的任務才完成);若不同,則繼續測試下一個地址。本實驗中將這三個基址都改為"1"雷數,以此可以快速驗證雷數是否修改成功。
最終這里雷數內存地址為:010056A4
2.2.2 "笑臉"的內存地址
通過分析可得"笑臉"一共有四種表情,分別是在平時普通的笑臉,勝利時戴墨鏡的臉,失敗時悲傷的臉,點擊格子時張嘴的臉。分析出這四種表情以后,就可以通過改變笑臉的表情來搜索變化的值找到控制笑臉的數值(通過編寫程序的經驗,對于這類只有三四個選項的變量時,往往會編寫一個變量,每個值代表一個選項,而且根據經驗而談,這類flag值一般都設為個位數,即0,1,2,3…通過對掃雷的逆向分析推導出該變量的編碼),找到值后,就可以找到基址。由于雷數太多導致實驗時間太長,所以提前修改我們上一個找的雷數值,將其修改為2,這樣可以加速試驗的時間。
1.這里建議通過ce,修改為2
2.老規矩,取消快速,選擇未知,點擊掃描
中間的一般都是雷,可以插旗子控制輸贏,或者踩雷來控制"笑臉"
開始時笑臉不變,搜索"未知的數值",在勝利時笑臉帶墨鏡,踩雷時表情變化,(在搜索笑臉時最好搜索勝利時的墨鏡臉和失敗時的悲傷臉,點擊時的張口臉由于太快可能CE修改器無法捕捉到,不過可以在測試一個地址是否為笑臉基址時使用,這個數值比較少見可以代表改變表情的特征)表情變化時搜索"變化的數值",表情不變時搜索"未改變的數值"。
可以在中間表情不變的時候或者結果數量一直不變的時候,搜索幾次"未變動的數值",可以篩除掉很多數據
重復多次,找到四個結果,修改結果觀察笑臉表情是否變化(此處需要再次點擊格子刷新),若變化,則該地址為笑臉基址;若沒有變化則繼續測試下一個地址。
最終找到笑臉的內存地址01005160
2.2.3 "計時器"的內存地址
計時器無法搜索精確數值,只能通過它的特性來查找,經過觀察可得,計時器在不斷增長,一次我們得知可以查找"增加的數值",要注意的是開局之后點擊一次格子,計時器才開始計時,在重置棋盤之后到點擊第一個格子之前這段時間里計數器一直為0,此時若是可選數據有很多,可以精確搜索0,來篩選數據。
搜索"未知的初始值",點擊一個格子,開始計時后搜索"增加的數值",多次搜索。
找到與頁面計時器同步增長的數值,那該地址即為計時器基址。
最終找到計時器的內存地址0100579C。
2.3分析雷存放算法
在整個掃雷軟件的項目中,一定存在一種用于布雷的算法,它主要決定了每一局中雷所放的位置,它被主函數調用的時機也決定了掃雷游戲中存雷的算法。分析他的算法對于理解掃雷游戲的運行有很大幫助。
首先我們要知道布雷函數被主函數調用的時機,根據觀察可得,打開掃雷游戲之后,自動生成初級掃雷游戲,那么軟件會在這個時候就調用布雷函數將雷的位置定好了嗎?咱們做一個實驗:打開掃雷軟件點擊固定位置的一個格子,點擊一個格子后就點擊f2重置棋盤,再次點擊上次點擊的格子,多次實驗。
結合之前咱們ce找各種內存地址時候的經驗,我們不難發現,每開局第一次點擊的格子都是安全地帶,無數次試驗中沒有一次第一次就踩到地雷。如果主函數在最初就調用布雷函數,那么一次就踩到雷的概率應該是40/256(中級棋盤),而實際測試出的結果是0,大概率說明我們一開始的假設------認為在棋盤初始化后就已經調用布雷函數的觀點是錯誤的。
所以我又做了第二個實驗,測試第二次是否能踩到雷。和第一個實驗的流程相同,同樣是選取了兩個固定的格子,進行了50次實驗,總結實驗數據后發現第二次踩雷的概率基本與理論上的概率擬合(40/255)。
甚至咱們還可以利用之前搜索到的"雷數內存地址",不能白搜是吧。
中級棋盤一共256個格子,游戲設定上限是225個雷,通過修改咱們改為255個雷!看看第一格格子會不會直接踩到。
結果可想而知。
通過實驗的結果比對,可以得出一個結論:主函數在第一次點擊棋盤上任意一個格子之前沒有調用布雷函數,也就是說無論玩家第一次點擊棋盤上任一格子都不會踩到雷,因為此時的棋盤上還不存在地雷,而在玩家點擊第一個格子之后到點擊第二個格子之前已經調用布雷函數,這時棋盤上的地雷才布置好。
此時我們知道了布雷函數在主函數的調用時機是在點擊第一個格子之后,那么在布雷的時候就要避免將雷布置在第一個格子上,否則在玩家點擊第二個格子之后會直接按踩雷結算。那么就需要在布雷函數中傳遞一個表示當前第一個格子的坐標的參數。我們先假設棋盤上的每一個格子位置都是由二維數組存儲的,這樣在傳參時只需傳遞橫坐標的值和縱坐標的值即可。
經過第二次實驗我發現每次重置后地雷的布置基本上沒有規律可循,我們先假設每次都是隨機布置地雷位置,那么我們可以用srand函數產生隨機數種子,以便在之后隨機分配橫縱坐標。以中級難度為例,我們需要提前知道需要多少雷數以及棋盤的長和寬,所以在調用布雷函數時也要把所需雷數和棋盤的長寬傳參過來。知道雷數后設一個循環函數知道所需雷數全部布置好。同時要注意需要跳過在前文中提到的第一次點擊格子位置,我所猜測的掃雷布雷算法的循環體結構如下:
其中row和col為第一次點擊格子的橫縱坐標,m_uMineNum為所需地雷數,m_uYNum和m_uXNum分別為棋盤的長和寬。因為隨機數的產生沒有限制范圍,所以會出現超過已有棋盤范圍的可能,為了解決這個問題,我對產生的隨機數取余,使其永遠在棋盤限制的范圍內。對于調過第一個格子的問題,我采用條件語句加continue跳過本次循環的語句來解決,經過編譯證實其與原版掃雷軟件的效果相同。
現在我們已經找到了符合要求數量的雷的位置,接下來我們需要做的是埋雷,根據經驗我們需要在循環體中設置一個埋雷語句。做這個工作時我們要注意隨機數會出現重復數據的現象,我們不需要在已經埋好雷的位置再次埋入新雷,所以我們需要避開已經埋過雷的位置。我所編寫的猜測代碼如下:
ATTRIB_MINE為地雷的標識碼,如果一個格子的標志值uAttrib與ATTIB_MINE相同的話,這個格子處埋著地雷。我使用了一個條件語句避開已經埋過雷的格子。將循環體的index放入這個條件語句中是因為只有找到一個沒有埋過雷的格子才算埋好雷,若是將index放在條件語句之外,會導致還沒有埋夠所需要的雷數就已經停止循環,無法達到需求。
到這里為止猜測布雷函數的基本功能已經編寫完畢,經過實驗驗證,用這個猜測函數做出來的掃雷游戲與原版掃雷游戲規則與功能基本相似,可以證明掃雷軟件的布雷算法基本與我們所猜測的一致。
2.4利用思維導圖分析"掃雷"游戲軟件的工作原理(設計原理)
點擊工具欄的"游戲",在等級區可以選擇難度,選擇初級顯示的是99的棋盤和10個地雷,選擇中級顯示的是1616的棋盤和40個地雷,選擇高級顯示的是16*30的棋盤和99個地雷,選擇自定義可以彈出一個彈窗自主輸入長度、寬度和雷數。
點擊工具欄的"游戲",取消"顏色"的選擇,整個界面變為灰白色。
點擊工具欄的"游戲",選擇"聲音",玩游戲時音效出現。
點擊工具欄的"游戲",選擇"掃雷英雄榜",可以查看每個難度最高紀錄,選擇左下角"重新計數",所有記錄清零。
點擊工具欄的"游戲",選擇開局,重置棋盤。左鍵點擊棋盤任意一個格子給這個格子插上旗子,同時顯示的雷數變少,當所有雷所在的格子被插上旗子,則判斷勝利。
右鍵點擊棋子任意一個格子,如果是第一次點擊格子,不會踩到雷。之后再點擊格子,如果這個格子里是雷,那么判定失敗;如果這個格子周圍8個格子中有雷,那么顯示周圍雷的個數(只有1,2,3這三種可能);如果這個格子周圍無雷,自動打開周圍8個格子。若是周圍8個格子的外圍有雷則隱藏含雷的格子,打開其他無雷的格子,以此類推。
三、針對"植物大戰僵尸"游戲
3.1安裝"植物大戰僵尸",完成詳細逆向復現報告
為了方便版本切換,這里我選擇網絡上的植物大戰僵尸綠色版,解壓即所得。方便快捷。
3.1.1針對"陽光值"
要求采用3種以上的方法掃描至少3關的"陽光值"的內存地址,并能修改;
第一種:精確數值修改陽光值
"精確數值"搜索初始陽光150
種下豌豆射手,消耗陽光到50,再次搜索,只留下一個地址
修改為999,游戲陽光值發生變化,驗證成功,確定為陽光的內存地址
第二種:根據增加的數值或減少的數值改變陽光數
首先搜索陽光初始值,結果如圖
種下一個植物,選擇"減少的數值",再次搜索,只存在一個結果
修改為666,游戲陽光值發生變化,驗證成功,確定為陽光的內存地址
第三種:根據數值增加了…或數值減少了…改變陽光數
老規矩,精確值搜索,然后種下一顆100陽光的"豌豆射手"!
搜索類型選擇"數值減少了…"100,然后再次掃描
修改為888,游戲陽光值發生變化,驗證成功,確定為陽光的內存地址
3.1.2找到陽光值的內存基址,簡述如何分析和找出基址的過程
以上題為例,已經改好的一次陽光值為888,在此基礎上找基址,如上圖所示,內存地址"1CB66A68"就是存放陽光的地址,我們可以隨意的修改此內存中的數值。但是此地址是動態的,下次運行游戲時它存放的肯定就不是陽光了,我們要繼續查找不會變的靜態地址。
1.在地址欄中,選中該行,點擊鼠標右鍵,選擇點擊"找出是什么訪問了這個地址"
2.將出現確認框,默認"Yes"。點擊確認Yes后將會出現有匯編代碼的窗口,如圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-538xXguP-1668256101901)(./media/image39.png)]
3.里面可能是空白的;切換回游戲,隨便種一棵植物(目的是讓陽光變少,好找出哪些代碼修改了此內存)﹔再回到CE,會看到剛才的空白對話框中已經有內容了
4.拾取一個陽光,陽光增加,發現多了三條指令
5.選中最后一行代碼,并點擊"詳細信息",將會出現一個新的窗口,窗口中的信息可以復制粘貼。咱們將偏移量記錄好。
分析:在詳細的信息中展示的是匯編語言的實現過程,[]中的值表示的是內存偏移地址,因此[]的出現表示的是內存的出現。即陽關的地址存放在內存單元中。上圖中我們可以得知add
[eax+5560],ecx這條指令是加法運算,最右側ECX里面就是我們當前需要增加的陽光數,將ECX中的陽光數賦值給[eax+5560]這個內存地址,那么我們的陽光就會增加,此時我們需要知道EAX寄存器指向的地址是多少,CE中已經為我們分析出了EAX寄存器當前值是1CC3D388我們此時需要記下它的一級偏移5560,然后去搜索1CC3D388這個內存地址。
6.
根據詳細信息中給出的十六進制數,進行新的搜索,搜索指針數值,此次搜索的是十六進制數值所以需要勾選數值框前面的"十六進制"框
分析:通過搜索指針數值之后會發先還有很多的結果,此時我們根據所搜索到的地址的形式進行分析,在這些內存地址中以001開頭的地址,以及以193開頭的地址出現的數目都是很多的,這么多的地址不具有特殊性,因此它們不會是陽光的基地址。然而此時出現了一個特殊的地址0281A368、0CDB72E4和0CDB7474,這三個地址顯然是很特殊的三個地址,那么在這么多地址中,由于它們比別的地址更加具有特殊性,那么它們就最有可能又來繼續搜索靜態基地址。
7.根據上述的分析,我們將目光鎖定到了0281A368、0CDB72E4和0CDB7474這三個最特殊的地址身上。雙擊將這它們地址記錄到下方。
8.由于此時并沒有出現綠色的靜態基地址,所以我們繼續搜索,右鍵點擊,什么訪問了這個地址
在這個地址下,采集陽光,我拾取了3次,這邊計數符合
第二個不是
第三個地址,這里我拾取兩次陽光,計數和陽光沒有關系,也不是這個。
所以回到第一個地址,重新試驗
拾取2次陽光,找到對應指令
通過觀察什么訪問了這個地址,發現箭頭所指向的指令是會隨著陽光的產生而發生變化。窗口中會出現一大堆指令,這里也需要一個遍歷技巧,我們可以排除CMP之類的對比指令,因為我們是增加陽光所以不可能出現對比的代碼,此外我們需要關注操作數左側是EAX的,因為我們要找的是誰給EAX賦值的,我們選擇mov?eax,[edx+00000768]這條匯編指令,然后發現二級偏移是768。
此時我們根據給出的16進制數值進行搜索
那么這個時候我們就索搜到了綠色的靜態地址,這些綠色的地址都屬于靜態的,到此說明我們已經找到了這個陽光的基地址了,這里我們可以隨意選擇綠色的地址作為基址使用。
但是還需要判斷哪個是陽光的基地址?
對四個地址逐一進行分析
通過觀察什么訪問了這個地址發現,之后箭頭所指向的指令是會隨著陽光的產生而發生變化,所以第二個地址就是陽光的基地址
最后我們通過查找到的基址與偏移相加的形式,就可以定位到動態地址了,具體公式應該是陽光=
[[[006a9ec0]+768]+5560],我們可以直接在CE中添加這個指針,用于進行測試,操作如下:
點擊手動添加地址,將這個特殊的地址輸入到地址框中,點擊下方的指針按鈕,根據上面的記錄,輸入偏移地址,確定具體數值。然后鎖定數值。
根據上述流程可以排除另外兩個的偏移地址,所以02819C00中涉及到的偏移量分別為:00005560、00000768,分別點擊"添加偏移"加入其中。有一個小細節是當你輸入正確的基地址和偏移量后,右上角顯示當前陽光數的時候,就代表你找對了
重新開始游戲確認陽光是否實現了永久鎖定
綜上所述,陽光的基地址是006A9F38。
3.1.3畫出陽光值的內存訪問示意圖或工作原理;
3.1.4分析陽光值功能實現的設計算法
我們先來說一下為什么會有動態地址與基址的概念!
大部分編程語言都會有局部變量和全局變量,相對于局部變量來說是在游戲運行后動態分配的默認由堆棧存儲,而全局變量則是我們所說的基址其默認存儲在全局數據區,全局數據區里面的數據則是在編譯的時候就寫入到程序里了,所以不會變化,而游戲的開發都會使用面向對象技術,我們可以推測游戲中的陽光很可能就是類中的一個數據成員,而數據成員的地址就是通過new動態分配的,如下代碼:
#include <stdio.h>
class SunClass{
public:
int SunTime;
int SunValue;
int SunAttr;
};
int main()
{
SunClass *Sun=new SunClass;
Sun->SunValue=100;
printf("SunValue: %d
",Sun->SunValue);
return 0;
}
如上代碼定義了SunClass類,在主函數中我們為Sun實例指針動態分配了內存,分配的內存存儲在棧中,而棧地址每次都會發生變化,所以分配的內存地址是不固定的,從而導致陽光的地址是動態的
3.1.5分析陽光值的相關匯編語言代碼的工作過程
通過編程的方式讀取并修改我們的陽光數量,如下這樣一段代碼,它可以實現讀取動態地址并修改陽光數量。
#include <iostream>
#include <Windows.h>
int GetDyAddr(int Pid,int Base, int Offset[], int len)
{
int temp;
HANDLE Process;
Process = OpenProcess(PROCESS_ALL_ACCESS, false, Pid);
ReadProcessMemory(Process, (LPVOID)Base, &temp, 4, NULL);
for (int i = 0; i < len; i++)
{
if (i == len - 1)
temp += Offset[i];
else
ReadProcessMemory(Process, (LPVOID)(temp + Offset[i]), &temp, 4,
NULL);
}
return temp;
}
int main()
{
int base;
int offset[3];
int PID = 5772;
base = 0x006a9ec0;
offset[0] = 0x768;
offset[1] = 0x5560;
int addr = GetDyAddr(PID, base, offset, 2);
printf("進程地址:%x
", addr);
HANDLE Process = OpenProcess(PROCESS_ALL_ACCESS, false, PID);
WriteProcessMemory(Process, (LPVOID)addr,&PID,4,0);
}
3.1.6 畫出逆向分析的思維導圖,并將以說明其逆向原理
3.1.7 分析該軟件所用內存,并畫圖說明其數據分布
HWND的hWnd = FindWindowEx(NULL,NULL,“XXXX”,“XXXX”);/
/這里是游戲過程中,窗口的名稱和窗口類名。
PVOID PADDR =(PVOID)0x43158F";
DWORD dwProcessId和= 0;
GetWindowThreadProcessId(HWND,dwProcessId和);
操作的hProcess = OpenProcess(PROCESS_VM_WRITE |
PROCESS_VM_OPERATION,FALSE,dwProcessId和) /
/適當的權限來打開游戲過程中得到處理。
和DWORD dwWritten = 0;
BYTE bCode =的0xe5;
的hProcess,PADDR,bCode,大小(bCode),與dwWritten
WriteProcessMemory();
CloseHandle的(的hProcess);
3.1.8 實現自動收集陽光,并詳細說明原理
通過陽光增加的值為切入點,找到自動收集陽光的關鍵判斷并實現自動收集陽光,首先我們猜測當陽光出現后,我們是否會去點擊,這個過程必然是由一個判斷和一個時鐘周期事件來控制的,那么當我們點擊下落的陽光以后,則該判斷條件實現,會執行收集陽光的CALL,否則的話繼續執行陽光下落的過場動畫,這正是正向開發的一種開發手段,此時我們也僅僅是猜測,接下來我們將去驗證這個大膽的想法。
為了找到陽光自動收集的關鍵跳轉,我們需要以陽光增加作為切入點,為啥以它作為切入點呢?我們可以這樣思考,當我們點擊陽光后陽光增加了,說明已經完成了判斷,下一步就是寫入變量從而增加陽光。
那么我們先來找到陽光的動態地址,并在該動態地址上右鍵,選擇"找出是什么改寫了這個地址",然后回到游戲等待陽光出現并點擊陽光,
此時CE會出現代碼,點擊00430A11這個內存地址,然后點擊"顯示反匯編程序"
右鍵點擊設置斷點,然后返回游戲 繼續撿陽光
撿起陽光,陽光值增加,程序運行到斷點,游戲暫停,右邊加載出寄存器信息
這里add
[eax+00005560],ecx,ecx的值為19,轉化為10進制為25,也就是我們撿到的一個陽光,將25添加給了[eax+00005560],所以斷定這里的增加陽關的.
此時我們需要逆向思考一個問題add
[eax+0x5560],ecx這條指令是在我們陽光被點擊后執行的,也就是說我們已經點擊了陽光現在開始賦值了,那判斷陽光是否被回收肯定是在這條指令之前出現,所以我們向上找。
觀察代碼我們不難看出執行add
[eax+0x5560],ecx指令之前有一個無條件跳轉jmp 0x00430A0E跳過來的。
繼續向上查找跳轉來源,可知在jmp跳轉之前有一個je
0x004309EF跳轉,經過測試這個地方具體控制陽光是否增加,在向上找就到段首了,此處代碼中并沒有出現自動收集陽光的關鍵跳轉,因此推斷這里應該是一個控制陽光是否增加的子過程(子過程:過程中調用的過程,稱為子過程),所以我們繼續回朔到上一層。
點擊"調試",然后"退出—執行直到返回"
找到call 00430E40,接著向上找跳轉,找最近的一個jne,會看到有一個jne
00431599此處如果將其改為jmp的話即可實現自動收集陽光,也就是說如果jne跳轉實現則執行收集陽光,否則繼續執行陽光下落的過場動畫。
找到jne代碼,修改為jmp之后,就實現了自動拾取陽光的功能。
現在游戲是停止狀態,我們點擊運行,當拾取陽光,游戲繼續暫停的時候,我們找到當時下的斷點,刪除他游戲就可以正常運行了。
已經實現了自動拾取陽光,原理就是:jne指的是鼠標點擊陽光才能跳轉到收陽光,jmp是無條件跳轉,所以實現了自動拾取陽光
3.2針對"植物"
1)將植物"向日葵"的狀態定義為:拿起(暗色,冷卻中)為"0",放下(亮色,可以放置)為"1"。我們以植物"向日葵"為例來學習植物的冷卻時間的基址掃描方法。
注意"數值類型"改為"字節"
(2)查看掃描的結果。選中后點擊鼠標右鍵,選擇"找出是什么改寫了這個地址",如圖所示:
因為我們要找的這個地址是特殊值,所以優先查找獨一無二
特殊的地址,這里可以把大批量的21FC開頭的地址過濾掉。
(3)看到窗口中出現的代碼的動作和植物的操作一致。
00488E73 - C6 45 48 00 - mov byte ptr [ebp+48],00 拿起
0040CDEA - C6 44 08 70 01 - mov byte ptr [eax+ecx+70],01 放下
選中第2行代碼,分析放下植物(亮色)的數據,如圖所示:
(4)切換成4字節,再掃描16基址的地址指針"131A5310",同樣的方法得到下面的窗口,如圖所示:
(5)再掃描地址指針,分析掃描結果。選擇有與植物操作有關的信息,如圖所示:
(6)點擊"詳細信息",如圖所示:
(7)再選擇指針進行掃描,如圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3YQgZ514-1668256101924)(./media/image84.png)]
看見綠色的地址就是靜態地址。
多找幾個植物,我們就可以發現,基地址是一樣的,如圖所示:
3.3針對"金幣"
(1)通過cE工具收索游戲本次運行的金幣基地址。猜想:金幣和數字對應比例,可能是1:1,也可能是其他比例。分析:金幣顯示的值不是數字1:1關系,我們只能通過范圍收索的方式定位金幣的地址了
(2)首先未知的初始值進行掃描,如圖所示:
(3)不改變金幣,再次進行掃描,如圖所示:
(4)變動金幣,進行掃描,如圖所示:
(5)重復上述步驟,直至找到極少的地址。我們可以發現。唯有一個地址與金幣的數值最接近,我們雙擊把它放到下方地址欄中,可以知道它的比例是10:1,如圖所示:
(6)像找陽光值的地址步驟一樣,找到金幣的基地址,如圖所示:
(7)觀察數據結構,找到了金幣的基地址,如圖所示:
3.3針對"僵尸"
3.3.1掃描僵尸的數量
(1)數僵尸的數量,進行首次掃描,如圖所示:
(2)改變僵尸的數量,再次掃描,知直到掃出一個地址,如圖所示:
(3)找出是什么訪問了這個地址,像陽光基址一樣操作,直到找出綠色的地址,如圖所示:
(4)添加指針,找到僵尸的基地址,如圖所示:
5.2.4.2掃描僵尸的血量
(1)首次選擇未知的初始值,進行首次掃描,如圖所示:
(2)被僵尸被豌豆射手打中時,進行減少的數值的掃描,如圖所示:
(3)被僵尸不被豌豆射手打中時,進行不變的數值的掃描,如圖所示:
(4)反復重復以上步驟,直到掃到一個地址為止,如圖所示:
(3)通過分析結構,我們可以找到相關的屬性,如圖所示:
3.5針對"關(級別)"
(1)第一關進行,首次掃描1,如圖所示:
(2)第二關進行,再次掃描2,如圖所示:
(3)第三關進行,再次掃描3,如圖所示:
(4)第四關進行,再次掃描4,如圖所示:
(5)通過觀察發現,此地址為關卡的地址。
掃描僵尸的血量
(1)首次選擇未知的初始值,進行首次掃描,如圖所示:
[外鏈圖片轉存中…(img-lhPbmRsa-1668256101932)]
(2)被僵尸被豌豆射手打中時,進行減少的數值的掃描,如圖所示:
[外鏈圖片轉存中…(img-Yg9I8K2i-1668256101932)]
(3)被僵尸不被豌豆射手打中時,進行不變的數值的掃描,如圖所示:
[外鏈圖片轉存中…(img-nB2gSUYt-1668256101933)]
(4)反復重復以上步驟,直到掃到一個地址為止,如圖所示:
[外鏈圖片轉存中…(img-saYPPto2-1668256101933)]
(3)通過分析結構,我們可以找到相關的屬性,如圖所示:
[外鏈圖片轉存中…(img-RN0uT3HK-1668256101934)]
3.5針對"關(級別)"
(1)第一關進行,首次掃描1,如圖所示:
[外鏈圖片轉存中…(img-CVJGJJYQ-1668256101935)]
(2)第二關進行,再次掃描2,如圖所示:
[外鏈圖片轉存中…(img-HwedHiy2-1668256101935)]
(3)第三關進行,再次掃描3,如圖所示:
[外鏈圖片轉存中…(img-Wc83SPYi-1668256101936)]
(4)第四關進行,再次掃描4,如圖所示:
[外鏈圖片轉存中…(img-wUqWXcDF-1668256101936)]
(5)通過觀察發現,此地址為關卡的地址。
[外鏈圖片轉存中…(img-wpcHhMPV-1668256101937)]
總結
以上是生活随笔為你收集整理的针对“扫雷“和“植物大战僵尸“游戏,分析,扫描,阳光值,植物,金币,僵尸的分析逆向的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不可小觑的吃内存大户
- 下一篇: 【AI视野·今日CV 计算机视觉论文速览