最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(7-反作弊機(jī)制:數(shù)據(jù)加密)

2022-08-21 18:18 作者:圍巾胖頭魚  | 我要投稿

說在前面:

????上期專欄介紹了原版綠寶石中反作弊機(jī)制的一種:跳動(dòng)的指針。本期專欄將繼續(xù)介紹一種反作弊機(jī)制的常見方法:數(shù)據(jù)加密。

背包道具數(shù)量修改:加密的數(shù)字

????在另一個(gè)系列的專欄究極綠寶石5.3——科普向,什么是金手指(三)中,作者提到了利用VBA模擬器中的“查找金手指”功能來找到游戲中的變量。如果一個(gè)游戲變量體現(xiàn)在游戲中恰好就是數(shù)字的形式(而不是文本、圖片等),用“查找金手指”的“追蹤式變量取值查找”功能可以將它快速定位。

????然而,上面這個(gè)方法能夠生效的關(guān)鍵在于:這個(gè)數(shù)字在游戲中和在程序代碼中是一致的。比如金幣數(shù)在游戲界面中顯示是10000,在程序代碼中代表金幣的變量取值也是10000;花費(fèi)一些金幣讓金幣數(shù)變成9000,那么程序代碼中相應(yīng)的變量也會(huì)變成9000。只有這樣查找變量取值才有意義。

????于是,一種反作弊機(jī)制就是對(duì)變量的取值進(jìn)行加密,讓變量的取值和游戲界面上顯示的數(shù)字不一致,這樣就無(wú)法通過“查找金手指”中的“精確查找”功能找到想要的變量了。

????關(guān)于這種反作弊機(jī)制,本期專欄給出例子是:原版綠寶石中背包道具數(shù)量的修改。

? ? 首先來看看源代碼項(xiàng)目中背包道具的信息在ROM中的什么位置:

背包道具

????其實(shí)上期專欄也提到了背包道具,它位于SaveBlock1結(jié)構(gòu)體內(nèi),在上圖的第950~954行。這5行定義,每行都是bagPocket_后面跟著一個(gè)不同的后綴,Items是道具,KeyItems是重要道具,PokeBalls是精靈球,TMHM是技能機(jī),Berries是樹果,恰好對(duì)應(yīng)了背包內(nèi)道具的5種類型。

????現(xiàn)在只關(guān)注一個(gè):道具bagPocket_Items,里面存放的是類似傷藥、驅(qū)蟲噴霧劑、先制之爪之類的道具。它位于結(jié)構(gòu)體內(nèi)相對(duì)地址0x560處,這個(gè)數(shù)字之后要用。

????用VS Code可以方便地查看到BAG_ITEMS_COUNT是30,也就是說道具欄最多只能存放30個(gè)道具,這就是原版綠寶石游戲的設(shè)定。轉(zhuǎn)到struct ItemSlot的定義:

ItemSlot的定義

????可以看到定義十分簡(jiǎn)單,用2個(gè)字節(jié)來表示道具的編號(hào),再用2個(gè)字節(jié)來表示道具的數(shù)量。4字節(jié)表示一個(gè)道具,連數(shù)據(jù)對(duì)齊的問題都不需要考慮了(數(shù)據(jù)對(duì)齊的問題在之前的專欄口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(2-基于名稱列表的詳情信息提取)提到過)。

????從上期專欄可以知道,想要找到背包道具的地址,首先需要到gSaveBlock1Ptr的位置去看這個(gè)指針指向了什么地址,該地址就是gSaveBlock1,然后在這個(gè)地址上加上0x560這個(gè)相對(duì)地址,就可以定位到背包道具了。作者在游戲中做如下嘗試:

查看gSaveBlock1Ptr

????gSaveBlock1在03005D8C處,現(xiàn)在顯示的取值是02025A44,再加上0x560就是02025FA4,然后再來到這里查看:

查看背包道具變量

????? ? 按理說,從02025FA4這里開始,就應(yīng)該按照struct ItemSlot的定義,每4個(gè)字節(jié)描述一條道具,前兩個(gè)字節(jié)是道具的編號(hào),后兩個(gè)字節(jié)是道具的數(shù)量。其中道具編號(hào)如何提取已經(jīng)在之前的專欄口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(1-字符集與文本信息的提取)說得非常清楚了(也就是金手指中提到的道具代碼)。

????按照上圖,0x0055對(duì)應(yīng)脫洞繩(Escape Rope),0x006F對(duì)應(yīng)心之鱗片(Heart Scale),0044對(duì)應(yīng)神奇糖果(Rare Candy)……這都沒有問題,直到0x0000表示這里沒有道具了。但是,0055后面的那個(gè)BA70是什么意思?背包中的脫洞繩只有4個(gè),這無(wú)論如何也跟BA70這個(gè)數(shù)字聯(lián)系不上。再觀察一下其他道具的數(shù)量,006F心之鱗片也是4個(gè),在內(nèi)存里面數(shù)字也是BA70;0044神奇糖果只有一個(gè),內(nèi)存中的數(shù)字卻變成了BA75。4比1大,但是BA70比BA75要小,頭一回看到這種對(duì)應(yīng)關(guān)系的讀者可能無(wú)法一眼看出來這兩者之間有什么關(guān)系。

????這就是加密,讓游戲中展示的數(shù)字和程序代碼中變量的取值不一致。如果想通過搜索道具數(shù)量來定位修改道具的金手指,就無(wú)法生效。

????有的讀者可能想去找找加密的規(guī)律了,逐一去比對(duì):4加密到BA70、1加密到BA75、2加密到BA76……可惜的是,原版綠寶石的加密沒那么容易破解。作者操控主角在周圍走動(dòng)一下,下樓上樓之后,再次打開“內(nèi)存查看器”,發(fā)現(xiàn)gSaveBlock1Ptr指向的地址已經(jīng)發(fā)生了變化(這在預(yù)料之內(nèi),上期專欄提到“跳動(dòng)的指針”就有這個(gè)特點(diǎn))。經(jīng)過一番計(jì)算,找到新的背包道具所在地址:

經(jīng)過一小段時(shí)間后的背包道具變量

????可以看到,0055、006F等這些道具的編號(hào)并沒有變化,但是道具數(shù)量對(duì)應(yīng)的那些內(nèi)存數(shù)據(jù)已面目全非,又變成了莫名其妙的9EAD、9EA8之類。這讓之前試圖找到加密規(guī)律的努力付之東流??磥?,背包道具的數(shù)量不但被加密了,還會(huì)隨著游戲流程不斷被再次加密,毫無(wú)規(guī)律可循。

????背包道具數(shù)量的反作弊機(jī)制,就是指針跳動(dòng)+數(shù)據(jù)加密的組合拳??磥碇缓玫皆创a項(xiàng)目中,從原理上理解一下它的加密過程了。

綠寶石怎么對(duì)數(shù)據(jù)做加密

????上期專欄提到了在尋找跳動(dòng)的指針時(shí),我們找到了load_save.c文件中的這個(gè)片段:

圖片來自上期專欄

????這是在函數(shù)MoveSaveBlocks_ResetHeap中。這里的函數(shù)名前半段MoveSaveBlocks說明了此函數(shù)的第一個(gè)功能:把存檔信息“移動(dòng)”一下。這里的“移動(dòng)”其實(shí)就是圖片中顯示的這一段代碼:改變指針指向的位置,將原本指針指向的內(nèi)容完全復(fù)制過來。繼續(xù)向下看:

MoveSaveBlocks_ResetHeap函數(shù)的末尾

????下面出現(xiàn)了一個(gè)被叫做encrptionKey的變量,它的含義是“加密密鑰”,是給數(shù)據(jù)加密用的??创a看到這里,就會(huì)發(fā)現(xiàn)這個(gè)變量十分可疑,源代碼項(xiàng)目給這個(gè)變量起這個(gè)名字肯定是有原因的。這個(gè)加密密鑰在第129行通過隨機(jī)數(shù)函數(shù)Random來取值,然后在第130行被用于ApplyNewEncryptionKeyToAllEncryptedData函數(shù)中,同時(shí)在131行還存儲(chǔ)在了gSaveBlock2里面。上面的注釋也提示(“create a new encryption key”),這部分代碼是要生成一個(gè)新的加密密鑰。

????ApplyNewEncryptionKeyToAllEncryptedData函數(shù)的名稱很長(zhǎng),但這就是源代碼項(xiàng)目翻譯質(zhì)量高的體現(xiàn)之一,它的含義是“將新的加密密鑰應(yīng)用于所有的加密數(shù)據(jù)”。這種良好的命名方式讓閱讀代碼的困難程度降低了太多太多,試想如果這個(gè)函數(shù)敷衍地用“Func_01”這種沒有任何信息量的名字來命名,那和去看匯編代碼還有什么區(qū)別?

????看來加密算法就藏在這個(gè)名字很長(zhǎng)的函數(shù)中了,來到它的定義:

加密算法的應(yīng)用范圍

????這個(gè)函數(shù)又包含了5個(gè)函數(shù),通過良好的命名,可以推測(cè)這些函數(shù)分別是給:游戲統(tǒng)計(jì)數(shù)據(jù)GameStats、背包道具BagItems、樹果粉末BerryPowder、金幣數(shù)money和游戲廳代幣數(shù)coins加密。新世界的大門仿佛已經(jīng)打開,這5個(gè)函數(shù)蘊(yùn)含著豐富的信息量,有興趣的讀者不妨去讀一讀這里的源代碼。本期專欄只看最相關(guān)的ApplyNewEncryptionKeyToBagItems_函數(shù):

????這個(gè)最后帶有一個(gè)下劃線的函數(shù)(不知道讀者在第一眼看到它的時(shí)候有沒有注意到)竟然只是給另一個(gè)函數(shù)套了一個(gè)殼,而這“另一個(gè)函數(shù)”的名字只是簡(jiǎn)單地去掉了下劃線。這種看似毫無(wú)意義的代碼寫法讓源代碼項(xiàng)目的作者也會(huì)吐槽:

????really GF?

????GF你認(rèn)真的嗎?(代碼寫成這樣就不要出來混了)

????題外話打住,來看ApplyNewEncryptionKeyToBagItems函數(shù),在第58行,終于出現(xiàn)了對(duì)道具數(shù)量quantity的加密函數(shù)ApplyNewEncryptionKeyToHword。這個(gè)函數(shù)有兩個(gè)參數(shù),第一個(gè)參數(shù)是道具數(shù)量,但前面還用了一個(gè)取地址運(yùn)算符&,說明這個(gè)函數(shù)是要修改第一個(gè)參數(shù)的值;第二個(gè)參數(shù)就是新的加密密鑰newKey。兜兜轉(zhuǎn)轉(zhuǎn),我們來到了加密算法的最后一站:

加密算法

????這個(gè)加密算法是如此地簡(jiǎn)單:異或操作。這個(gè)函數(shù)在276行執(zhí)行的其實(shí)是解密操作,也就是說,在第276行執(zhí)行之后,在第277行執(zhí)行之前,*hWord的取值就是它在游戲中對(duì)應(yīng)的數(shù)字。對(duì)于異或運(yùn)算來說,加密和解密的算法是一樣的,因?yàn)閷?duì)一個(gè)數(shù)字A來說,連續(xù)兩次異或同一個(gè)數(shù)字B,得到的還是數(shù)字A本身。回過頭來再看生成新密鑰的地方:

上面的圖搬下來繼續(xù)用……

????再來看第131行就好理解了,gSaveBlock2里存儲(chǔ)的加密密鑰是老版本的加密密鑰,這個(gè)函數(shù)做的事情是更新一下密鑰,并把之前所有的加密數(shù)據(jù)重新用新密鑰加密一遍。也就是為什么在游戲中,過一小段時(shí)間之后,道具數(shù)量那里對(duì)應(yīng)的變量取值會(huì)出現(xiàn)毫無(wú)規(guī)律的變化。

