燒餅遊戲修改器是一款元老級的遊戲修改器,提供了精確搜索、模糊搜索、聯合搜索、數據過濾、存儲搜索與讀取搜索等功能。主要實現搜索手機進程的內存數據並作相應修改。php
本文中分析的版本爲2.0.2(34),SDK:8,TargetSDK:17,代碼通過混淆,修改器基本使用方法爲輸入須要修改的數據進行查詢,查詢結果少則可直接修改,查詢結果多則須要返回遊戲,使想修改的數據發生變化後再次搜索,最後根據數據變化偏移找到須要修改的地址。輸入想要修改爲的數據便可修改。html
本程序測試機爲LG Nexus 5,版本爲Android 4.4,運行程序前需先root手機。java
系統環境:Java 1.8.0_92 ,Android Debug Bridge version 1.0.36linux
使用工具:AndroidKiller、JEB、Eclipse、IDAandroid
爲了便於分析,本文中涉及向工程中注入smali代碼並從新打包運行,對經常使用的注入代碼作以下說明。其中使用到的寄存器vn要根據實際代碼使用的寄存器個數來作相應修改。如圖2-1中的run()中「.locals 5」申明使用了5個寄存器,即v0~v4,若是咱們須要插入一條日誌信息,爲了避免影響原來代碼的執行,須要本身增長一個寄存器v5,先將「.locals 5」變成「.locals 6」,再用v5來保存日誌信息。shell
圖2-1 Smali代碼中對寄存器的說明編程
const-string vn, "提示語"windows
invoke-static {vn}, Lcom/android/killer/Log;->LogStr(Ljava/lang/String;)V安全
圖2-2 Log信息輸出框架
const-string vn, "string數據"
invoke-static {vn, v1}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
圖2-3 打印字符數據
const-string vn, "int數據"
invoke-static {v1}, Ljava/lang/Integer;->toString(I)Ljava/lang/String;
move-result-object v(n+1)
invoke-static {vn, v(n+1)},Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
圖2-4 打印整型數據
const-string vx, "boolean數據"
invoke-static {p1}, Ljava/lang/Boolean;->toString(Z)Ljava/lang/String;
move-result-object v(x+1)
invoke-static {vx, v(x+1)}, Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I
圖2-5 打印boolean型數據
new-instance vn, Ljava/lang/Exception;
const-string v(n+1),"這裏是 trace"
invoke-direct{vn,v(n+1)},Ljava/lang/Exception;-><init>(Ljava/lang/String;)V
invoke-virtual{v(n+1)},Ljava/lang/Exception;->printStackTrace()V
圖2-6 棧追蹤
const-string v0, "這裏是Toast輸出"
const/4 v1, 0x1
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
圖2-7 Toast輸出
const-string v0, "這裏是Toast輸出"
const/4 v1, 0x1
invoke-static {p0, v0, v1}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
move-result-object v0
invoke-virtual {v0}, Landroid/widget/Toast;->show()V
圖2-8 加載so庫
用AndroidKiller打開該apk,獲得反編譯以後的工程,如圖2-9。
圖2-9 反編譯以後的apk工程目錄
查看AndroidMainfest.xml,如圖2-10,能夠看到應用程序包名爲「org.sbtools.gamehack」,程序主活動爲「MainActivity」,還能夠看到服務名爲「org.sbtools.gamehack.sesrvice.FlowServ」。
圖2-10 AndroidMainfest.xml
找到MainActivity.smali,其中onCreate方法如圖2-11,在作一些佈局工做後調用了a(),a()方法如圖2-12,其主要工做爲啓用Instrumentation,經過Instrumentation框架,能夠在主程序啓動以前,建立模擬的系統對象,如Context;控制應用程序的多個生命週期;發送UI事件給應用程序;在執行期間檢查程序狀態等。從AndroidMainfest.xml中能夠知道Instrumentation對應的方法爲org.sbtools.gamehack.GameInstrumention。在Instrumentation中啓用了服務,如圖2-13。
圖2-11 MainActivity.onCreate()
圖2-12 MainActivity.a()
在FlowServ中,發現該方法加載了Libencode.so,而在該方法中咱們能夠找到decode被聲明爲native(圖2-14),想必能用到這個decode的地方必定是關鍵之處,因而在工程裏搜索decode,發如今/d/i.smali中用到了decode,而decode上面出現了兩個可疑文件(圖2-15)。在工程中注入代碼打印出string v1,打開eclipse, 在DDMS中打印出如圖2-16的信息,可知將路徑「/data/data/org.sbtools.gamehack/files/hack」和「/data/data/
org.sbtools.gamehack/files/gamehack」做爲參數傳給了decode(),隨後在該類的a方法中運行了hack文件(圖2-17),運行以後將該文件刪除(圖2-15)。
圖2-14 Native程序加載
圖2-15 調用decode的地方
圖2-16 獲取的path
圖2-17 給hack文件賦予root權限
這裏的gamehack文件筆者未找到,IDA調試程序安裝時顯示Libdecode.so加載失敗,所以按邏輯圖2-7中的decode()執行失敗,後面的hack文件不能執行,但以附加方式調試代碼時候hack文件確實已經執行了,觀察smali代碼反應JEB翻譯的java邏輯沒有問題,猜想程序採用了一些反調試的手段,具體緣由還待考究。
打開該程序,搜索界面和搜索結果界面如圖2-1八、圖2-19,咱們有多種方法來了解執行搜索時候java層的執行邏輯,好比在AndroidKiller中搜索字符串「搜索」,找到其ID,逐層分析其流程,或從搜索結果入手,搜索找到「共搜索到%ld個數值,請選擇修改」出現的地方,而後利用再smali代碼中添加棧回溯語句來查看棧調用順序。
圖2-18 搜索界面
圖2-19 搜索結果頁面
最後咱們在ah類中找到程序對搜索消息的的設置(圖2-20),最後發送的數據爲「s [要搜索的數據] 標誌位 0」,其中s表示正在進行搜索操做,當輸入的搜索數據合法時,標誌位爲1。咱們在這個方法中注入代碼打印出發送的消息,發送的消息如圖2-21所示。
圖2-20 設置搜索消息
圖2-21 發送的消息
那麼如今問題來了,這些消息發送給了誰?又是誰來接收這些搜索指令呢?分析到這裏,以前提到的hack文件的功能就可想而知了。
那麼這個hack文件具體作了些什麼呢?爲了進一步分析咱們須要先提取該hack文件。打開adb shell,進入該文件所在目錄,可是ls命令並未查看到,文件顯然已經被刪掉了。(圖2-22)
圖2-22 adb shell未查找到文件
此時咱們有兩種方法來找到該hack文件:
方法一:找到刪除文件的smali代碼,註釋掉刪除文件的代碼,從新打包運行。以後用adb pull /data/data/org.sbtools.gamehack/files/hack D://命令將文件拷貝到本地計算機。註釋掉的代碼如圖2-2三、圖2-24所示。
圖2-23 註釋掉的代碼1
圖2-24 註釋掉的代碼2
方法二:linux系統中每個進程都有一個/proc/[pid]目錄,該目錄下保存着有關該進程的各種信息,其中有個文件名爲exe,這個文件是一個連接指向該進程的實際可執行文件。用命令ps |grep gamehack找到該進程ID爲18912(圖2-25),執行cd /proc/18912 進入到該進程信息目錄,用ls –al會看到咱們要找的文件。linux系統刪除文件是使用了unlink這個函數,這個函數只會減小某個文件的硬鏈接數,當某個文件被打開後,並調用unlink刪除該文件時,使用ls命令是不能查看到該文件了的,但這個文件實際上仍是存在在磁盤上的,當使用該文件的進程結束時或者調用close關閉該文件描述符時,這個文件才真正的從磁盤上消失。所以,只要程序還在運行,該hack文件就不會被真正刪除,將該文件拷貝到sdcard,再pull到計算機上(圖2-26)。
圖2-25 查看進程ID
圖2-26 進入進程目錄並提取文件
接下來就能夠對該文件進行分析了。
IDA加載提取出來的hack文件,查看導出表,只有一個start(),雙擊進入start(),F5以後如圖2-27所示。
圖2-27 start()啓動函數
在我重命名爲「_HackWhat」的函數中,實現了該程序中最核心的功能。首先創建起socket鏈接,接收來自遠端的數據,並根據第一個數據來決定後續要執行的操做(圖2-28)。前面咱們已經得出,當執行數據搜索的時候用字母「s」來表示,直接分析case s的代碼(圖2-29),能夠發如今_DataMemory()中對接收到的數據作了一些處理,提取出須要搜索的數值,接着在_SearchData中讀取進程內存信息進行搜索。
圖2-28 接收socket數據
圖2-29 搜索數據
靜態分析搜索部分的代碼,能夠看到程序首先用ptrace來attatch進程(圖2-30),接着打開了進程內存映射信息所在的文件「/proc/[PID]/maps」並讀取相關信息進行保存(圖2-30)。
圖2-30 Ptrace進程
圖2-31 讀取內存映射信息
接下來程序讀取進程內存信息「/proc/[PID]/mem」並保存。此處用於監測程序的內存映射信息是否發生變化。當在執行搜索操做時,程序實際上執行的爲圖所示的_SearchData函數,該函數在IDA中的偏移地址爲0000A900。
圖2-32 讀取進程內存
圖2-33 執行搜索
在該函數中,一樣先ptrace進程,讀取內存信息並和以前保存的作一個比較,校驗內存是否發生變化,接着從內存信息中搜索咱們要修改的數據(圖2-3五、圖2-36),而此處的具體邏輯還待深究,此處未做進一步描述。
圖2-34 讀取內存信息
圖2-35 搜索數據a
圖2-36 搜索數據b
搜索完數據以後,執行圖2-29中的_SendFindResult將搜索結果發送到遠端,交給java層代碼作接下來的處理。
若是搜索結果太多,須要咱們返回遊戲,手動使想要修改的數據發生變化,而後從新搜索(圖2-37)。此時發送的消息爲「f = [Data]」 (圖2-38)。Hack程序收到socket信息後會提取變化以後的數字,再次執行圖2-33中的_SearchData函數,不過此時會讀取剛纔搜索數字8以後的內存,檢測哪個內存保存的數值變爲了12,據此來鎖定想要修改的數據所在的內存。接着執行修改操做。
圖2-37 變化數據
圖2-38 第二次搜索時向socket發送的數據
當點擊修改以後,hack進程識別標誌修改的字母「m」並執行如圖2-39所示的操做流程。在對收到搜索命令作一系列提取等操做以後,ptrace注入進程並對相應內存地址的數據進行修改(圖2-40),最後將修改結果發送給java層進行處理。
圖2-39 修改數據a
圖2-40 修改數據b
以上分析結合了靜態分析和動態分析,用IDA對進程進行動態分析的步驟以下:
1) 把IDA\dbgsrv目錄下的android_server push到android中,命令:
adb push android_server /data/data/sv
2) adb shell進入該目錄,爲android_server賦755權限並以管理員權限運行。
cd /data/data/sv
chmod 755 android_server
su
./android_server
成功運行以後能夠看到監聽端口爲23946。.
3) 在windows控制檯下轉發window到模擬器或手機端口。
adb forward tcp:23946 tcp:23946
4) 在IDA中選擇android調試,在Debuggger 中的process options 的hostname 填上localhost。
5) 在Debugger中的attach上選擇對應的android程序便可。
這裏因爲hack文件運行以後被刪除了 所以須要註釋掉刪除文件的代碼,從新編譯運行以後才能attach上該進程。附加上該進程以後在IDA右側的Modules窗格能夠看到該文件基址爲00008000,從剛纔IDA加載的咱們導出的hack文件中能夠看到start偏移地址爲00009010。兩個地址相加即爲該代碼在elf文件中的實際地址,即00011010,咱們在IDA中找到這個地址並下斷。接着運行程序點擊搜索,能夠發現程序執行了如圖所示的流程,在寄存器窗格中能夠查看到存放接收數據的地址,Hex窗格中能夠看到該地址下存放的數據。(圖2-41)
圖2-41 IDA動態加載hack程序——數據處理
調試到圖2-42所示的過程當中發現程序在讀取內存信息。
圖2-42 讀取內存
搜索完數據以後對搜索結果進行處理,將處理以後的數據發送給遠端(圖2-43)。發送的信息如圖2-44,其格式爲「[內存地址]=[查找的數據]=[數據類型]」。
圖2-43 處理搜索結果
圖2-44 發送的數據
本文中分析的燒餅遊戲修改器是一款經典的遊戲修改器,以後時常出現的不少修改器和外掛都在其基礎上衍生,對該遊戲修改器進行分析能幫助學者素數掌握修改器和外掛的思路。經過這段時間的學習,收穫以下:
1) 掌握了逆向分析的大體流程和相關工具的使用;
2) 對java語言有進一步瞭解;
3) 熟悉了android框架及一些基礎控件的使用;
4) 熟悉了smali代碼語法,能讀懂smali代碼,經過注入samli代碼來調試程序;
5) 掌握了IDA動態調試進程的方法;
6) 對Native程序有了初步的認識。
該apk是筆者分析的第一個android程序,因爲沒有相關分析經驗,以及對工具和相關編程語言不熟悉,致使前期花費了大量時間在android編程學習和java層代碼的分析上,沒有抓住程序的關鍵點。針對本文中的遊戲修改器的分析,尚有許多待完善之處:
1) 程序讀取完內存以後執行搜索操做的時候用的什麼方法或函數來搜索尚不肯定;
2) 本文只對綜合搜索進行了分析,對於修改器中提供的其餘功能,如模糊搜索、深度搜索、聯合搜索、反加密等還未作進一步分析。
3) 對JNI還需深刻學習。
初次分析,不免有錯誤、不當和疏漏的地方,若有發現,還請指正,謝謝!
@Vivi
@qq:3320163319
@email:viwilla@outlook.com
《Android 軟件安全與逆向分析》
《遊戲安全》
Android killer中的一些使用技巧: http://www.pd521.com/thread-509-1-1.html
Android killer方便搜蘇哦資源ID的一個插件http://www.pd521.com/thread-472-1-1.html
關於ptrace:http://www.cnblogs.com/catch/p/3476280.html
xx助手之每天酷跑外掛詳細分析:
http://bbs.pediy.com/showthread.php?t=187948
ARM指令STMFD和LDMFD: