? ? ? ?Xposed框架是一款可以在不修改APK的情況下影響程序運(yùn)行(修改系統(tǒng))的框架服務(wù)产捞,基于它可以制作出許多功能強(qiáng)大的模塊愈涩,且在功能不沖突的情況下同時(shí)運(yùn)作捧灰。
Github地址:https://github.com/rovo89/Xposed喳钟。
官方教程:https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
目前有關(guān)Xposed框架的說明已經(jīng)很多律想,這里通過一個(gè)登錄劫持實(shí)例來介紹Xposed模塊開發(fā)。
登錄例子如下:
public class MainActivity extends AppCompatActivity {
private final String USER="admin";
private final String PASSWORD="123456";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick_Login(View view) {
EditText editText = (EditText) findViewById(R.id.user);
EditText editText1 = (EditText) findViewById(R.id.password);
String m_user = editText.getText().toString();
String m_password = editText1.getText().toString();
if(CheckLogin(m_user,m_password)){
Toast.makeText(MainActivity.this,"登陸成功",Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(MainActivity.this,"登陸失敗",Toast.LENGTH_SHORT).show();
}
}
private boolean CheckLogin(String user, String password) {
return user.equals(USER) && password.equals(PASSWORD);
}
}
編譯運(yùn)行流济,只有當(dāng)用戶锐锣、密碼匹配才提示登錄成功腌闯,否則顯示登錄失敗。
接下來編寫Xposed模塊雕憔,通過Xposed模塊可以攔截CheckLogin()這個(gè)函數(shù)绑嘹,使得不管輸入什么用戶、密碼都能提示登錄成功橘茉。
(1)創(chuàng)建無acitvity工程工腋,設(shè)置成為xposed模塊
在application標(biāo)簽增加三個(gè)三個(gè)元數(shù)據(jù)(meta-data)
(2)引用xposed框架的jar包
將xposed庫(kù)文件XposedBridgeApi-XX.jar, 放入app/lib文件夾下畅卓,編輯更改庫(kù)的依賴關(guān)系為Provided擅腰,這個(gè)很重要。build.gradle中為
(3)創(chuàng)建模塊類Hook翁潘,實(shí)現(xiàn)Xposed中的接口IXposedHookLoadPackage
public class Hook implements IXposedHookLoadPackage {
String packName = "com.ch369.loginwindow";
String className = "com.ch369.loginwindow.MainActivity";
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
//處理指定包名的應(yīng)用
if(!loadPackageParam.packageName.equals(packName))
return;
XposedBridge.log("Loaded app: " + loadPackageParam.packageName);
XposedHelpers.findAndHookMethod(className,
loadPackageParam.classLoader,
"CheckLogin",
String.class,
String.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("param 1:" + (String) param.args[0]);
XposedBridge.log("param 2:" + (String) param.args[1]);
// param.setResult(true);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
XposedBridge.log("login result:" + param.getResult().toString());
}
});
}
}
其中handleLoadPackage()獲取包加載時(shí)的回調(diào)并拿到其對(duì)應(yīng)的ClassLoader趁冈。findAndHookMethod()找到指定類對(duì)應(yīng)的方法進(jìn)行hook。原型如下:
public?static XC_MethodHook.Unhook findAndHookMethod(
String className, //函數(shù)所在類名
ClassLoader classLoader, //指定Classloader
String methodName, //方法名
Object... parameterTypesAndCallback) { //參數(shù)類型列表和Hook回調(diào)return findAndHookMethod(findClass(className, classLoader), methodName, parameterTypesAndCallback); }
其中參數(shù)類型列表是不定參拜马,按順序傳入?yún)?shù)的類型渗勘,最后一個(gè)參數(shù)一定是回調(diào)函數(shù),用于在Hook點(diǎn)被執(zhí)行時(shí)的回調(diào)俩莽。
其中旺坠,回調(diào)分為如下兩種:
XC_MethodHook:在目標(biāo)方法執(zhí)行前/后運(yùn)行相應(yīng)的替換函數(shù);
XC_MethodReplacement?:完全替換目標(biāo)方法扮超。
這里用了XC_MethodHook取刃,有beforeHookedMethod和afterHookedMethod兩種方法在Hook點(diǎn)被執(zhí)行回調(diào)。
(4)申明主入口類出刷,
在assets目錄下新建“xposed_init”文件璧疗,在文件中說明需要加載到XposedInstaller的入口類,完整的類名:包名+類名
編譯并安裝到裝有Xposed框架的手機(jī)上馁龟,Xposed Installer會(huì)自動(dòng)檢測(cè)到崩侠,進(jìn)入Xposed Installer,選中HookDemo,并重啟手機(jī)坷檩。
重啟手機(jī)后運(yùn)行登錄程序却音,輸入user和password登錄,在Xposed Installer日志中可以看到日志如下日志信息淌喻,表明登錄函數(shù)CheckLogin已經(jīng)被攔截成功僧家。
在beforeHookedMethod()中增加param.setResult(true),重新編譯安裝重啟運(yùn)行裸删,這時(shí)無論輸入什么用戶和密碼,都能提示登錄成功阵赠,篡改登錄函數(shù)CheckLogin()成功涯塔。
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("param 1:" + (String) param.args[0]);
XposedBridge.log("param 2:" + (String) param.args[1]);
param.setResult(true);
}
同樣肌稻,用XC_MethodReplacement完全替換對(duì)應(yīng)方法也可以達(dá)到類似效果。
XposedHelpers.findAndHookMethod(className,loadPackageParam.classLoader, "CheckLogin", String.class,
String.class, new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("login ok");
return true;
}
});