6、XPOSED二、叉叉助手框架--用XPOSED實現
阿新 • • 發佈:2019-01-07
繼《xposed框架初探》之後,編寫一個小小的demo應用,剛好之前分析叉叉的遊戲輔助框架(參考《叉叉助手逆向分析續集--模擬實現遊戲外掛框架--再擴充套件到脫殼機》,我們是用了libsubstrate的hook框架來完成的),這次就用XPOSED實現一下。
相關參考:
看雪論壇《XPOSED的小筆記》,文章介紹的很詳細很清晰。
準備工作:
上一篇中我們用的是“華為專用Xposed框架”,也並不是很完美,於是還是從官網上下載穩定版本的,這個要視不同手機而定。
http://repo.xposed.info/module/de.robv.android.xposed.installer,點下面的“Show
older versions”逐個版本安裝試用,每個版本都要啟用一次並重啟手機,還是挺麻煩的,好在試到2.5.1版本的時候成功了!這個版本確實比“ 華為專用Xposed框架”要穩定完美許多,果斷換用2.5.1官方版本。
實現思路:
實現介面IXposedHookLoadPackage的介面函式handleLoadPackage,判斷引數包名是否是目標APK,若是則呼叫findAndHookMethod對目標啟動類的onCreate函式進行HOOK,在afterHookedMethod函式中動態載入外掛,將引數中有關activity的例項傳給外掛。
一個 XposedModule 本質上是設定了部分特殊元資料標誌位的普通應用程式,需要在 AndroidManifest.xml 檔案中新增如下設定:
AndroidManifest.xml => Application => Application Nodes (at the bottom) => Add => Meta Data
新增節點:name = xposedmodule,value = true。name = xposedminiversion, value = API level。
Next, make the XposedBridge API known to the project. You can download
xposed與libsubstrate的對比: 測試都需要經過反覆的重啟,此次xposed的測試demo也是如是,即便寫的只是java層程式碼,也需要每次改動都要重啟手機。而之前用libsubstrate實現的底層hook,在每次改動JNI程式碼後也是需要重啟手機的。 程式碼量方面還是xposed框架下少很多,而且都是java層程式碼,寫起來速度也快不容易出錯,測試的時間自然也少很多。
<新增標記的作用估計是讓XPOSED安裝器識別為外掛。 新增庫檔案:XposedBridgeApi.jar 需要注意的是這個jar包不能放到工程的libs目錄,否則執行會出現異常。最好是放到工程主目錄下,然後在eclipse裡右鍵選擇該jar-Build Path => Add to Build Path。 注意這個jar包版本選擇,經測試XposedBridgeApi-54.jar在2.5.1版本的xposedinstaller下是相容的,但是最新版的靠譜助手(2.5.1143)上預設整合安裝了2.6.1版本的xposedinstaller,測試發現XposedBridgeApi-54.jar並不是很穩定,後來改用XposedBridgeApi-42.jar是可以的。application android:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name" android:theme="@style/AppTheme"android:name=".MainApplication"> <!-- Xposed --> <meta-dataandroid:name="xposedmodule" android:value="true" /> <meta-dataandroid:name="xposedminversion"android:value="42+" /> <meta-data android:name="xposeddescription"android:value="GameAssistant" /> <activityandroid:name="com.netease.ga.view.MainActivity"android:theme="@android:style/Theme.NoTitleBar.Fullscreen"><intent-filter> <actionandroid:name="android.intent.action.MAIN" /> <categoryandroid:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activityandroid:name=".view.MyGamesActivity"android:theme="@android:style/Theme.NoTitleBar.Fullscreen"/><activity android:name=".view.PluginsActivity" /> <activityandroid:name=".view.MoreActivity" /> <receiverandroid:name=".receiver.MyReceiver" /> </application>
Next, make the XposedBridge API known to the project. You can downloadXposedBridgeApi-<version>.jar
from
the first post ofthis
XDA thread. Copy it into a subfolder calledlib
.
Then right-click on it and select Build Path => Add to Build Path. The<version>
from
the file name is the one you insert asxposedminversion
in
the manifest.
這個設定對應到androidstudio的操作步驟: F4開啟工程結構,選擇Modules-當前專案-Dependencies-+-選擇“Jar or directiories”, 選擇jar包後,在“Scope”欄選擇“Provided”,不要選擇“Complie”。 然後宣告一個類XposedXXHook實現介面IXposedHookLoadPackage 在 assets 目錄下新建一個 xposed_init 檔案,這個檔案聲明瞭需要載入到 XposedInstaller 的入口類:com.netease.ga.XposedXXHook 由於改動不大,因此直接在原來的GA工程(基於libsubstrate的叉叉遊戲輔助框架)上新增。 完善XposedXXHook的程式碼:Make sure that the API classes are not included (but only referenced) in your compiled APK, otherwise you will get an
IllegalAccessError
. Files in thelibs
(with "s") folder are automatically included by Eclipse, so don't put the API file there.
package com.netease.ga; import android.app.Activity; import android.content.Context;import android.content.SharedPreferences; import android.os.Build; importandroid.os.Bundle; import android.util.Log; import java.lang.reflect.Method; importdalvik.system.DexClassLoader; import de.robv.android.xposed.IXposedHookLoadPackage;import de.robv.android.xposed.XC_MethodHook; importde.robv.android.xposed.callbacks.XC_LoadPackage; import staticde.robv.android.xposed.XposedHelpers.findAndHookMethod; import staticde.robv.android.xposed.XposedHelpers.findClass; /** * Created by sing on 14-9-17. * desc: */ public class XposedXXHook implements IXposedHookLoadPackage { private staticfinal String TAG = "XposedXXHook"; private static final String TARGET_PACKAGE = "com.example.helloapplication"; private static final String TARGET_CLASS = "com.example.helloapplication.MainActivity"; private static final String TARGET_FUNCTION = "onCreate"; //private SharedPreferences sp; /** * * @param param *@throws Throwable */ @Override public voidhandleLoadPackage(XC_LoadPackage.LoadPackageParam param) throws Throwable { String packageName = param.packageName; Log.d(TAG, "handleLoadPackage: " + packageName); if(packageName.equals(TARGET_PACKAGE) == false) { return; } Log.d(TAG,"handleLoadPackage: star hook"); XC_MethodHook.Unhook unhook = findAndHookMethod(TARGET_CLASS, param.classLoader, TARGET_FUNCTION, Bundle.class, newXC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param)throws Throwable { Log.d(TAG, "[handleLoadPackage]beforeHookedMethod"); } @Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable { Log.d(TAG,"[handleLoadPackage]afterHookedMethod: " + param.thisObject.toString()); String plugApkPath = "/data/data/com.netease.ga/app_plugin/lianmengplug.apk"; String plugSoPath = "/data/data/com.netease.ga/app_plugin/libxxlianmeng_mm.so"; String dexOutputDir = "/data/data/" + TARGET_PACKAGE + "/cache"; ClassLoader localClassLoader = ClassLoader.getSystemClassLoader(); DexClassLoader localDexClassLoader = new DexClassLoader(plugApkPath, dexOutputDir, null, localClassLoader); java.lang.Class<?> plugClass = localDexClassLoader.loadClass("com.xxAssistant.UI.UniversalUI"); Method mInit = plugClass.getDeclaredMethod("init", Activity.class, String.class); mInit.invoke(null, param.thisObject, plugSoPath); } }); if (unhook!=null) { Log.d(TAG,"handleLoadPackage: hook ok"); }else{ Log.d(TAG, "handleLoadPackage: hook failed"); } } }注意這段程式碼只HOOK包名為com.example.helloapplication的應用程式,如果要HOOK其他應用程式則把包名過濾的判斷去掉,並動態解析應用程式的主啟動類即可。 編譯安裝好後在xposed安裝器的模組中啟用GA並重啟手機。 啟動手機後不用執行xposed安裝器和GA,直接執行helloapplication程式: 可以看出外掛已經被我們成功載入了。 常見錯誤: 09-17 07:58:42.049: I/Xposed(2447): java.lang.NoSuchMethodError: com.example.helloapplication.MainActivity#onCreate()#exact 錯誤為未找到對應的函式,在hook的時候需要指定函式的引數形式。
findAndHookMethod(TARGET_CLASS, param.classLoader, TARGET_FUNCTION, newXC_MethodHook(){...});
因為onCreate是有引數的,所以正確的呼叫方式是:
findAndHookMethod(TARGET_CLASS, param.classLoader, TARGET_FUNCTION, Bundle.class, newXC_MethodHook(){...});
xposed與libsubstrate的對比: 測試都需要經過反覆的重啟,此次xposed的測試demo也是如是,即便寫的只是java層程式碼,也需要每次改動都要重啟手機。而之前用libsubstrate實現的底層hook,在每次改動JNI程式碼後也是需要重啟手機的。 程式碼量方面還是xposed框架下少很多,而且都是java層程式碼,寫起來速度也快不容易出錯,測試的時間自然也少很多。