無需Root也能Hook?——Depoxsed框架演示
之前我們介紹過rovo89在Githu上的Xposed框架,我們也介紹瞭如何使用Xposed框架進行
登入劫持,和廣告注入。
但是,之後很多朋友都在問我,這個Xposed框架使用起來很確實很好用。可是就是有一
個巨大的缺點,就是需要Root許可權。很多裝置都沒有Root許可權,有沒有一個不需要Root
許可權的Hook框架。
答案是,確定的。就是目前的Alibab的開源框架,Dexposed框架。
Dexposed
它的官方介紹如下:
它基於ROOT社群著名開源專案Xposed改造剝離了ROOT部分,演化為服務於所在應用自
身的AOP框架,並在Apache 2.0協議下開源。
Xposed是XDA社群使用者rovo89開發並管理的一個專案,它通過修改Android
Dalvik執行時的Zygote程序,使用Xposed
Bridge將第三方程式碼注入到Android應用的方法呼叫中,實現非侵入式的在執行期動態
修改系統和應用行為的能力。
Dexposed的原理也是很簡單,如它介紹中所說的。它是Xposed框架剝離掉了Root部分的
功能。
不熟悉Xposed原理的,可以看這裡
沒有Root許可權,那麼Xposed框架式無法替換app_process的,當然也就無法進行整個系統
級應用程式的注入了。當然,對自我程式本身還是沒有問題的。
目前Dexposed的主要應用場景有以下幾種:
- AOP程式設計
- 插樁 (如測試、效能監控等)
- 線上熱補丁
- SDK hooking以提供更好的開發體驗
AOP為Aspect Oriented
Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程
序功能的統一維護的一種技術。
看到這裡,很多小夥伴估計都會產生疑問,我靠,不能進行登入劫持了,不能注入廣告
了。我用你來幹什麼。/(ㄒoㄒ)/~
AOP程式設計,線上熱補丁
沒錯,Dexposed框架主要的功能,還是提供作為AOP框架使用。這麼一來的話,我們之前
也介紹過Android的外掛實現方式。這裡我們所用Dexposed框架來實現的話,外掛模型將
會更加簡單。
首先先介紹一下,Dexposed框架也提供了一個與Xposed框架類似的方法。
/**
* 該系統是否支援hook
*/
public static synchronized boolean canDexposed(Context context)
/**
* 尋找並hook一個指定的方法
* @param clazz 類的class
* @param methodName hook的方法名稱
* @param parameterTypesAndCallback 引數和返回callback
* @return
*/
public static Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)
線上熱補丁例項
如何進行線上的熱補丁呢?我們這裡以alibaba的demo為例。
如在主線版本中,我們有一個showDialog方法。已經發布出去了。但是,突然發現有一
點bug或者突發性需求,我們不能夠理解的發版更新。
- 這裡就能夠通過之前我們所說的DexClassLoader的方式,載入線上的外掛Path.apk
。
2. 通過Dexposed框架,動態的Hook並替換主線版本中的showDialog函式方法。
具體的邏輯如下圖所示:
看到上面的效果說明圖之後,相信大家對Dexposed的線上熱補丁已經有一定的瞭解了。
這裡我們也不用做過多的贅述。
當然,你可能想到很多使用熱補丁的應用方向,比如:
- Bug補丁修復
- 外掛功能
- 等等
Dexposed框架原理很簡單,功能也算不上強大。但是,確實特別實用。我也是推薦各大
Android開發者,特別是創業公司使用。是牆裂推薦!!
下面是主工程中與補丁工程中的邏輯實現。這裡,童鞋們可以對比著效果圖看一下。
如果大家對動態的使用DexClassLoader載入一個apk程式碼還存在疑問。 可以clone一下
dexposed的原始碼學習學習。
主工程中,MainActivity showDialog方法的定義
public class MainActivity extends Activity {
//..........一些忽略掉的程式碼
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Dexposed sample")
.setMessage("Please clone patchsample project to generate apk, and copy it to \"/Android/data/com.taobao.dexposed/cache/patch.apk\"")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).create().show();
}
}
線上熱補丁,Path.apk中的程式碼
/**
* 外掛的補丁類
*/
public class DialogPatch implements IPatch {
@Override
public void handlePatch(final PatchParam arg0) throws Throwable {
// 獲取主程式的ClassLoader
Class<?> cls = null;
try {
// 獲取主程式的MainActivity類
cls= arg0.context.getClassLoader().loadClass("com.taobao.dexposed.MainActivity");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return;
}
// hook並替換MainActivity中的showDialog方法
DexposedBridge.findAndHookMethod(cls, "showDialog", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
// 彈出一個外掛中的Dialog
Activity mainActivity = (Activity) param.thisObject;
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
builder.setTitle("Dexposed sample")
.setMessage("The dialog is shown from patch apk!")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).create().show();
return null;
}
});
}
}
/*
* @author zhoushengtao(周聖韜)
* @since 2015年8月26日 凌晨0:08:22
* @weixin stchou_zst
* @blog http://blog.csdn.net/yzzst
* @交流學習QQ群:341989536
* @私人QQ:445914891
/