Android版xx助手之天天酷跑外掛詳細分析
轉載於:紅黑聯盟
Android版xx助手之天天酷跑外掛詳細分析
圖/文 莫灰灰
背景
近些年來,移動網際網路的大肆崛起,潛移默化中影響著人們的生活和工作習慣。當騰訊的微信平臺接入手機遊戲之後,移動端的遊戲也開始火了起來,這更是改變了人們長久以來的遊戲娛樂習慣。茶餘飯後,小夥伴們掏出“傢伙”打個飛機已是習以為常的事情了。加之移動客戶端遊戲開發週期短,投入少等特點,很多初創公司也紛紛投入到這個領域中來,並且很多遊戲都取得了不錯的成績。就在前不久,全球遊戲巨頭暴雪的新遊戲《爐石傳說》也推出了iPad版本,更加印證了移動端的重要性。
如同PC端一樣,移動端遊戲的興起,自然也就造就了遊戲外掛產業的火熱市場。大名鼎鼎的xx助手就是這樣一款移動端的遊戲外掛軟體,它不僅功能強大,而且相容IOS和Android等多平臺系統。正所謂樹大招風,接下來,我們就來對其內部實現做一個詳細的分析,來一窺Android平臺下游戲外掛的實現原理。
特此申明:本文涉及的程式碼與分析內容僅供學習交流使用,任何個人或組織不得使用文中提到的技術做違法犯罪活動,否則由此引發的任何後果與法律責任本人概不負責。
測試環境
紅米TD版
MIUI-JHACNBA13.0(已越獄)
叉叉助手Beta1.1.2
使用工具
IDA
Apktool
Ddms
jd-gui
程式分析
在分析程式之前,我首先去下載了《歡樂鬥地主》、《全民飛機大戰》、《天天酷跑》三款騰訊的熱門遊戲,開啟xx助手,介面如圖1所示。
圖1
此時,xx助手已經檢測到機器上安裝的遊戲了,在xx助手裡面下載相應遊戲的外掛程式之後點選“啟動遊戲”來開啟天天酷跑,介面如圖2所示。
圖2
很明顯,從xx助手中開啟遊戲會發現右邊多了一個設定按鈕,點選設定,在彈出的介面中我們可以設定相應的“飛行距離”、“獎勵倍數”等。
開啟DDMS,使用FileExplorer工具定位到/data/data/com.xxAssistant,檢視目錄結構如圖3所示。
圖3
仔細檢視圖3中的app_plugin目錄,發現其中恰好有三個子級目錄,分別對應了酷跑,歡樂鬥地主和飛機大戰的外掛外掛。
到目前為止,單從這個目錄結構中,我們大致可以得出如下一個猜想,即:xx助手主程式只是一個啟動器,用來啟動各個遊戲外掛,更多時候,可以把它理解為是一個遊戲外掛的釋出平臺,本身並不具備修改遊戲的功能。而每一個外掛目錄才是具體實現某個遊戲的外掛程式。例如,拿103目錄來說,xxUI.apk是上述圖2中看到的那個遊戲中出現的設定介面,libxxkupao.so是實現hook遊戲關鍵函式,修改遊戲功能的重要庫檔案,而xxplist可能是某個配置檔案。為了印證自己的猜測是否正確,我們利用工具把103外掛目錄匯出到本地來做詳細分析。
驗證猜想
1、com.tencent.pao.xxplist
用文字編輯器開啟外掛目錄下的com.tencent.pao.xxplist檔案,內容如圖4。
圖4
經過簡單的分析,此檔案確實是為xx助手的配置檔案。其中,game-name欄位為被操作的遊戲包名;apk-path欄位為具體外掛的apk檔案;ui-name欄位則是外掛啟動後的主Activity;activity-name欄位為遊戲的主Activity;so-path欄位則為具體實現hook遊戲相關函式,patch遊戲程序的主要檔案。
2、xxzhushou_android.apk
此apk檔案為xx助手的安裝檔案,經過詳細分析,xx助手主程式主要實現了下載指定遊戲外掛、啟動遊戲、解析上述xxplist、把外掛dex注入到遊戲程序等功能。而且這一整套東西的實現與具體的某個遊戲是鬆耦合的,堪稱是一個遊戲外掛的釋出平臺呀。(由於我們今天主要分析的是遊戲外掛的實現原理,下回有時間再寫一篇詳細分析xx助手的文章,所以在這裡,關於xx助手本身的功能就先一筆帶過了)
3、xxUI.apk
這個包檔案是進入遊戲之後主要顯示的外掛設定介面,具體如圖2所示。下面我們來具體分析下其實現原理。
解包xxUI.apk,使用JavaDecompiler工具檢視解密出來的類java程式碼,程式碼結構如圖5所示。
圖5
發現程式碼並沒有經過加密混淆,下面我們首先來看看xxkupao這個類的實現,如圖6所示。
圖6
這個類的init函式首先儲存so path路徑,然後呼叫show函式初始化介面佈局。show函式中呼叫initView來建立Setting和About View,並使用線性佈局來排版介面。接下來我們來看看Setting View的實現,如圖7。
圖7
這個Setting View類的大致功能是,首先儲存so檔案的路徑,即/data/data/com.xxAssistant/app_plugin/103/libxxkupao.so,然後呼叫initNativeFunc函式載入so檔案,並開始patch遊戲的相關函式,接著呼叫initView函式初始化介面中的各種控制元件。
具體來看下initNativeFunc函式,圖7中這個函式反編譯出來的程式碼並不是很準確,大致的程式碼應該是這樣的,如圖8所示。
圖8
InitNativeFunc函式首先載入so檔案,然後通過呼叫set方法設定相應的外掛屬性。最後判斷CPU的型別,實施不同的hook方案(因為天天酷跑這個遊戲會根據CPU的不同而釋放不同的遊戲so檔案,所以hook的時候程式碼偏移都有所不同,這裡hook方案的不同主要就是為了配合遊戲釋放出來的檔案不同)。其中這裡的set方法和xxdohook函式都是JNI呼叫,即在java層中呼叫底層c或者c++的程式碼,不知道這方面知識的同學可以學習下NDK開發。
4、libxxkupao.so
通過上面的分析之後,我們知道 xxUI.apk其實是通過JNI呼叫實現的,具體功能的實現都在這個so檔案中。
具體來看下setBonus,即設定獎勵倍數方法的具體實現吧,其他都大同小異了。使用IDA開啟libxxkupao.so,定位到Java_com_xxAssistant_UI_xxkupaoSettingView_setBonus函式,彙編程式碼如圖9所示。
圖9
JNI呼叫的前面兩個引數是系統傳進來的,我們不必關心,引數3是我們自己傳進來的獎勵倍數,是一個整形的數值,經過簡單處理之後把獎勵倍數儲存為全域性變數,供後面函式呼叫使用。
下面我們來看看xxdohook函式的實現,由於函式太長,主要以獎勵倍數功能的實現開始分段講解。
(1).儲存傳進來的引數到區域性變數中,引數3即是我們自己傳進來的引數,根據CPU型別來決定hook型別。
圖10
(2).獲取遊戲程序中libGameApp.so的基址。
圖11
(3).根據CPU的不同,java層會傳遞不同的引數下來,用以實現不同的hook。其中大體的實現思路是一樣的,主要是因為不同的CPU,遊戲釋放出來的so檔案是不同的,所以兩種hook型別基本上只是檔案偏移的不同,下面我們選擇其中的一個分支來進行詳細介紹。
圖12
(4).獲取到遊戲so檔案基址之後,呼叫dlsym方法根據符號名試圖解析出AddScore函式的地址。
圖13
(5).如果通過符號找到了相應函式的地址,那麼就呼叫MSHookFunction函式進行hook遊戲的關鍵call,以此來改變遊戲的執行流程。(MSHookFunction是Cydia Substrate的庫函式,此框架功能強大,支援Android和IOS的hook)
圖14
(6).當然,通常情況下,我們並沒有遊戲的符號檔案,所以在第(4)步中呼叫dlsym函式解析符號地址的時候就已經失敗了,那麼此時函式便會根據硬編碼地址來進行hook。
圖15
(7).至此,遊戲的patch工作已經全部完成,接下來就可以開始玩遊戲了。遊戲在執行過程中,會進入到我們的hook函式中。例如,一局遊戲結束後,那麼系統會給予一定獎勵,此時,便會進入我們的mine_AddScore函式中開始執行,下面我們來看下此函式的具體實現。
圖16
經過分析,此函式的實現邏輯其實很簡單,例如我設定了獎勵倍數為10,那麼hook程式碼就會迴圈呼叫10次遊戲本身的addScore函式來實現多倍獎勵的功能。
總體的呼叫過程用一張圖來說明就更加形象了,如圖17所示。
圖17
總結
遊戲的設計和架構在很大程度上與網路資源息息相關。基於移動端網路的不穩定性,以及國內網路流量資費比較昂貴等特點,大多數移動端遊戲都會將絕大部分的功能放在本地來實現,只有絕少部分重要的資訊才會與伺服器端程序同步,例如裝備、資金的變更。因此,遊戲外掛只要patch掉本地遊戲的關鍵函式就能達到類似無敵、穿牆、飛行等變態功能。
基於以上的特點,遊戲作者可以額外的開一個執行緒來定時檢測自身程式碼是否被惡意篡改了。但是,執行緒和定時器又是很容易被外掛patch掉的,因此,不管是PC端遊戲還是移動端遊戲,外掛與遊戲的鬥陣始終都不會結束。