編輯:關於Android編程
圖/文 莫灰灰
近些年來,移動互聯網的大肆崛起,潛移默化中影響著人們的生活和工作習慣。當騰訊的微信平台接入手機游戲之後,移動端的游戲也開始火了起來,這更是改變了人們長久以來的游戲娛樂習慣。茶余飯後,小伙伴們掏出“家伙”打個飛機已是習以為常的事情了。加之移動客戶端游戲開發周期短,投入少等特點,很多初創公司也紛紛投入到這個領域中來,並且很多游戲都取得了不錯的成績。就在前不久,全球游戲巨頭暴雪的新游戲《爐石傳說》也推出了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端游戲還是移動端游戲,外掛與游戲的斗陣始終都不會結束。
這篇文章主要介紹一下如何實現View的3D旋轉效果,實現的主要原理就是圍繞Y軸旋轉,同時在Z軸方面上有一個深入的縮放。演示的demo主要有以下幾個重點: 1,自定義旋轉動
在研究如何實現Pushing功能期間,收集了很多關於Pushing的資料,其中有一個androidnp開源項目用的人比較多,但是由於長時間沒有什麼人去維護,聽說bug的幾
上一篇,我們從源碼的角度分析了View的事件分發過程,這篇我們從實例的角度來看看不同實例下具體的輸出會是什麼樣子的呢?好的,我們開始吧!同樣我們的測試布局文件: 
前言給自己的APP增加相機是一個不錯的功能,在我們打開相機時,如果能動態給我們的臉上貼上標簽,或者是貼上一個卡通的眼睛,最後點擊拍照,一張合成的圖片就產生了,這是不是一個