錦州市廣廈電腦維修|上門維修電腦|上門做系統|0416-3905144熱誠服務,錦州廣廈維修電腦,公司IT外包服務
topFlag1 設為首頁
topFlag3 收藏本站
 
maojin003 首 頁 公司介紹 服務項目 服務報價 維修流程 IT外包服務 服務器維護 技術文章 常見故障
錦州市廣廈電腦維修|上門維修電腦|上門做系統|0416-3905144熱誠服務技術文章
unity游戲生成與修改so文件教程

作者: 迷之裙擺  日期:2017-06-24 15:52:03   來源: 本站整理

 

本文主要介紹如何對unity3d引擎制作的游戲進行修改。包含了apk文件安裝后在手機中的位置分析、修改游戲時遇見內聯函數之坑時的解決辦法,以及so文件的原理介紹與解析修改。

并將實例教學如何修改unity3d游戲(想學崩壞3修改的同學請注意啦)。

教程是給入門新手看的,請大神繞道勿噴。文章的核心內容在最后利用Il2CppDumper的部分,前面清楚的話可直接繞到最后看。(因為手機截圖下來的圖片分辨率太大。看起來排版會不太舒服,

可以直接到文章最后下載文檔查看,排版會舒服很多)
基礎知識
0x1.apk安裝后在手機中的目錄
apk安裝后會在兩個包下生成相關包:data/data/、data/app/。
這里拿網易云音樂的安裝目錄舉例。Data/App目錄下通常會有三個文件:
1.lib文件夾(包含so庫文件)、
2.oat文件夾(OAT文件是一種android私有ELF文件格式,它不僅包含有從DEX文件翻譯而來的本     地機器指令,還包含有原來的DEX文件內容。

這使得我們無需重新編譯原有的APK就可以讓它正常地在ART 里面運行)、
3.base.apk啟動包。【其中apk啟動包是不允許重命名或刪除的,因為app運行時其實就是鏈接到這個啟動包,然后才能繼續啟動操作。這個啟動包用beyond對比后可以發現,與原安裝包沒有任何不同,

所以就相當與apk的原版安裝包】。
     
                                  


Data/data目錄下一般是存儲lib文件夾(保護so庫文件)以及其他數據文件、緩存等。只需要知道這里的lib實際上與data/app目錄下的lib目錄中內容是一樣的。  
游戲在運行的時候,一般都會載入dada/data目錄中的lib與data/app中的lib,通常來說只需要修改data/data中的lib文件夾中的so文件即可達到成功修改的效果。當然也有一小部分游戲根本不讀取data/data目錄

下的lib文件夾,待會會講到。
       
 
0x2.Unity3D中的資源路徑


Application.dataPath

此屬性用于返回程序的數據文件所在文件夾的路徑。例如在Editor中就是Assets了。

Application.streamingAssetsPath

此屬性用于返回流數據的緩存目錄,返回路徑為相對路徑,適合設置一些外部數據文件的路徑。

Application.persistentDataPath

此屬性用于返回一個持久化數據存儲目錄的路徑,可以在此路徑下存儲一些持久化的數據文件。

Application.temporaryCachePath

此屬性用于返回一個臨時數據的緩存目錄。
android平臺

Application.dataPath

/data/app/xxx.xxx.xxx.apk

Application.streamingAssetsPath

jar:file:///data/app/xxx.xxx.xxx.apk/!/assets

Application.persistentDataPath

/data/data/xxx.xxx.xxx/files

Application.temporaryCachePath

/data/data/xxx.xxx.xxx/cache
IOS平臺

Application.dataPath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data

Application.streamingAssetsPath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/xxx.app/Data/Raw

Application.persistentDataPath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Documents

Application.temporaryCachePath

Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Caches


0x3.C#的inline內聯函數優化
雖然C#不支持inline,但是JIT支持自動inline,即將IL轉成真正機器碼時,會自動將某些函數進行inline展開,只是條件非常苛刻,網上提到JIT自動進行inline展開的一些選擇依據:
1)函數內部有循環語句、catch語句等復雜結構,都不做inline優化。
2)函數體比較長的不做inline優化,只有比較簡單的才可能inline優化。(有人說IL不足32字節才做inline),
2)編譯成機器碼時,inline展開的代碼比函數調用更短的,一定做inline。(注:如果參數多而代碼少,就符合此情況)
這里為什么要講內聯函數呢,加入如果游戲中有一個讀取人物攻擊力的函數,其內部代碼十分簡單,結果被編譯為機器碼的時候變為了內聯函數。那么這個時候要來修改就十分麻煩了,

因為你找到那個讀取人物攻擊力的函數是沒有用的,修改了也是白修改,只能到每一處調用這個函數的地方逐行修改。
好了,說了這么多,下面從開始unity3d游戲開發的的角度逐漸逆向分析。

一、通過unity3d打包生成libil2cpp.so:
1.如何識別u3d游戲?打開解壓包,如果lib文件夾下有libunity.so就證明這是一個unity3d游戲。
2.要修改Unity3d游戲,首先就要對其游戲代碼存放位置有一個基本的了解。Unity3d生成游戲的游戲主邏輯一般放在三個地方:libil2cpp.so、Assembly-CSharp.dll、lua腳本。
【對于libil2cpp.so來說:我們知道,unity3d最大的一個特點是一次制作,多平臺部署,而這一核心功能是靠Mono實現的。但是在2014年年中的時候,Unity3D引出了IL2CPP的概念,IL2CPP,

英文意思即Intermediate Language to cpp,就是把IL中間語言轉換成CPP文件。】
上面所說的這三個地方通常來說是唯一的,即只會出現一種情況。這是由unity3d引擎的生成方式決定的。下面通過開發者的角度對unity3d生成游戲進行實例講解:

新建unity3d工程,工程命名為HelloCPP!:
 
 
利用ugui創建兩個text,一個為“CoinUI”顯示“金幣”,一個為“Coin”顯示金幣值,并創建腳本GameManager,綁定在MainCamera中。

腳本GameManager代碼如下:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine.UI;
  4. using UnityEngine;


  5. public class GameManager : MonoBehaviour {


  6.     private GameObject coin;
  7. void Start () {
  8.         coin = GameObject.Find("Coin");

  9. }
  10.     private int GetCoin()
  11.     {
  12.         return 50;
  13.             
  14.     }
  15.     public void ChangeCoin()
  16.     {
  17.         float v = GetCoin();
  18.         coin.GetComponent<Text>().text = v.ToString();
  19.     }
  20. }
  21. 方法與按鈕事件綁定。那么當點擊按鈕的時候就會更新一次</font>ui。</font></font></font>
復制代碼


代碼中的GetCoin方法放回一個50的數值,當游戲運行起來的時候,腳本會將ui界面中Coin的值改為50,如下:
 

好了,游戲邏輯已經寫完了,保存場景,直接打包,點擊主菜單file>BuildSetting進入打包界面,選擇轉化為android平臺,并點擊playersetting進入配置界面:
這里我把PackageName設置為com.hellocpp。
然后頁面下拉,找到scriptingbackend:
 
 


這里的scriptingBackend就是設置生成游戲的游戲邏輯存放方式,如果選擇默認的Mono2x的話,會在反編譯后的apk的assets\bin\Data\Managed目錄下找到Assembly-CSharp.dll文件,

也就是大多數unity游戲邏輯存放的位置,這種情況下,lib文件夾下是沒有libil2cpp.so文件的。

如果是選擇IL2CPP的話,會在lib文件夾下生成libil2cpp.so文件,并在assets\bin\Data\Managed\Metadata目錄下生成global-metadata.dat配置文件。
 

對于生成Assembly-CSharp.dll文件的情況來說,用reflector很容易修改,這里略過,直接講解生成libil2cpp.so文件的情況。把生成的apk直接拖入ide中反編譯,進入根目錄后,進入lib文件夾中觀察。

二、對生成的apk進行反編譯分析

直接把apk拖入ide,然后進入lib文件夾查看
 

 
 
生成了兩個文件夾,一個是armeabi-v7a,即arm架構,一個為x86,是因特爾架構。我們這里進入arm文件夾中分析。
【有時會有人問,為什么so修改后模擬器運行閃退,無法正常運行?這種情況多半是因為你只修改了arm文件夾下的so,所以只能在大部分真機中運行,因為真機多半是arm架構的,

而模擬器是因特爾架構的,所以在模擬器上運行會奔潰。】
 
可以看到,里面一共三個文件,其中libunity與libmain是unity的內部文件,我們不需要去管它,現在只需要知道這里確實生成了libil2cpp.so即可。

好了,現在我們要分析修改這個apk,手機中運行起來我們發現其顯示金幣為50,我們現在來修改其數值。



按照國際慣例,先在ide中搜索字符串“金幣”,發現沒有結果,于是判斷游戲邏輯在so中,我們再搜索loadlibrary,然后發現了里面唯一用到的原生方法是在libmain中,然后估計就有人去分析libmain.so文件了,

但libmain.so里面其實是沒有游戲核心邏輯的,

這只是unity內部的一些庫,真正的游戲核心邏輯是在libil2cpp.so中,這個庫文件實在載入libmain后才被調用的。
所以,碰到unity游戲,一定要先看看lib文件夾下是否有libil2cpp.so,如果有的話,直接分析這個so就行了,從smali分析存粹是浪費體力。
打開
IDA,載入so,搜索coin,會發現依然找不到相關函數,推測在jni中動態加載,然而搜索jni也是找不到任何函數。在view-A面板中尋找,發現大多數函數只有一個函數尾,而函數頭似乎被可以“掐”掉了。
 


三、對Il2CppDumper.exe工具的介紹
出現上述情況的原因與unity引擎中的MetadataCache.cpp相關,打開u3d目錄,可找到MetadataCache.cpp:
 

意思就是在生成libil2cpp.so時,u3d同時會在目錄assets\bin\Data\Managed\Metadata下生產資源文件global-metadata.dat。游戲中使用的字符串都被保存在了一個叫global-metadata.dat的資源文件里,

只有在動態運行時才會將這些字符串讀入內存。這使得用IDA對游戲進行靜態分析變得更加困難。那么為了解決這個困難,有人造了輪子,即Il2CppDumper.exe。此可讀取global-metadata.dat文件中的信息,并與libil2cpp.so結合起來。
 

相關源碼可看國外大神的分析:還原使用IL2CPP編譯的unity游戲的symbol(一)
【https://www.nevermoe.com/?p=572】以及(github:https://github.com/nevermoe/unity_metadata_loader)與github:https://github.com/Perfare/Il2CppDumper)

好了,如果你覺得這個看起來過于麻煩的話,可以直接略過,只要學會使用其工具化下來的exe就行了。

這里為了方便下載直接使用,我已經把exe文件生成出來了,會直接打包到百度云。
這個exe文件主要是通過對global-metadata.dat與so文件的結合自動生成相關函數與其對應在ida中的偏移地址。(相關原理其實就是分析global-metadata.dat,這里是自動幫我們省去了這個步驟)。

使用方法:
打開Il2CppDumper.exe,會彈出一個窗口,第一個選擇lib2cpp.so,第二個選擇global-metadata.dat,然后按下鍵盤鍵2,就會自動完成后續的操作了。
 


 

生成的文件就是這個dump.cs,我們點進去后直接搜索coin,定位到這里:
 

下面的數字就是偏移量,復制511f50后進入ida,按g鍵進入到相關地址
發現代碼沒有展開的話,按一下c鍵就可以了。
 
可以看到,他這里是返回了50。那么,這個時候我們就興奮了,這里就是我們要修改的地方!講道理把這里的0x32修改為0xFF00后,我們在游戲中點擊按鈕,顯現的值就應該變為65280了:
 
用hex二進制修改器修改后,命名為libil2cpp改.so。
接下來可以直接把so替換掉原so然后打包回編譯,但這種辦法遇到apk有簽名驗證或其他亂七八糟的檢驗時不好操作。這里我們使用另一種部分,即先安裝apk到手機,

然后進去根目錄下去手動把so給替換掉(手機需root)。

把apk與修改后的so一起扔進手機:

 


 
安裝apk后,先打開來看看,點擊按鈕后,金幣為50
 

好了,接下來就是替換so了。在前面的基礎知識中我們講到,apk安裝后,會在data/data與data/app下分別生成自己的包文件。并且兩個文件夾下都有lib,里面封裝了一樣的so庫文件。

那么我們是去替換哪一個呢?答案:兩個都試試。
因為有些app只讀取data/app/com.hellocpp目錄下的lib文件夾信息,不讀取data下的文件夾信息,比如這個apk。你會發現你直接把data/data下的com.hellocpp包給刪掉也是完全可以運行的,但是如果你刪了app目錄下的com.hellocpp/lib,立刻無法運行。
我們把原so重命名為libil2cpp.so原,然后把改后的so命名為libil2cpp.so
 
大功告成,我們重新打開游戲,然后會發現。
沒有任何變化(心涼)
 

正常情況這樣修改后就應該會成功了的,但是這里為什么依然沒有任何變化呢。
這里又涉及到前面說的基礎知識,當這種情況發生的時候,很可能就是函數內聯了。
你修改函數本體是沒有任何效果的,因為這個函數被調用它的函數內置了。你必須找到所有調用這個函數的地方,去找到相關點修改。這個就需要去看匯編代碼了。
我們也可以動態調試的時候在getcoin()方法處下一個斷點,然后ida動態調試,會發現按鈕按下時確實沒有斷下來(限于篇幅請讀者自行嘗試)。或者我們直接把那個函數本體給nop掉,會發現程序依舊正常運行,這都說明了函數確實內聯了。

內聯了的函數很難分析,我遇到了就只能跑路,這里只是點出其位置,再深入的分析就要去好好讀代碼了,不多分析(如果有大神會的話麻煩評論區指點指點)

這里我直接找到這個地方,改為mov r0,0
 
再次替換后運行結果確實變為0了:
 
 

實例二
好了,分析完上面這個核心處存在內聯函數的apk,我們下面來一個最常見的apk修改實例。
仍然是上面這個apk的功能,但不同的是為了防止其編譯的時候又被當成內聯函數編譯了,我在方法GetCoin()內增加了一個循環和幾個debug,確保其不被當作內聯。其他功能不變。依舊是在GetCoin()中返回50,然后在ChangeCoin()修改ui界面的數值。
代碼如下:

 
然后同樣步驟打包生成apk,但把包名改為了com.HellobanInline
生成apk后直接扔進ide中反編譯,然后把global-metadata.dat與libil2cpp.so拿出來,用Il2CppDumper.exe把函數名生成出來:
 
打開dump.cs,搜索GetCoin()
 

函數位置在偏移511d48上。
 
因為方法是返回一個int值的數值,我們直接讓其返回0xff00,也就是65280.
 

用hex二進制文件修改后把文件命名【libil2cpp改.so】。與apk一起扔到手機中。
Apk安裝完成后,進入data/app中的包com.HellobanInline-1的lib/arm中,把【libil2cpp改.so】復制進來,重命名如下:
【這里對為什么包名后面有一個-1做一下解釋:這是因為復制版本覆蓋。一般來說第一次安裝的話包名后綴-1,第二次覆蓋安裝就會多一個相同包名后綴為-2,再次覆蓋安裝又會變為-1……】
                    

好了,大功告成,這個時候充滿期待的打開apk吧。點擊按鈕后數值已經由50變為了65280!
效果圖:
 

市面上絕大部分游戲都是直接生成c#方法名后到ida中直接修改就生效了,像實例一的比較少見,但有助與深入理解。
一般生成方法名后,就看修改經驗或游戲開發經驗了,比較火的u3d游戲有很多,比如崩壞3的修改,你可以搜索方法名“GetBaseAttack”,修改為一個超大值,那么你人物就一擊十幾億,防御十幾億,

生命十幾億了。對于崩二的話,其加了愛加密的殼,

并且似乎有檢驗so是否被篡改,若有高人能跳過檢測希望能告訴我一下,十分感謝!然后再其他的游戲修改也都是這套路,多多熟悉就會了。

大概就這些內容吧,自己羅里吧嗦的,感覺篇幅有點累贅了。
[size=10.5000pt] 




百度云鏈接:http://pan.baidu.com/s/1i5Hur2H 密碼:viqv    解壓密碼www.wuaipojie.com
world文檔:  http://pan.baidu.com/s/1i5EC5pj 密碼:ja84

圖片1.png (78.43 KB, 下載次數: 1)

圖片1.png


熱門文章
  • 機械革命S1 PRO-02 開機不顯示 黑...
  • 聯想ThinkPad NM-C641上電掉電點不...
  • 三星一體激光打印機SCX-4521F維修...
  • 通過串口命令查看EMMC擦寫次數和判...
  • IIS 8 開啟 GZIP壓縮來減少網絡請求...
  • 索尼kd-49x7500e背光一半暗且閃爍 ...
  • 樓宇對講門禁讀卡異常維修,讀卡芯...
  • 新款海信電視機始終停留在開機界面...
  • 常見打印機清零步驟
  • 安裝驅動時提示不包含數字簽名的解...
  • 共享打印機需要密碼的解決方法
  • 圖解Windows 7系統快速共享打印機的...
  • 錦州廣廈電腦上門維修

    報修電話:13840665804  QQ:174984393 (聯系人:毛先生)   
    E-Mail:174984393@qq.com
    維修中心地址:錦州廣廈電腦城
    ICP備案/許可證號:遼ICP備2023002984號-1
    上門服務區域: 遼寧錦州市區
    主要業務: 修電腦,電腦修理,電腦維護,上門維修電腦,黑屏藍屏死機故障排除,無線上網設置,IT服務外包,局域網組建,ADSL共享上網,路由器設置,數據恢復,密碼破解,光盤刻錄制作等服務

    技術支持:微軟等
    主站蜘蛛池模板: 亚洲国产精品成人AV无码久久综合影院| 欧美性生交xxxxx无码影院∵| 亚洲中文字幕无码一区二区三区| 亚洲人成影院在线无码按摩店| 久久国产加勒比精品无码| 日日摸日日碰夜夜爽无码| 久久久久久久久无码精品亚洲日韩| H无码精品3D动漫在线观看| 亚洲AV无码专区在线观看成人 | 无码国内精品久久人妻蜜桃| 亚洲AV无码一区二区三区牲色| 中文字幕无码第1页| 国产精品亚洲专区无码唯爱网| 亚洲A∨无码无在线观看| 亚洲精品一级无码中文字幕| 精品久久久久久久无码| 中文字幕丰满乱孑伦无码专区| 成人无码Av片在线观看| 蜜桃臀无码内射一区二区三区| 亚洲中久无码永久在线观看同| 无码喷水一区二区浪潮AV| 69久久精品无码一区二区 | 人妻系列AV无码专区| 国产品无码一区二区三区在线| 国产成人无码AV麻豆| 无码精品人妻一区二区三区人妻斩 | 人妻无码第一区二区三区| 国产羞羞的视频在线观看 国产一级无码视频在线 | 无码中文字幕av免费放| 制服在线无码专区| 亚洲欧洲日产国码无码网站| 亚洲永久无码3D动漫一区| 亚洲精品~无码抽插| 日韩精品无码免费专区午夜| 惠民福利中文字幕人妻无码乱精品| 无码乱码av天堂一区二区| 亚洲熟妇av午夜无码不卡| 欧洲精品无码成人久久久| 国产人成无码视频在线观看| 少妇无码?V无码专区在线观看| 国产午夜无码片在线观看影院 |