android unity hook,[原创]Unity3d安卓游戏DLL动态调式与HOOK基础
[原創]Unity3d安卓游戲DLL動態調式與HOOK基礎
2016-4-4 02:40
8207
[原創]Unity3d安卓游戲DLL動態調式與HOOK基礎
2016-4-4 02:40
8207
本文作者七少月,文章中很多觀點和技術手段為本人原創,轉載請注明出處,由于本人技術水平有限,不當之處,還請斧正。
前言:
由于本人一直以來都比較忙,開班、工作等等事情太多,所以很長一段時間沒有發帖。其實我確實想看一看,尤其是Unity3d安卓游戲逆向領域有沒有更出彩的文章。可能有些不恰當的說,確實這一段時間以來,雖然也有一些Unity3d安卓游戲逆向的優秀文章,如對金庸群俠傳X1.0的數據庫解密和功能解鎖修改,但無論從數量上,還是從難度上,我都難以滿意。不知道是愿意共享的人少了,還是覺得U3D逆向技術太簡單了,如果是后一種原因,我只想說,U3D在安全開發的投入和技術發展是難以想象的飛速,如U3D把關鍵函數引向lua,利用Lualib實現C#與LUA交互,不僅實現熱更新,也保護了代碼,而lua腳本文件則作為資源文件打包混淆。以上是后話,現在最大的問題在于,即使DLL解密脫殼后,我們依然在靜態分析DLL。
難以逾越的鴻溝:
本篇技術文章需要一定的U3D安卓逆向基礎,沒有的推薦看法總的教程,至少你能用reflector把DLL中一個return hp語句修改為return 99999.在之前我們說過,由于U3D底層并不開源,而且DLL運行在安卓上已經是受到了很大限制,所以在給我們逆向帶來比普通安卓的dex和so目標更為明確的同時,也讓我們逆向手段帶來很大拘束。導致的一個結果就是,我們逆向U3D的DLL,只能使用靜態分析,通過搜索,然后修改,最后測試。一直以來,我們認為,只要把關鍵DLL拿到,即使是網游,也可以進行修改。但以后就不是這個樣子,可能以后DLL確實是所謂的關鍵DLL,但就不做保護地擺在那里,都沒有什么作用。如果你一直看我U3D逆向的相關文章,這是繼U3D把DLL加密加殼階段的下一個新的階段,我稱為關鍵DLL無效的階段。回到本文,我們好像確實很為難,只能使用靜態分析仿佛成了我們一道無法逾越的鴻溝。
Unity3d游戲DLL動態調式與HOOK:
能實現對U3D游戲進行動態調試,是我和法總一直以來的愿望。早先,我寫過一篇理論指導性的文章《Unity3d游戲動態調試理論框架》。當然,就在那不久之后,里面的思想相繼得到了實現。最具代表性的,就是利用IDA動態調試libmono.so,DUMP下來解密后的DLL。但很可惜,那種動態調試,實質是在動態調試so,離我們當初想實現的真正的DLL動態調試相距甚遠,更別提對DLL進行更深層的HOOK。當然,如若想實現DLL能像dex或SO那樣進行單步調式,可能還是比較遙遠,首先就是沒有工具,IDA對安卓DLL的效果很不理想,我們的神器reflector還不提供遠程調式安卓DLL的功能,但確實可以存在一些替代性的策略。下面,我們要知道以下幾點:
1. 任何一種動態調試,并非一定要實現單步調式才叫動態調式,能實現單步調式是我們最理想的狀態,但動態調試都是從log開始的;
2. 把程序在運行時斷下來,是動態調試的精髓所在,但也有一些簡單的替換性策略,比如我在C#編寫的EXE中的代碼中,插入一句message.show(“運行到此處”)代碼,讓程序在運行到我感興趣的那段代碼時彈出對話框。但這個在U3D中實現是很困難的,遠沒有安卓smali中通過靜態注入Alert對話框代碼那樣簡單,因為U3D的腳本代碼和組件聯系太過緊密,U3D本身更貼近于一個類似于3DMAX的三維設計軟件。
3. HOOK本質的意義是注入代碼,也是替換程序原本函數,所以DLL的HOOK可以分為內部HOOK和外部HOOK。由于reflector的插件reflexil本身就可以對DLL進行注入類、方法、變量、屬性等,通過這種方式的HOOK就是內部HOOK。而外部HOOK,就是在其他DLL,甚至是其他的非C#編寫的任何文件去HOOK這個DLL。
說了這么多,理論基礎終于講完了,本篇是基礎,只講解簡單的LOG和內部HOOK注入。
準備及樣本:
為了方便,我們采用比較簡單的berryrush游戲作為樣本,該樣本在法總教程中存在。
首先,我們需要游戲的關鍵Assembliy-csharp.dll,當然這個DLL要是解密后的,而且要是真正的關鍵DLL,當然它要對游戲有決定性作用,而不是里面只有不關鍵的支持性代碼,關鍵性代碼存在于別的地方。其次,我們要把UnityEngine.dll拿出來,一般這個類被處理的很少。然后把它們一起拉到Reflector工具中。下面,我們來認識一下,UnityEngine.dll的UnityEngine命名空間中的Debug調式類。該類有Break、Logstr等方法。如圖:
已經淘汰的U3D開發技術:
由于這些技術過于簡單,非常容易被逆向,在現今的U3D中,已經被淘汰
1. 把關鍵變量寫成屬性,且可以被外部調用,表現為其關鍵變量是個屬性,存在get_XX和set_XX方法。現今,都是對變量進行不可被調用的聲明,也就是為變量,表現為在Reflector中用藍色長方體作為圖標,且往往其聲明為protected或private,而不是public
2. 不再存在如GetCoins(),這樣明顯的關鍵性函數,即使有,要不代碼非常復雜,邏輯特別難懂,要不就是修改了也沒用的;
3. 不再存在關鍵性變量在使用時直接進行賦值語句,如this.coinscount = 0,與上種情況相同
以上說明只是讓大家知道,本例中這些情況是存在的。
Debug類的初步使用下斷:
我們選擇GetCoins()這個函數,我們加一句代碼Debug.Break()。那么在IL語言中怎么添加中,首先,我們要注意,在添加指令的時候,指令是call,類型是Method,操作數是Debug.Break()這個函數。
我們的代碼就是:
Offset
OpCode
Operand
0
ldarg.0
1
ldfld
System.Int32 StrawberryPlayer::coinsCount
6
call
System.Void UnityEngine.Debug::Break()
11
ret
然后,我們回編,利用手機版的log工具(會在附件中里有),對其進行log,我們發現游戲并沒有停止運行,但是在這句代碼被執行時,會給予該代碼執行的時間及一些狀態,如果下多個這樣的斷點,是完全可以了解一定的程序運行邏輯的。
DLL的內部注入HOOK:
首先,我們要知道,HOOKDLL究竟有多大的好處。HOOK就是注入,替換。我們舉個例子,上面已經說過,現在關鍵性的變量都沒有get,set,也不在函數中進行賦值,總之一切都在U3D內部邏輯完全,緊密貼合于組件。這就好比是客戶端和服務端,如果一直這么雙方聯系著,會對我們分析和修改帶來很大不便。我們注入就好比是中間人,假設我們注入是一個變量,那么這個變量可以去替換一個程序原先使用的變量在函數里出現的位置,我們根本不需要知道原本這個變量如何計算得到,我們只需要定義一下這個中間變量,然后賦值給原先的變量,然后觀察程序運行的反應和效果。這樣一來,我們就找到了一個突破點,順著這個點,再繼續分析下去。本例中,我選取StrawberryPlayer類中的StartRunning()函數,變量則選取該類里的coinsCount,在游戲中表示金幣數,在StartRunning()函數中被賦值為0。
在進行DLL HOOK之前,我們一定要知道,我們通過靜態分析,得到的關鍵類、關鍵方法、關鍵變量是什么,任何動態調試,如果沒有靜態分析時的確定目標,那就是無頭蒼蠅。本例的關鍵在剛剛已經寫得非常清楚。
接下來,我們在關鍵類StrawberryPlayer類右鍵,選擇Reflexil2.0(我的該插件版本是2.0),然后選擇inject field,即注入變量,這里要注意,注入的變量數據類型要和原本想替換的變量數據類型一致,本例的coinsCount是一個Int32型,變量命名為coinlog。
注入后,DLL加載會刷新一次,然后你就發現在該類下有了coinlog變量。
下面,我們到StartRunning()函數中,在代碼的尾部添加以下幾句代碼,也就是先賦值coinlog變量為99999,再讓coinsCount=coinlog,最后Debug.Logstr(“金幣已做修改”)。對于賦值語句添加是基礎內容,可去學習法總教程,對于Debug類使用上述已經說過,這里只給結果:
274
ldarg.0
275
ldc.i4
99999
280
stfld
System.Int32 StrawberryPlayer::coinlog
285
ldarg.0
286
ldarg.0
287
ldfld
System.Int32 StrawberryPlayer::coinlog
292
stfld
System.Int32 StrawberryPlayer::coinsCount
297
ldstr
金幣已做修改
302
call
System.Void UnityEngine.Debug::Log(System.Object)
307
ret
簡單說一下:274-280偏移指令是this.coinlog=99999;285-292偏移指令是coinsCount=coinlog;297-302偏移指令是Debug.Logstr(“金幣已做修改”)。注意一下,這里的274等數字是指令所在的相對偏移地址,也就是offset,如果簡單用第幾句指令的話,應該是第86句-95句。
我們回編測試,自然游戲初始化的金幣就是99999了,用log手機版查看,也非常清晰,可以看到這個函數是何時被調用的。
下載地址:http://pan.baidu.com/s/1gfdfsbT
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的android unity hook,[原创]Unity3d安卓游戏DLL动态调式与HOOK基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android+无触摸操作,如何在And
- 下一篇: android 相机路径,android