前言
Xposed這位老兄大家可能不認(rèn)識织狐,微信自動搶紅包大家聽過吧、微信記錄器作弊大家聽過吧筏勒、地理位置模擬大家聽過吧,我很負(fù)責(zé)任的告訴大家旺嬉,這些都是Xposed干的管行,對的,就是它邪媳,相信大家充著“誰搶我紅包”的憤怒捐顷,也想結(jié)識下這個牛逼的人物吧荡陷,草民在此(淫蕩一笑),我們開始吧迅涮。
Xposed 介紹
大名鼎鼎得Xposed废赞,是Android平臺上最負(fù)盛名的一個框架,百度百科介紹是:“Xposed框架是一款可以在不修改APK的情況下影響程序運(yùn)行(修改系統(tǒng))的框架服務(wù)叮姑,基于它可以制作出許多功能強(qiáng)大的模塊唉地,且在功能不沖突的情況下同時運(yùn)作”,在這個框架下传透,我們可以加載很多插件App耘沼,這些插件App可以直接或間接劫持、篡改朱盐、偽造一些信息群嗤。有了Xposed后,理論上我們的插件APP可以hook到系統(tǒng)任意一個Java進(jìn)程zygote兵琳、systemserver狂秘、systemui。
Xposed 原理
Zygote 進(jìn)程簡析及與Xposed關(guān)系
在Android系統(tǒng)中躯肌,應(yīng)用程序進(jìn)程以及系統(tǒng)服務(wù)進(jìn)程SystemServer都是由Zygote進(jìn)程孵化出來的者春,而Zygote進(jìn)程是由Init進(jìn)程啟動的,Zygote進(jìn)程在啟動時會創(chuàng)建一個Dalvik虛擬機(jī)實(shí)例羡榴,每當(dāng)它孵化一個新的應(yīng)用程序進(jìn)程時碧查,都會將這個Dalvik虛擬機(jī)實(shí)例復(fù)制到新的應(yīng)用程序進(jìn)程里面去,從而使得每一個應(yīng)用程序進(jìn)程都有一個獨(dú)立的Dalvik虛擬機(jī)實(shí)例校仑,這也是Xposed選擇替換app_process的原因忠售。
Zygote進(jìn)程在啟動的過程中,除了會創(chuàng)建一個Dalvik虛擬機(jī)實(shí)例之外迄沫,還會注冊一些Android核心類的JNI方法到Dalvik虛擬機(jī)實(shí)例中去稻扬,以及將Java運(yùn)行時庫加載到進(jìn)程中來。而一個應(yīng)用程序進(jìn)程被Zygote進(jìn)程孵化出來的時候羊瘩,不僅會獲得Zygote進(jìn)程中的Dalvik虛擬機(jī)實(shí)例拷貝泰佳,還會與Zygote一起共享Java運(yùn)行時庫,這也就是可以將XposedBridge這個jar包加載到每一個Android應(yīng)用程序中的原因尘吗,想更多了解Zygote 進(jìn)程可以去看下老羅的文章Android系統(tǒng)進(jìn)程Zygote啟動過程的源代碼分析逝她。
Hook/Replace 簡析
Xposed 框架中真正起作用的是對方法的hook。在Repackage技術(shù)中睬捶,如果要對APK做修改黔宛,則需要修改Smali代碼中的指令,而另一種動態(tài)修改指令的技術(shù)需要在程序運(yùn)行時基于匹配搜索來替換smali代碼擒贸,但因?yàn)榉椒暶鞯亩鄻有耘c復(fù)雜性臀晃,這種方法也比較復(fù)雜觉渴。
在Android系統(tǒng)啟動的時候,zygote進(jìn)程加載XposedBridge將所有需要替換的Method通過JNI方法hookMethodNative指向Native方法
xposedCallHandler徽惋,xposedCallHandler在轉(zhuǎn)入handleHookedMethod這個Java方法執(zhí)行用戶規(guī)定的Hook Func案淋。
Xposed框架的原理是通過替換/system/bin/app_process程序控制zygote進(jìn)程,使得app_process在啟動過程中會加載XposedBridge.jar這個jar包险绘,從而完成對Zygote進(jìn)程及其創(chuàng)建的Dalvik虛擬機(jī)的劫持踢京。
與采取傳統(tǒng)的Inhook方式詳見Dynamic Dalvik Instrumentation這篇文章 相比,Xposed在開機(jī)的時候完成對所有的Hook Function的劫持隆圆,在原Function執(zhí)行的前后加上自定義代碼漱挚,由于是通過安裝基于Xposed框架的App來修改系統(tǒng),所以風(fēng)險會比直接修改系統(tǒng)文件來得少渺氧,有一定風(fēng)險旨涝,如變磚、無限重啟等侣背,需謹(jǐn)慎白华!
工程組成
XposedInstaller
這是Xposed的插件管理和功能控制APP,也就是說Xposed整體管控功能就是由這個APP來完成的贩耐,它包括啟用Xposed插件功能弧腥,下載和啟用指定插件APP,還可以禁用Xposed插件功能等潮太。注意管搪,這個app要正常無誤得運(yùn)行必須能拿到root權(quán)限。
Xposed
這個項(xiàng)目屬于Xposed框架铡买,其實(shí)它就是單獨(dú)搞了一套xposed版的zygote更鲁。這個zygote會替換系統(tǒng)原生的zygote。所以奇钞,它需要由XposedInstaller在root之后放到/system/bin下澡为。
XposedBridge
這個項(xiàng)目也是Xposed框架,它屬于Xposed框架的Java部分景埃,編譯出來是一個XposedBridge.jar包媒至。
XposedTools
Xposed和XposedBridge編譯依賴于Android源碼,而且還有一些定制化的東西谷徙。所以XposedTools就是用來幫助我們編譯Xposed和XposedBridge的拒啰。
使用示例
環(huán)境搭建
一、下載完慧、安裝XposedInstaller
安裝后如圖所示:
...
二图呢、gradle 配置
dependencies {
// ** 省略部分代碼
provided 'de.robv.android.xposed:api:82'
//如果需要引入文檔,方便查看的話
provided 'de.robv.android.xposed:api:82:sources'
}
三骗随、AndroidManifest 配置
在application標(biāo)簽下添加配置:
<?xml version="1.0" encoding="utf-8"?>
<manifest xxx
<application xxx>
<!-- 1蛤织、標(biāo)識自己是否為一個Xposed模塊 -->
<meta-data
android:name="xposedmodule"
android:value="true"/>
<!-- 2、Xposed模塊的描述信息 -->
<meta-data
android:name="xposeddescription"
android:value="a sample for xposed"/>
<!-- 3鸿染、支持Xposed框架的最低版本 -->
<meta-data
android:name="xposedminversion"
android:value="53"/>
</application>
</manifest>
至此指蚜,準(zhǔn)備工作都已完畢,下面可以擴(kuò)展xposed模塊了~
模塊擴(kuò)展
這里我簡單模擬一下獲取imei號的劫持篡改涨椒。
一摊鸡、activity 代碼示例:
TextView tvImei = (TextView) findViewById(R.id.tv_imei);
TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
String imei = telephonyManager.getDeviceId();
tvImei.setText("imei:" + imei);
二、TelephonyHooks
通過源代碼跟蹤蚕冬,我們發(fā)現(xiàn)telephonyManager.getDeviceId()
在android.telephony.TelephonyManager包下免猾,所以我們需要劫持此方法。
public class TelephonyHooks implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
// 可以排除非當(dāng)前包名
if (!lpparam.packageName.equals("com.walid.xposedlocation")) {
return;
}
XC_MethodHook hook = new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("beforeHookedMethod");
}
@Override
protected void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable {
methodHookParam.setResult("walid");
XposedBridge.log("Hook device id is successful!!! ");
}
};
findAndHookMethod("android.telephony.TelephonyManager", lpparam.classLoader, "getDeviceId", hook);
}
}
三囤热、在assets目錄下創(chuàng)建xposed_init文件并添加TelephonyHooks文件所在完整目錄
例如我的是:
com.walid.xposedlocation.TelephonyHooks
四猎提、運(yùn)行項(xiàng)目
運(yùn)行結(jié)果如下:
此刻有的同學(xué)要吐槽了:
問:說您老忙活半天,這不還是沒篡改成功嗎旁蔼,結(jié)果還是真正的imei號呀锨苏!是在逗我呢嗎?
答: 由于xposed框架從根上Hook了Android Java虛擬機(jī)棺聊,所以它需要root伞租,且每次為它啟用新插件APP都需要重新啟動才能生效,這點(diǎn)草民也有些想吐槽限佩,不過這個權(quán)衡之后草民還是接受了葵诈,畢竟人無完人,何況程序呢祟同。
五作喘、開啟xposed模塊并軟重啟
1、選中模塊
2耐亏、選擇重啟
3徊都、運(yùn)行結(jié)果
長嘆一口氣,我們終于看到劫持篡改后的結(jié)果了~
結(jié)語
這篇簡短的教程广辰,草民并沒有像其他人一樣給予大家demo地址之類的暇矫,因?yàn)椴菝癫⒉幌胱尨蠹抑苯酉螺ddemo,run一下就可以了择吊,還是希望大家多動手李根,同時如果有不清楚的同學(xué),隨時聯(lián)系草民几睛,同時這樣的hook技術(shù)可以應(yīng)用到任何場合房轿,包括反編譯、分析競品、植入廣告囱持、搶紅包等等夯接,還是希望將技術(shù)應(yīng)用到該用的地方,而不是應(yīng)用在非法或者違法常規(guī)的事情上面纷妆,忘謹(jǐn)記?浮!掩幢!