植物大戰僵屍:無冷卻分析方法


植物大戰僵屍這款游戲可以說是很多90后的回憶了,基本上只要是90后或多或少的都接觸過,而玩游戲與制作輔助是兩個概念,今天我將給大家分享一些游戲輔助方面的制作技巧,之所以使用植物大戰僵屍這款游戲是因為游戲簡單容易分析,且不需要考慮驅動保護版權等相應的問題,這里我會把我的分析思路分享出來,來供大家參考。

植物無冷卻的實現

根據上節課查找太陽花生產速度的遍歷技巧,你一定會想到,此處植物的槽位有很多個,那我可不可以通過上節課的內容,找到兩個相鄰植物之間結構的相對偏移,然后找到第一個植物的基址並通過基址與偏移動態獲取冷卻數據呢?

想法雖然是不錯,不過此處如果你去查找第一個植物的基址的話,或許會讓你失望,你根本找不到第一個植物的基址!原因很簡單,植物冷卻結構是游戲運行后動態開辟的內存空間,該空間可能通過堆棧存儲數據。

並且游戲作者也並沒有分別給每一個植物分配一個定時器,而是使用了一個通用定時器來管理所有植物的冷卻,如果去查基址無論查找哪個植物最終都會定位到時鍾的計時代碼上,你或許會想,尼瑪一個定時器管理所有植物冷卻?怎么可能,其實是可以的!經過我的分析,我寫出了大體實現代碼,游戲中的冷卻實現可能是如下代碼:

#include <stdio.h>

struct MyStruct
{
	int BotanyID;         // 植物ID號
	int BotanyTime;       // 植物當前時間
	int BotanyRecTime;    // 冷卻周期
	int BotanyFlag;       // 當前植物狀態
};

int main()
{
	struct MyStruct SunFlower = { 0, 0, 700, 0 };     // 太陽花動態地址
	struct MyStruct Botany = { 1, 0, 1000, 0 };       // 豌豆射手動態地址
	while (true)
	{
		SunFlower.BotanyTime++;
		Botany.BotanyTime++;

		if (SunFlower.BotanyTime == SunFlower.BotanyRecTime)
		{
			SunFlower.BotanyFlag = 1;
			SunFlower.BotanyTime = 0;
			printf("太陽花冷卻完成了....\n");
		}
		else if (Botany.BotanyTime == Botany.BotanyRecTime)
		{
			Botany.BotanyFlag = 1;
			Botany.BotanyTime = 0;
			printf("豌豆射手冷卻完成了....\n");
		}
		Sleep(10);   // 模擬時鍾定時
	}
	return 0;
}

上方代碼中,結構體MyStruct部分存儲的就是單個植物的屬性,其中植物的屬性可能包括植物ID,植物當前冷卻計時,植物冷卻周期,以及植物的當前狀態,而隨着選擇不同植物卡片,游戲會根據選擇植物的多少以及植物屬性來動態分配內存空間。

經過對游戲的分析,冷卻時間是一個遞增的定時器(此處可通過CE查找驗證),作者為什么會用遞增計時器呢?因為遞增到一定程度變成0,0則表示冷卻完成,那么也就不需要單獨使用一個標志位來存儲植物當前狀態了。

除此之外,游戲中控制植物冷卻的時鍾只有一個,那么通過遞增計時器,對照不同植物的冷卻周期,就可用一個定時器控制所有植物冷卻,而如果用遞減定時器,雖然也可以,但是卻不方便編程實現。

接下來我們將去驗證這一個猜測,首先說一下無冷卻的遍歷技巧,無冷卻的話有兩種方式可以遍歷:

無冷卻的遍歷技巧1
打開CE->回到游戲種植一顆向日葵 -> 掃描未知初始數值
然后切回游戲 ->馬上切回CE ->搜索變動的數值 -> 一直重復 ->直到冷卻結束
此時不進行任何建造 -> 回到CE -> 搜索未變動的數值 -> 依次排查

無冷卻的遍歷技巧2
打開CE-> 搜索類型選擇字節類型-> 在植物亮的狀態時搜索1
拿起植物-> 搜0 -> 放下植物搜1 ->拿起植物搜0-> 一直重復-> 地址一般在最后面

這里我經過分析知道了這個定時器是一個遞增定時器,那么我就使用查找遞增的方式來找了,節約時間。

首先當關卡開啟時,默認櫻桃炸彈是在冷卻狀態下的,我們直接搜索未知初始化數據,然后回到游戲搜索增加的數值不斷重復,當櫻桃炸彈冷卻結束后直接搜索減少的數值,由於冷卻結束這個數值會變為0,因此直接找數值是0的哪一個就是櫻桃炸彈的冷卻時鍾,找到后直接查看寫入,會得到0048728C - 83 47 24 01 - add dword ptr [edi+24],01

接着我們種下一個豌豆射手,然后用同樣的遍歷技巧找到豌豆射手的冷卻周期,同樣的查找寫入,會發現其出現的地址與櫻桃炸彈地址相同,說明游戲中所有的植物都是在共用add dword ptr [edi+24],01這條代碼進行計時的。

此時我們知道了櫻桃炸彈的冷卻時間地址是011F33CC我們還知道豌豆射手的地址是011F332C,接下來我們通過使用CE提供給我們的插件,結構爬行器來對比兩個結構之間的差異,可知偏移為0的位置就是我們植物的當前冷卻時間,而緊隨其后的5000/750則分別代表的是植物的冷卻周期,最后的2代表的櫻桃炸彈卡片的位置,而0則代表豌豆射手的卡片位置。

分析到此接下來就是修改了,此處我們有兩種修改方式,第一種是修改植物的冷卻時間鎖定為0,即可實現植物無冷卻,另一種改法是將植物的冷卻周期修改的低一些,這樣同樣能實現快速完成冷卻。

我們的冷卻地址是一個動態的,下一步應該是找基址,不過這款游戲中的無冷卻無法直接找到基址,不信你可以找找看!

為了能通過編程的方式修改程序,此處我們可以直接使用硬編碼的方式寫入內存數據,如下圖所示:

上圖中已經做好了備注,此處改法有很多,你可以直接將add dword ptr ds:[edi+24],1里面的1修改為64這樣一來植物的冷卻速度就會變快,其次你也可以直接將jle plantsvszombies.4872AC處的指令直接nop掉,由於所有植物都會共用這一處區域進行冷卻的驗證,所以只要此處修改,所有的植物都會無冷卻。

原創作品:轉載請加出處,您添加出處,是我創作的動力!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM