網上已經有很多文章講解過unity3d指令碼dll 解密,基本方法原理都差不多,就是通過hook或者除錯下斷mono_image_open_from_data_with_name這個函式拿到解密後的dll。這些方法都需要比較專業的知識(hook或者過反除錯),另外對於使用了強度比較高的第三方保護,也無能為力。下面我們來**一下更為通用簡便的u3d指令碼dll解密方法。
一、指令碼解密原理
先來理一下通過mono_image_open_from_data_with_name解密指令碼dll的原理。
unity3d遊戲的指令碼預設情況下是非加密形態,儲存於如下圖的壓縮包目錄下,一般情況名字為assembly-csharp.dll或assembly-csharp-firstpass.dll。
這樣的指令碼dll是由c#語言編寫的,可以被類似reflector之類的工具反編譯成原始碼。破解者得到原始碼就可以對其進行修改,實現內購破解、修改遊戲人物屬性(修改金幣、hp等)、修改戰鬥技能(無敵、強制勝利等)。
我們來看下mono_image_open_from_data_with_name這個函式的原始碼
幾個主要函式的引數意義:
data: 指令碼內容
data_len:指令碼長度
name:指令碼名稱
這個函式執行了如下幾步操作:
1.把data指向的指令碼拷貝到新申請的記憶體
2.填充乙個monoimage結構體
3.使用do_mono_image_load初步載入該指令碼
4.註冊並返回monoimage結構體指標
這個原始mono_image_open_from_data_with_name函式,如果輸入的data指向的是個加密過的指令碼dll,在這個函式執行之前,先要對該data指向的記憶體進行解密。
除錯解密可在return處下斷,此時data指向的記憶體已經解密,把該處記憶體拷貝出來即是解密後的dll
hook解密原理是待mono_image_open_from_data_with_name原始函式返回後拷貝data指向的記憶體
不過往往第三方保護都是帶反除錯的,新手要過掉反除錯還是比較費周折的,有些厲害的反除錯,老手都不一定過得了。對so做hook也是要有一定的技術基礎才能做到。
對於強度稍微高點的保護,這個函式處是拿不到解密後的dll的,等這個函式返回的時候,記憶體可能是空的。
絕大部分加密,都緊盯著data指向的記憶體來做文章,認為只要把mono_image_open_from_data_with_name引數裡的data加密搞定就萬事大吉了,而忽略掉了另一塊永久存在的處於解密狀態的dll記憶體。
mono_image_open_from_data_with_name第一步就是把data記憶體使用memcpy拷貝到一塊新申請的記憶體裡,這塊記憶體將永久存在,因為c#語言是需要動態解析類、函式等資訊的,時不時要用到這塊記憶體。而data待這個函式呼叫完後,將會被釋放掉。
這也是某些強度比較高的第三方保護,通過那兩種方法都得不到解密dll的關鍵所在,它在mono_image_open_from_data_with_name函式返回前就把data指向的記憶體給清空了。
二、指令碼解密方法
下面就來講一下我們的u3d指令碼dll解密方法,原理即是利用了記憶體中存在的那個memcpy拷貝的dll。
由於記憶體中永久存在這個dll,我們只要全記憶體搜尋這個dll就可以了。如何全記憶體搜尋呢,自己寫個工具還是挺麻煩的一件事。
其實用手遊分析者比較熟悉的乙個現成工具就可以做到:燒餅修改器(八門神器等其它修改器也可以),燒餅修改器可以對遊戲進行數值搜尋。那我們要搜尋什麼數值呢?
先用二進位制工具hiew來看下assembly-csharp.dll
這是個pe結構的檔案,以4d 5a 90 00這四個位元組為magic head,這可以做為c# dll指令碼的特徵,我們只要搜尋0x905a4d這個數值就可以了,由於燒餅修改器是使用10進製數值,將其轉換成10進製值:9460301
下圖是使用燒餅修改器搜尋乙個3d卡車小遊戲的示例:
顯示出來的是搜尋結果,一共搜尋到了12個結果
第乙個搜尋結果,即是以52c4c008起始位址的指令碼dll,我們可以使用memdump工具把這塊記憶體dump下來,由於不知道大小,先dump 0×3000大小來看一下。
儲存為abc.dll,再用hiew 看下abc.dll
可以看到dump下來的確實是個csharp 指令碼dll,dll實際大小可通過下圖這個ffi 工具,解析出來,將第 3行的0x10a00 加上 0×200 即是實際大小。可通過這個方法來確定這12 個 dll ,哪個是你需要解密的 dll 。
這個方法的優點是可以不用去管反除錯,也不用去學習怎麼hook,用現成的工具組合起來就可以做到解密指令碼。最重要一點是對保護強度比較高的保護也可以無視。
Unity3d時鐘指令碼
var tu1 texture2d var time1 float 0 function fixedupdate function ongui function gettime time float string var lasttime string var hour mathf.floortoi...
Unity3D 指令碼入門
1 資料型別和基本運算 a 命名空間就像在檔案系統中乙個資料夾容納多個檔案一樣,可以看作某些類的乙個容器。通過把類放入命名空間可以把相關的類組織起來,並且可以避免命名衝突。命名空間既用作程式de 內部 組織系統,也用作 外部 組織系統。使用命名空間 using 2 整型 整數 8個名稱 sbyte ...
unity3d 指令碼入門
1 virtual和override a virtual 用在基類中,指定乙個虛方法 屬性 表示這個方法 屬性 可以重寫。b override 用在派生類中,表示對基類虛方法 屬性 的重寫。class test2 test public sealed override void show 執行的結果...