吞食鱼2(FeedingFrenzyTwo) 修改器
童年回憶系列。小時(shí)候特別喜歡玩這類游戲,軟件不大,很慢的網(wǎng)速也不會(huì)下載太久,然后對(duì)配置要求不高,很破的電腦也可以玩得很開(kāi)心。不過(guò)也有糟心的時(shí)候啊,大魚太多,無(wú)數(shù)次死于挑戰(zhàn)咬梭子魚的尾巴……今年最后一天,就休閑一小會(huì)吧。
小時(shí)候看不懂是啥意思,現(xiàn)在知道了,我來(lái)翻譯下第一段。
警告!
發(fā)現(xiàn)梭子魚在珊瑚礁附近游蕩。留意警告標(biāo)志,遠(yuǎn)離它張開(kāi)的大嘴!要是你有迷之自信,可以試著咬它的尾巴。咬 4 次就會(huì)有驚喜……如果到那時(shí)候你還活著……
現(xiàn)在再玩已經(jīng)沒(méi)有當(dāng)年的感覺(jué)了——鼠標(biāo)換了……其實(shí)我老早就想,為什么到了下一關(guān),我的魚就變小了??太不爽了。游戲里各種對(duì)玩家不利的設(shè)定:小魚不能吃大魚、被大魚追、被貝殼吃掉、被烏賊噴、被水母電、被大嘴鳥吞、被水雷炸、被河豚刺、吸水還要 CD、跳出水面翻滾的話進(jìn)水眩暈……所以只有修改內(nèi)存數(shù)據(jù)才是稱霸海洋的秘訣!
工具:Cheat Engine 6.4 (以前搞的漢化版,其實(shí)翻譯不完全,建議用英文版)
大,大,大
這個(gè)游戲的規(guī)則是吃小魚,躲大魚,等長(zhǎng)大了以后就可以吃遍全圖。成長(zhǎng)值進(jìn)度條在左上角,前面的關(guān)卡都是 3 個(gè)成長(zhǎng)階段,到了后面還有更多的級(jí)別。
好的,按照程序員的思路,姑且猜測(cè) growth 數(shù)據(jù)用整型存儲(chǔ),每種魚的加成不一樣,小魚少些,大魚多些,初始值為 0,打開(kāi) CE ,開(kāi)始搜索,每吃一條魚就搜一次“增加的數(shù)值”。
好的,沒(méi)搜幾次,輕松搜到 2 個(gè)值。嘗試修改第一個(gè),發(fā)現(xiàn)魚沒(méi)反應(yīng);再嘗試第二個(gè),魚長(zhǎng)大了!然后自然是一頓操作:找出改寫 -> 顯示反匯編,然后看到了如下代碼:
這也太舒服了,直接找到靜態(tài)地址005AC624,省的找基址了,直接手動(dòng)添加地址,growth 就有了。基址005AC624偏移+3C, +40(跟基址寫成 "FeedingFrenzyTwo.exe"+001AC624 是一樣的)
四兩吃千斤
修改 growth 的數(shù)值,就可以瞬間變大,通關(guān),但是這一點(diǎn)也不爽啊,我一定要把被吃的仇報(bào)了才行!
還是剛才的進(jìn)度條,用通常思路來(lái)猜,成長(zhǎng)階段數(shù)值分別是 0, 1, 2 ,姑且先試一下。借助修改 growth 值快速長(zhǎng)大,搜索這幾個(gè)值就很快了。
先嘗試修改第一個(gè),圖中我修改 0245AE24 的值為 0 以后,我 2 階的大魚被比我小的魚吃掉了,那應(yīng)該就是它了。觀察了一會(huì)發(fā)現(xiàn),這個(gè)值就是用來(lái)確定會(huì)不會(huì)被吃的,但是查找訪問(wèn)它的代碼并沒(méi)找到什么關(guān)鍵判定,代碼太多了,我也懶得看,反正只要不被吃復(fù)位,這個(gè)值就不會(huì)變,直接把它改大點(diǎn)就行了。
在魚變大的時(shí)候查找改寫它的地址,可以找到偏移量 EC
00496B47 - 89 99 EC000000 - mov [ecx+000000EC],ebx
再稍微調(diào)試跟蹤下,找到基址。基址005AC624偏移+40, +344, +0, +EC,類型我選了 byte ,不過(guò)應(yīng)該沒(méi)啥影響。
然而事實(shí)是,我不會(huì)被大魚吃掉了,但是在大魚旁邊的時(shí)候也不會(huì)觸發(fā)吃魚的動(dòng)作了……是太難吃了嗎?哈哈……不過(guò),離成功不遠(yuǎn)了。經(jīng)過(guò)一番探索,我用“增大的數(shù)值”搜索前邊的成長(zhǎng)階段,找到了另一個(gè)數(shù)值。簡(jiǎn)單點(diǎn)來(lái)說(shuō),這兩個(gè)值一個(gè)是玩家魚在電腦魚面前的大小,一個(gè)是電腦魚在玩家魚面前的小大。<- 我說(shuō)小大,因?yàn)榈诙€(gè)值數(shù)值越大判定電腦魚越小。
基址005AC624偏移+40, +344, +0, +F8,就在上一個(gè)值旁邊,很狡猾啊,這個(gè)值是從 1 到 3 的,之前搜精確數(shù)值的時(shí)候沒(méi)找到,早知道就先去看看數(shù)據(jù)結(jié)構(gòu)了。
把這兩個(gè)值同時(shí)改成 5 ,終于報(bào)了當(dāng)年的血海深仇,啊哈哈哈哈哈哈哈……
速度和位置
吸取剛才的教訓(xùn),現(xiàn)在來(lái)看看數(shù)據(jù)結(jié)構(gòu)。
嘿嘿,果然有了意外收獲。仔細(xì)觀察魚的狀態(tài)和數(shù)值,可以發(fā)現(xiàn)上面的 4 組浮點(diǎn)數(shù)分別代表魚的位置和速度,修改這些值可以讓魚瞬移到地圖任何地方。
然后我就有了一個(gè)大膽的想法——能不能把地圖里的其他魚瞬移到我嘴邊呢?省的亂跑了。事實(shí)是——YES! 首先要找到存放地圖上所有魚的地方。
拿玩家魚的位置來(lái)說(shuō),地址是 基址005AC624偏移+40, +344, +0, +98,按照程序的對(duì)象模型來(lái)想,+344指針應(yīng)該是玩家指針,里面存放了很多和玩家相關(guān)的數(shù)據(jù),剛才做四兩吃千斤的時(shí)候,數(shù)據(jù)也在這個(gè)對(duì)象下,那么看下+0指針應(yīng)該就是玩家的魚的指針了,我這次游戲的指針是 09397280 。好的現(xiàn)在假設(shè)有這么個(gè)全局魚數(shù)組,那么這個(gè) 09397280 也一定在里面,直接搜索這個(gè)指針:
嘿嘿,我為什么單獨(dú)標(biāo)出來(lái)這個(gè) 07EDC488 呢?因?yàn)榭磾?shù)據(jù)結(jié)構(gòu),在之前的 +344 指針前面,在 +324 指針的地方,指向的數(shù)據(jù)不就是 07EDC488 嘛,這應(yīng)該是個(gè)數(shù)組首地址,展開(kāi)一看,果然全都是魚!
魚是有了,可是數(shù)量不知道……這個(gè)數(shù)組沒(méi)有結(jié)束標(biāo)識(shí),貌似是像vector那樣管理的,有固定大小,靠整數(shù)標(biāo)記結(jié)束的位置,而游戲本身可能不記錄實(shí)時(shí)的魚數(shù)量,所以我找了一遍,一直沒(méi)找到數(shù)據(jù),也可能是我找的方法不對(duì)。魚在不同狀態(tài)的時(shí)候地圖上的魚數(shù)量會(huì)變,但是因?yàn)椴恢谰唧w值,非常難找,我猜測(cè)是一些常數(shù),規(guī)定了不同關(guān)卡魚的數(shù)量上限。
我還強(qiáng)行試了下移動(dòng)所有魚直到空指針,會(huì)訪問(wèn)銷毀過(guò)的魚對(duì)象而導(dǎo)致訪問(wèn)越界崩潰,問(wèn)題應(yīng)該出在這里 mov ebx,[eax+edi]//4*n ,edi 的值增大以后,eax+edi 就不一定是有效地址了。然而令人驚奇的是,只要不點(diǎn)錯(cuò)誤窗口上的確定鍵,就還可以繼續(xù)游戲!真神奇……腳本如下:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
//0051A002
alloc(newm,512)
label(nextfish)
label(exit)
newm:
pushad
mov eax,["FeedingFrenzyTwo.exe"+001AC624]
mov eax,[eax+40]
//GetPlayersFish
mov esi,[eax+344]
mov esi,[esi]//ThisIsThePlayersFishClass
//PlayerPosition
mov ecx,[esi+98]
mov edx,[esi+9C]
//GetYou(heiheihei)
mov eax,[eax+324]
mov edi,0
nextfish:
mov ebx,[eax+edi]//4*n
cmp ebx,0//NoNextFish
je exit
add edi,4
cmp ebx,esi//IsPlayer?
je nextfish
mov [ebx+98],ecx
mov [ebx+9C],edx
jmp nextfish
exit:
popad
ret
createthread(newm)
LdrInitializeThunk:
DB 8B FF 55 8B EC
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newm)
可以不理它,別點(diǎn)確定,直接返回游戲:
如果想穩(wěn)妥一點(diǎn),就去掉 jmp nextfish 這句,這樣就每次只移動(dòng) 1 只魚,因?yàn)榈貓D上一直會(huì)有一堆魚,所以低頻調(diào)用移動(dòng) 1 只魚的腳本是沒(méi)事的,也可以輕松疊滿 FRENZY
因?yàn)橐呀?jīng)可以四兩吃千斤了,所以繼續(xù)搞這個(gè)功能也沒(méi)啥必要了,就到此一游吧,不找魚總數(shù)了。
變小魔法
游戲里有很多有意思的道具,比如蘑菇,可以讓周圍的大魚變小;還有個(gè)紅色的瘋狂魚,可以時(shí)間停止然后自動(dòng)吃掉屏幕里的魚,如果能找到對(duì)應(yīng)的 call 就爽了。下面就來(lái)試一試。
首先我大概想了個(gè)思路,因?yàn)橹暗玫搅舜鎯?chǔ)魚 growth 數(shù)值的地方,電腦魚與玩家魚用的是同一個(gè)類,所以存儲(chǔ)的偏移應(yīng)該也是一樣的,所以查看數(shù)據(jù)結(jié)構(gòu)里全局魚數(shù)組,隨便找條大魚,查找改寫 growth 數(shù)值的地方,然后去吃個(gè)蘑菇。之后代碼斷在了 0041D744 ,這里沒(méi)什么有用信息,返回到上層函數(shù),發(fā)現(xiàn)了有意思的東西。
0042863F - 68 08B35500 - push 0055B308 : ["shrinkBurstFx"]
這個(gè)單詞 "shrink" 就是縮小的意思,再繼續(xù)向上返回查找,又發(fā)現(xiàn)了一個(gè)位置:
0049AA93 - 68 B8E65400 - push 0054E6B8 : ["fishShrink"]
然后我再繼續(xù)返回,發(fā)現(xiàn)到了外層大循環(huán),而函數(shù)內(nèi)部的斷點(diǎn)是在魔法光球打在魚身上的時(shí)候才會(huì)中斷,我們需要的函數(shù)卻是吃蘑菇的事件函數(shù)。好的,現(xiàn)在先暫停一下,縷縷思路:
玩家吃蘑菇
觸發(fā)吃蘑菇事件函數(shù),發(fā)出光球,目標(biāo)是電腦大魚
電腦大魚被光球打中,觸發(fā)縮小事件,縮小
我們剛才找的 "shrink" 相關(guān)的函數(shù)應(yīng)該是步驟 3 ,需要找的是步驟 2 ,而步驟 2 到步驟 3 應(yīng)該不在同一個(gè)函數(shù)中,它們之間應(yīng)該只是消息傳遞的過(guò)程,所以這個(gè)線索就斷了。
不過(guò),嘿嘿,代碼注釋里已經(jīng)給我們提供了新的線索——"shrink" 字符串。每次觸發(fā)事件的時(shí)候,就會(huì)引用和 "shrink" 相關(guān)的字符串,所以新的思路有了——搜索 "shrink" 字符串,然后查找什么訪問(wèn)了字符串,看看吃蘑菇的時(shí)候會(huì)斷在哪里。首先找到 078BBCF8 的位置是我們剛才找到的 "fishShrink" ,而就在它下面不遠(yuǎn)的位置,發(fā)現(xiàn)了 "shrinkPickup" ,地址是 078BBE10!!!哇,運(yùn)氣好到爆炸!
查找什么訪問(wèn)了 078BBE10 ,然后查看堆棧,在這個(gè)字符串附近的函數(shù)一個(gè)一個(gè)進(jìn)去看,終于在 004747CD 的地方找到了線索。
在004747CD 下斷點(diǎn),然后吃東西就會(huì)中斷,再向上返回,發(fā)現(xiàn)返回的位置和吃的東西有關(guān)。
吃蘑菇返回到這里
吃魚返回到這里
試了幾次,吃什么就會(huì)返回到什么地方,所以附近應(yīng)該就有吃的函數(shù)了,傳入的指針就是吃的東西,用多態(tài)的思想,吃什么就執(zhí)行什么的事件函數(shù),所以離勝利不遠(yuǎn)了……
經(jīng)過(guò)一番調(diào)試,終于找到了吃東西的函數(shù)——call [eax+90] ,就在 0042A98C 的地方,esi 是被吃的對(duì)象,+90 大概是虛函數(shù)表里執(zhí)行被吃事件的函數(shù)指針,參數(shù)是 edi ,儲(chǔ)存發(fā)起吃東西事件對(duì)象的指針,還有個(gè)寄存器參數(shù) ecx ,儲(chǔ)存的是被吃對(duì)象指針。一個(gè)以吃東西為游戲內(nèi)容的游戲,把吃東西的函數(shù)找到了,游戲結(jié)束!
后面的工作就輕而易舉了,下斷點(diǎn)在每次吃掉蘑菇的時(shí)候步入,就到了 004A249D ,這個(gè) call 00493BD0 就是我們苦苦尋找的吃蘑菇的事件函數(shù)了,這個(gè)函數(shù)只有一個(gè)寄存器參數(shù),就是 esi 儲(chǔ)存發(fā)起事件的對(duì)象指針,這里我們把玩家填進(jìn)去就好。還記得玩家指針在哪嗎?沒(méi)錯(cuò),就是之前找四兩吃千斤的時(shí)候找到的對(duì)象:基址005AC624偏移+40, +344, +0
然后寫出腳本,只要執(zhí)行這個(gè)腳本,就相當(dāng)于吃了蘑菇,變小魔法就會(huì)觸發(fā)了,大功告成。
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
//004A249D
alloc(newm,512)
label(exit)
newm:
pushad
mov eax,["FeedingFrenzyTwo.exe"+001AC624]
mov eax,[eax+40]
//GetPlayersFish
mov esi,[eax+344]
mov esi,[esi]//ThisIsThePlayersFishClass
call 00493BD0
exit:
popad
ret
createthread(newm)
LdrInitializeThunk:
DB 8B FF 55 8B EC
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newm)
狂吃
還是按照上面的思路,在0042A98C 的吃東西函數(shù) call [eax+90] 下斷點(diǎn),然后吃個(gè) "FEEDING FURY" 道具,找到對(duì)應(yīng)的代碼。很輕松就找到了,然后寫出下面的腳本。
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
//0053D05D
alloc(newm,512)
label(exit)
newm:
pushad
mov eax,["FeedingFrenzyTwo.exe"+001AC624]
mov eax,[eax+40]
//GetPlayersFish
mov esi,[eax+344]
mov esi,[esi]//ThisIsThePlayersFishClass
//feeding fury 00502399
add esi,00000154
mov eax,[esi]
mov ecx,esi
call [eax+20]
test eax,eax
je exit
mov eax,[esi]
mov ecx,esi
call [eax+20]
mov edx,[eax]
mov ecx,eax
call [edx+70]
exit:
popad
ret
createthread(newm)
LdrInitializeThunk:
DB 8B FF 55 8B EC
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newm)
防雷
直接找出是什么訪問(wèn)了玩家魚指針,然后去撞水雷。查詢過(guò)程非常卡,所以到了水雷旁邊再開(kāi)始查詢。撞到水雷時(shí),會(huì)出現(xiàn)一些新的代碼,一個(gè)一個(gè)找。運(yùn)氣很不錯(cuò),找第一個(gè)就發(fā)現(xiàn)了關(guān)鍵跳轉(zhuǎn)。
0050B773 - 75 30 - jne 0050B7A5 有魚死掉時(shí)的關(guān)鍵跳轉(zhuǎn)
再向下找,就在下面找到了魚撞雷死亡調(diào)用的函數(shù)
0050B798 - FF 90 DC000000 - call dword ptr [eax+000000DC]
當(dāng)玩家單位觸發(fā)時(shí)步入,里面只有 3 行匯編。
只要在玩家觸發(fā)水雷的時(shí)候跳過(guò)這個(gè)函數(shù)就可以了
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
push eax
mov eax,["FeedingFrenzyTwo.exe"+001AC624]
mov eax,[eax+40]
//GetPlayersFish
mov eax,[eax+344]
mov eax,[eax]//ThisIsThePlayersFishClass
//if player hit a mine
//then jump
cmp eax,ecx
pop eax
je exit
originalcode:
mov eax,[ecx]
call dword ptr [eax+000000EC]
exit:
jmp returnhere
"FeedingFrenzyTwo.exe"+102BE3:
jmp newmem
nop
nop
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FeedingFrenzyTwo.exe"+102BE3:
mov eax,[ecx]
call dword ptr [eax+000000EC]
//Alt: db 8B 01 FF 90 EC 00 00 00
因?yàn)檫@里的函數(shù)在其他事件觸發(fā)時(shí)也有被調(diào)用到,所以不知道這么改有什么副作用,暫且先這樣,等以后出了問(wèn)題再回來(lái)看……(懶)
另外還發(fā)現(xiàn)了銷毀玩家對(duì)象的函數(shù),不知道以后用不用得上。
00438EBD - FF 50 1C - call dword ptr [eax+1C] 玩家魚對(duì)象銷毀
其他
吸水能量條 基址"FeedingFrenzyTwo.exe"+001AC624 偏移 +40, +344, +0, +20C 類型是 float 從 0 到 1
吸水持久度 基址 005A7314 浮點(diǎn)數(shù) float,數(shù)值越小持續(xù)時(shí)間越長(zhǎng)
吸水恢復(fù)速度 基址 005A7318 浮點(diǎn)數(shù) float,數(shù)值越大恢復(fù)速度越快
直接過(guò)關(guān) 基址 005AC624 偏移 +40, +8C 字節(jié) byte ,改成 1 即可。大部分時(shí)候好用,個(gè)別關(guān)不行,不知道為啥
從空中翻滾后落到水里會(huì)暈一會(huì),這個(gè)腳本可以防止眩暈。其實(shí)功能非常簡(jiǎn)單,就是跳過(guò) mov byte ptr [ebx+0000019D],01 這一句。
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
jmp exit
originalcode:
mov byte ptr [ebx+0000019D],01
exit:
jmp returnhere
"FeedingFrenzyTwo.exe"+13FC74:
jmp newmem
nop
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"FeedingFrenzyTwo.exe"+13FC74:
mov byte ptr [ebx+0000019D],01
//Alt: db C6 83 9D 01 00 00 01
結(jié)語(yǔ)
總結(jié)
以上是生活随笔為你收集整理的吞食鱼2(FeedingFrenzyTwo) 修改器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 远程登录工具 —— filezilla(
- 下一篇: Navicat安装及简单使用