以下是【bjwj007】分享的內容全文:
小游戲 Brain Test 3 大腦測試3 跳過付費內容 無限內購
游戲屬于il2cpp,現在很多的安卓游戲都采用了這個打包。對于這類游戲,常見的改法是修改dex的入口,在入口處添加一個調用代碼,每次啟動都自動修改sp的long值,這樣就打到了無限金幣的目的。還有另一種改法就是直接修改so文件,通過修改底層代碼,可以實現的玩法也比較多,比如不減反增、定死數值、免費購物、全部解鎖等。但是相對的也比較麻煩,對于沒有匯編經驗的萌新來說,還是寫個Java實在。
軟件樣品為當前最新版1.50.0。
準備工具
1、IDA32
2、Il2CppDumper
想不到這游戲已經出到第三部了,前兩部我還發過帖子如何修改無限提示,不過是改dex的。現在換另一種方法,改so破解游戲。
游戲風格比較適合小朋友,有些關卡我實在想不通為什么是這樣……
游戲有廣告,怎么去掉我就不說了,用幸運破解器一鍵搞定就好了,來來去去都是那幾個熟面孔。

先看一下游戲界面,第一次玩游戲的時候會送50個電燈泡,正常情況下會越用越少,那么就會有相減的邏輯,修改so的時候可以利用相反的指令讓燈泡越來越多,也就是不減反增。
下好Il2CppDumper后,順序打開相應的文件,libil2cpp、global-metadata.dat。等待分析完成后打開dump.cs文件備用。
接著ida打開so文件,選擇左上角運行如下兩個腳本文件,靜靜等待加載完畢即可。電腦差的會比較久,可以先去喝杯奶茶再回來看看


之前說過這類游戲的數值一般儲存在sp里面,位于com.unicostudio.braintest3.v2.playerprefs.xml,打開后他是長這樣的:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <int name="cross_promo_id" value="61" /> <string name="unity.player_session_count">5</string> <int name="Screenmanager%20Resolution%20Height" value="2220" /> <string name="unity.player_sessionid">4976473052650692822</string> <int name="Gdpr_Control" value="1" /> <string name="NotificationHelper.Scheduled">273129443%7C1094985734</string> <int name="__UNITY_PLAYERPREFS_VERSION__" value="1" /> <int name="Screenmanager%20Resolution%20Width" value="1080" /> <string name="unity.cloud_userid">95a0dbb4b1309fcf094060f513e8d42d</string> <string name="playerData">%7B%22coins%22%3A5%2C%22OnCoinsChanged%22%3A%7B%7D%2C%22gems%22%3A0%2C%22OnGemsChanged%22%3A%7B%7D%2C%22hammers%22%3A0%2C%22OnHammersChanged%22%3A%7B%7D%2C%22adsRemoved%22%3Afalse%2C%22OnAdsRemovedChanged%22%3A%7B%7D%2C%22completedLevels%22%3A%5B1%2C2%2C3%2C4%2C5%2C7%2C8%2C9%2C10%2C11%2C12%5D%2C%22lastReachedLevel%22%3A13%2C%22lastPlayedLevel%22%3A13%2C%22hintsOpened%22%3A%7B%226%22%3A%5B0%5D%2C%227%22%3A%5B0%2C1%5D%7D%2C%22OnHintsOpenedChanged%22%3A%7B%7D%2C%22flags%22%3A%5B%22new_level_popup_showed%22%2C%22bonus_Bonus1_skipped%22%2C%22hint_LevelTricky1_0%22%2C%22hint_LevelTricky1_1%22%2C%22tricky_LevelTricky1_played%22%2C%22hint_Make_Potion_1%22%2C%22hint_Alchemy_1%22%5D%2C%22selectedPets%22%3A%7B%22cat%22%3A-1%2C%22dog%22%3A-1%2C%22bird%22%3A-1%2C%22frog%22%3A-1%7D%2C%22unlockedPets%22%3A%7B%22cat%22%3A%5B%5D%2C%22dog%22%3A%5B%5D%2C%22bird%22%3A%5B%5D%2C%22frog%22%3A%5B%5D%7D%2C%22activeActionLevel%22%3A1%2C%22LastReachedLevel%22%3A13%7D</string> <int name="Screenmanager%20Fullscreen%20mode" value="-1" /> <int name="rate_shown" value="1" /> <int name="shareClaimed" value="1" /> </map>
playerData里的coins就是電燈泡的數量,gems應該是鉆石。coins%22%3A5,這個5就是數量,當前為5。