破解數(shù)據(jù)加密的金手指

????想要破解綠寶石的數(shù)據(jù)加密,需要對(duì)異或操作有一些基本的理解:

????任何數(shù)字X和0異或,得到的結(jié)果還是數(shù)字X本身。

????所以只需要把129行的C代碼改成:

就大功告成了。

????當(dāng)然,使用金手指的話還是得到綠寶石的ROM中去找匯編代碼。從符號(hào)表中可以找到MoveSaveBlocks_ResetHeap的地址是在08076c2c。

MoveSaveBlocks_ResetHeap的地址

????考慮到第129行是MoveSaveBlocks_ResetHeap的結(jié)尾位置,而匯編代碼的一個(gè)特點(diǎn)就是函數(shù)結(jié)尾的地方往往會(huì)出現(xiàn)pop指令。從VBA模擬器的反匯編窗口內(nèi),來到08076c2c向下搜索,可以在08076ce8開始向后找到3個(gè)pop指令:

函數(shù)結(jié)尾的pop指令

????上圖中最后一行bx r0可以看做是C代碼函數(shù)的return指令,而開頭的第1行和第3行(08076cc6和08076ccc)這兩處調(diào)用了同一個(gè)函數(shù),查找符號(hào)表可以知道就是Random函數(shù),這和C代碼的第129行,用兩次Random函數(shù)生成encryptionKey就對(duì)的上了。這里還是用的寄存器r4來存儲(chǔ)加密密鑰。

????順帶一提第5行和第6行(08076cd2和08076cd4)處對(duì)r0的兩個(gè)操作:先lsl,也就是左移16位;再lsr,右移16位。這種先左移再右移,移動(dòng)的還是相同的位數(shù),帶來的結(jié)果就是:r0的低16位保持不變,但高16位被清零了。也就是說,這兩句話相當(dāng)于對(duì)r0這個(gè)32位的數(shù)字進(jìn)行了一個(gè)強(qiáng)制轉(zhuǎn)換:

????在08078cd6處,原本的匯編代碼是為了完成計(jì)算encrytionKey的最后一步:

????只需要把它改成:

????加密密鑰就被固定成0,再也起不到加密作用了。

????通過在線網(wǎng)站https://armconverter.com/進(jìn)行轉(zhuǎn)換后,這條破解數(shù)據(jù)加密的金手指就是:

????本期專欄我們又看到了反作弊機(jī)制的一種方法:數(shù)據(jù)加密。并且破解它的過程也體現(xiàn)出了上期專欄說到的特點(diǎn):設(shè)計(jì)一個(gè)反作弊機(jī)制需要幾十行甚至上百行的C代碼,但是破解它往往只需要一兩行匯編代碼的修改。只不過想要找到這一兩行代碼位于何處,是需要對(duì)源代碼有一定程度的了解才行的。

????反作弊機(jī)制還不止指針跳動(dòng)和數(shù)據(jù)加密,下期專欄還會(huì)繼續(xù)介紹反作弊機(jī)制的其他方法。

????再次感謝眾位讀者的支持!

口袋妖怪綠寶石——數(shù)據(jù)提取與代碼分析(7-反作弊機(jī)制:數(shù)據(jù)加密)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
同江市| 宜黄县| 奎屯市| 商都县| 沧源| 大同县| 准格尔旗| 太谷县| 林甸县| 保山市| 南平市| 平昌县| 会泽县| 西平县| 文昌市| 南江县| 方正县| 清原| 辽源市| 永嘉县| 克山县| 会同县| 雷山县| 苏州市| 淄博市| 呈贡县| 屏边| 潢川县| 宁海县| 扶绥县| 万年县| 宁晋县| 库尔勒市| 山丹县| 儋州市| 千阳县| 朝阳县| 凤凰县| 靖边县| 合川市| 惠东县|