Xposed工作原理
zygote进程
Android运行的心脏。每一个应用都是这个进程的fork,都从这个进程的一个fork开始。
Android系统启动时,zygote进程被/init.rc脚本启动。当/system/bin/app_process加载完成时,zygote启动完成。/system/bin/app_process负责加载必要的类和调用初始化方法。
Xposed
安装xposed后,会复制一份扩展后的app_process到/system/bin,这个app_process会添加一个额外的jar到classpath并且在特定的地方调用方法。
举个例子,当虚拟机创建后,在zygote的main函数执行之前,或者main函数中,xposed时zygote的一部分并且可以控制上下文。
jar位于/data/data/de.robv.android.xposed.installer/bin/XposedBridge.jar
。
使用Xposed可以hook方法,在方法前后注入代码。
XposedBridge还有native方法hookMethodNative,会将某个方法改成native并且把方法link到自己的native方法。
Xposed入门示例
新建Android Studio工程,选择空白activity
下载xposedAPI,放在工程的libs目录下
改动build.gradle(:app),如果有implementation fileTree()就换成compileOnly,如果没有就添加一行compileOnly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.example.redclocknew"
minSdkVersion 20
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
// implementation fileTree(dir: "libs", include: ["*.jar"])
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}编辑AndroidManifest.xml,添加一系列meta-data,比如我的是这样
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.redclocknew">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Easy example which makes the status bar clock red and adds a smiley" />
<meta-data
android:name="xposedminversion"
android:value="53" />
</application>
</manifest>创建类,添加代码,示例如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34package com.example.redclocknew;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import android.graphics.Color;
import android.widget.TextView;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
public class RedClock implements IXposedHookLoadPackage {
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.systemui"))
return;
// XposedBridge.log("Loaded app: " + lpparam.packageName);
findAndHookMethod("com.android.systemui.statusbar.policy.Clock", lpparam.classLoader, "updateClock", new XC_MethodHook() {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
TextView tv = (TextView) param.thisObject;
String text = tv.getText().toString();
tv.setText(text + "🍖");
tv.setTextColor(Color.RED);
if(text!=null&&text.length()>0){
char c = text.charAt(text.length()-1);
if((c&1)!=0){
tv.setText(text+"🍭");
tv.setTextColor(Color.GREEN);
}
}
}
});
}
}添加assets/xposed_init文本文件,在文件中添加你的完整类名,比如我的是
1
com.example.redclocknew.RedClock
工具栏build->build apk(s)
找到对应的apk,使用
1
adb install 文件名
进行安装
重启手机,愉快体验
自定义Xposed模块
根据Xposed实现原理,大概的替换思路有了:找到要hook的方法,然后利用xposedhook该方法并且实施自己要做的动作。
找源码有两种方式,反编译和阅读源码(如果有)
相关资料
下载android源码 or here
获取系统中指定App安装包的方法
获取栈顶activity(当前界面所属activity)
1
2
3adb shell dumpsys window | findstr mCurrentFocus
# or
adb shell dumpsys activity | findstr mFucusedActivity获取app文件安装路径
1
adb shell pm path com.test
- /system/app rom附带软件
- /system/priv-app 手机厂商定制软件
- /data/app 用户安装软件
使用pull命令获取应用
1
adb pull path_to_apk path_to_store
使用push命令可以存储应用
1
adb push path_to_file path_on_phone
找到可以修改的点和相关函数,注意xposed只能hook函数。
使用下面的代码确定相关app是否存在
1 | public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable { |
使用findAndHook方法hook方法→_→
1 | package de.robv.android.xposed.mods.tutorial; |
参考资料
[1] Xposed turtorial