然后搜索dump.cs里的playerData,只有一個結果,那么這里就是就是破解的關鍵入口。其中get_Coins、get_Gems這兩個都是比較常見的代碼,如果你不知道關鍵字可以先搜這兩個,看看有沒有相關信息。
// Methods
// RVA: 0x13D954C Offset: 0x13D954C VA: 0x13D954C public int get_Coins() { }
// RVA: 0x13D14DC Offset: 0x13D14DC VA: 0x13D14DC public void set_Coins(int value) { }
// RVA: 0x13D9554 Offset: 0x13D9554 VA: 0x13D9554 public int get_Gems() { }
// RVA: 0x13D75B4 Offset: 0x13D75B4 VA: 0x13D75B4 public void set_Gems(int value) { }
// RVA: 0x13D955C Offset: 0x13D955C VA: 0x13D955C public int get_Hammers() { }
// RVA: 0x13D9564 Offset: 0x13D9564 VA: 0x13D9564 public void set_Hammers(int value) { }
// RVA: 0x13D9604 Offset: 0x13D9604 VA: 0x13D9604 public bool get_AdsRemoved() { }
// RVA: 0x13D960C Offset: 0x13D960C VA: 0x13D960C public void set_AdsRemoved(bool value) { }
// RVA: 0x13D96B8 Offset: 0x13D96B8 VA: 0x13D96B8 public int get_LastReachedLevel() { }
// RVA: 0x13D96C0 Offset: 0x13D96C0 VA: 0x13D96C0 public void set_LastReachedLevel(int value) { }
// RVA: 0x13D974C Offset: 0x13D974C VA: 0x13D974C public void SetHintOpen(int level, int hintIndex) { }
// RVA: 0x13D998C Offset: 0x13D998C VA: 0x13D998C public bool GetHintOpen(int level, int hintIndex) { }
// RVA: 0x13D9A88 Offset: 0x13D9A88 VA: 0x13D9A88 public void .ctor() { }
先來看Coins(),有兩個結果,public int get_Coins()和public void set_Coins(int value),get_Coins根據地址跳轉到0x13D954C,我查看了一下引用,結果為0,沒有函數引用這個地方,如果修改這里的話十有八九是沒什么用的。

接著繼續看set_Coins,跳轉到地址0x13D14DC。英文意思是設置、顯示數值。破解過java的應該知道,方法名中有set_xx,get_xx,應該是改get,而不是set,set這個函數基本上有傳入參數,所以不能直接修改這里,這里只是用來顯示數值的。但是剛才的get找不到引用,所以只能另尋方法。

通過查看set_Coins的交叉引用,可以確定是哪里調用了顯示,如上圖紅框,分別是幾種扣費地址。隨便選一個,匯編如下:
il2cpp:01324714 ; --------------------------------------------------------------------------- il2cpp:01324714 MOV R0, #8 //函數地址 il2cpp:01324718 LDR R7, [R0] //r0地址讀取放入r7,此時r7是剩余的電燈泡 il2cpp:0132471C BL HintPanel$$get_cost //獲取商品價格,需要花費多少電燈泡 il2cpp:01324720 MOV R6, R0 //把價格存入r6 il2cpp:01324724 BL sub_2B6FD4 il2cpp:01324728 ; --------------------------------------------------------------------------- il2cpp:01324728 il2cpp:01324728 loc_1324728 ; CODE XREF: sub_1324350+C4↑j il2cpp:01324728 SUB R1, R7, R6 //r1=r7-r6,此時r1是剩余的電燈泡 il2cpp:0132472C MOV R0, R5 //r5傳入r0,然后進入BL il2cpp:01324730 MOV R2, #0 //初始化 il2cpp:01324734 BL PlayerData$$set_Coins //進行顯示 il2cpp:01324738 MOV R0, #0 il2cpp:0132473C BL DataManager$$get_playerData il2cpp:01324740 MOV R5, R0 il2cpp:01324744 CMP R0, #0 il2cpp:01324748 BNE loc_1324750 il2cpp:0132474C BL sub_2B6FD4
v13 = DataManager__get_playerData(0); v14 = v13; if ( !v13 ) sub_2B6FD4(); v15 = *(v13 + 8); cost = HintPanel__get_cost(); PlayerData__set_Coins(v14, v15 - cost, 0); v17 = DataManager__get_playerData(0); if ( !v17 ) sub_2B6FD4();
偽代碼比較容易理解,有個減號,很容易看出這是扣費的地方。

所以把5個函數的調用,全部由減法改成加法指令(add)即可越用越多,其它的貨幣也是一樣的思路,就不一一舉例了。
本站不存儲任何資源文件,敬請周知!
本網站采用 BY-NC-SA 協議進行授權 轉載請注明原文鏈接:小游戲 Brain Test 3 大腦測試3 跳過付費內容 無限內購

侵權舉報/版權申訴



