红色警戒2修改器原理百科(六)
??? 先說一件事情,昨天我在繼續(xù)OD調(diào)試游戲的時候,運行錯了版本,然后OD的備注、標簽和斷點通通沒有了。喜大普奔上天關(guān)上了一扇門,然后我開了一扇窗戶——拋棄之前的枷鎖,重新出發(fā),目前來看可能是找到了判斷地圖觸發(fā)器的整個過程,待進一步測試;還找到了立即勝利的源頭。
??? 讓我們書接上回。
(十三)枚舉地圖玩家——隱藏在背后的黑暗勢力
??? 如果細心的你在進行上一步的瘋狂的掠奪的時候,發(fā)現(xiàn)了沒人占有的建筑物的pOwner不是NULL,你就可能發(fā)現(xiàn)一片新大陸。是誰擁有了這個建筑物,卻還能顯示沒有歸屬。
??? 前一篇最后一個圖,轉(zhuǎn)移所屬函數(shù)(call [ebx+378])前面有這么備注的一個CALL:玩家ID獲取數(shù)據(jù)基址(其實這個描述不準確),不知是否注意到了?當時調(diào)試時,傳入ECX=0,EAX返回玩家數(shù)據(jù)地址,然后粗略的看了看里面的循環(huán),就做了個這樣的標簽。畢竟能返回玩家數(shù)據(jù)地址的函數(shù),需要一個參數(shù),那八成就是玩家ID,因為咱就是本地第一個玩家,就是0號位置咯。聯(lián)網(wǎng)對戰(zhàn)時,才會變成其他位置,單機只能在0號。。。
??? 既然有這么一個ID,就來找找ID在哪個偏移處。用CE的分析數(shù)據(jù)/結(jié)構(gòu)功能,對比分析地圖上所有玩家數(shù)據(jù)(通過電腦建筑的pOwner獲得電腦玩家數(shù)據(jù)地址,我測試時就兩個玩家,我用美國,對手是簡單的蘇聯(lián)),同時嘗試發(fā)現(xiàn)一些其他顯而易見的數(shù)據(jù),只發(fā)現(xiàn)偏移+30處比較明顯,我是0,電腦是1。基本就確定(玩家數(shù)據(jù)地址——[game.exe+635DB4])+30偏移就是玩家ID。然后就是一堆不明顯的數(shù)據(jù),一大片0。
??? 然而,當我因某些原因又去看了下那個所謂的CALL<玩家ID獲取數(shù)據(jù)基址>,卻發(fā)現(xiàn)沒有一條指令讀取了+30偏移,Amazing!然后仔細跟蹤發(fā)現(xiàn)一個莫名其妙的循環(huán)次數(shù),地圖上有2個玩家,卻循環(huán)了4次。嘗試3個玩家,結(jié)果循環(huán)5次。而且和參數(shù)ECX比較的是玩家數(shù)據(jù)+34偏移處的一個地址的+B8偏移處的數(shù)據(jù),文字表述比較復雜。C語言描述就是:if (CurrentPlayer.onePointer->oneValue == ECX)。
??? 這個oneValue,它永遠和玩家ID相同的嗎?冥思苦想一番,這個指針指向的是什么結(jié)構(gòu)?最終從地圖編輯器獲得靈感,地圖上的單位歸屬可以設(shè)置給不同國家,還有平(即無歸屬)和治安(一個神秘的組織),這就解釋了為什么循環(huán)次數(shù)永遠多兩次:平和治安在你看不到的地方,作為特殊玩家一直存在。也解釋了單位看起來沒有歸屬,實際上還是有個歸屬者。玩家數(shù)據(jù)+34偏移是所屬勢力對象指針,所屬勢力對象結(jié)構(gòu)的+B8偏移是勢力編號。那么這個CALL的準確備注應(yīng)該是:勢力編號獲取數(shù)據(jù)基址。
??? 現(xiàn)在才算進入正題了,來分析下這個函數(shù)(004ED760),就能找到枚舉全圖玩家的必要條件了:地圖玩家數(shù)(包括平和治安)(game.exe+6322A8),地圖玩家數(shù)組(game.exe+63229C)。然后你就能知道他們有多少錢,有幾個步兵,有幾個建筑等等等等,這些偏移比較好找。
??? 號外,好像是在一個蘇軍任務(wù)上發(fā)現(xiàn),玩家ID終于不是0了,因為劇情是強行登陸建立基地,我是侵略者還有最后一關(guān),俘獲總統(tǒng)任務(wù)地圖上有13個玩家(還有兩個隱藏的更深的勢力叫GDI和Nod)——我眼瞎,玩得時候沒看到。。
(十四)立即勝利——來打我啊~
??? 如果對游戲編程有些許了解的話,一個簡單的小游戲的大概框架簡單描述如下:
int main() {init(); //程序初始化,防止重復啟動等setGameOption();startGame();cleanup();return 0; }void startGame() {initGame(); //初始化數(shù)據(jù),加載資源while(true){doSomething();draw();if (gameIsOver())break;} }??? 由此,只要找到游戲的主循環(huán)就很容易找到游戲判斷結(jié)束的地方。游戲的所有操作都在doSomething()里,對于具體游戲而言,當然會有好多層調(diào)用,在游戲的一個操作斷下后,一直返回上層,就可以來到主循環(huán)了。
??? 就以建造單位時金錢減少為例,應(yīng)該是這個地方:
然后查看調(diào)用堆棧:
game.<ModuleEntryPoint>+0DB就是調(diào)用程序main()函數(shù)的地方,前面都是編譯器附加的初始化代碼;
繼續(xù)往上看,game.00690883:
看到字符串“Main_Game”,估計00690883就對應(yīng)上面所說的startGame()函數(shù)。
繼續(xù)往上, game.00481DBA:
??? 這段比較長,因為實際情況不可能像上面那么一個簡化的模型那么簡單。圖中“game loop finished”是OD自己分析出來的程序內(nèi)部字符串,另外我添加的“//”開頭的注釋也讓這段程序的流程變得很清晰。注意紅警和上述游戲模型的異同!
進入0053F840:
??? 通常游戲中會設(shè)置一個邏輯變量來標識是否結(jié)束,當結(jié)束條件滿足時,被設(shè)置成TRUE,所以可以注意mov [xxxxxxxx],1;
??? 從上圖看出,al=1游戲就結(jié)束了,可以從函數(shù)尾向上分析al如何變成1的;
??? 也可以把類似“[A35DB1]”這樣的固定的內(nèi)存地址都添加到CT表中,觀察游戲結(jié)束時是怎樣的狀態(tài),然后依次修改;
??? ……等等其他方法。
最后給出,其實就是上面的提到的,立即勝利=1(字節(jié),game.exe+635DB1)。
To be continued…
轉(zhuǎn)載請注明來源,http://www.cnblogs.com/viewll/p/4773802.html
轉(zhuǎn)載于:https://www.cnblogs.com/viewll/p/4773802.html
總結(jié)
以上是生活随笔為你收集整理的红色警戒2修改器原理百科(六)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SAP 财务月结之 外币评估(TCODE
- 下一篇: 快捷方式图标变成白色