简介
VirtualXposed可以在非root手机上运行xposed插件。通过xposed插件做到各种操作,如:模拟定位、监听用户行为等。
原理
VirtualXposed 是基于VirtualApp和Epic在非ROOT环境下运行Xposed模块的实现(支持5.0~10.0)
https://github.com/android-hacker/VirtualXposed/blob/vxp/CHINESE.md
VirtualApp 是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。
https://github.com/asLody/VirtualApp
Epic 是一个在虚拟机层面、以 Java Method 为粒度的运行时AOP Hook框架。它可以拦截本进程内部几乎任意的 Java 方法调用,可用于实现 AOP 编程、运行时插桩、性能分析、安全审计等。
https://github.com/tiann/epic/blob/master/README_cn.md
Epic 的实现原理
http://weishu.me/2017/11/23/dexposed-on-art/
下载
32位系统:
由于google play不允许32位应用上架,0.20之后不再支持32位应用
https://github.com/android-hacker/VirtualXposed/releases/download/0.18.2/VirtualXposed_0.18.2.apk
64位系统:
https://github.com/android-hacker/VirtualXposed/releases/download/0.20.3/VirtualXposed_0.20.3.apk
使用
1、安装【VirtualXposed】后打开软件,若出现【图2】的弹窗,点击弹窗外部即可,点击【图3】标记位置可以打开【设置】页面。
2、安装应用:先将插件、测试应用安装到手机上,进入【VirtualXposed】,点击【添加应用】,选择插件、测试应用,点击【安装】。弹窗中选择【VIRTUALXPOSED】
3、激活设备:【图3】页面向上划,即可进入应用列表,点击【Xposed Installer】,进入激活页面。【图8】为激活结果。
4、安装插件:在【设置】页面点击【模块管理】,勾选我们安装的插件,返回后在【设置】页面点击【重启】,如【图11】所示,此时插件已经安装完毕。
5、日志获取:点击【Xposed Installer】,点击左上角按钮,进入侧边栏。点击【日志】,即可看到日志数据。点击页面右上角按钮,可以选择【立即清理日志】清除之前的日志。
然后打开测试软件,再次进入日志页面,出现【图14】内容。获取到了测试包getImei的行为,点击图中按钮可以进行保存。
插件开发
1、新建android工程,并在app的build.gradle中添加依赖。
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'
}
2、在AndroidManifest.xml中添加声明
<meta-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposedminversion"
android:value="54" />
<meta-data
android:name="xposeddescription"
android:value="这是插件的描述,在添加的时候会在插件列表展示出来" />
3、新建java类,实现IXposedHookLoadPackage接口。并重写handleLoadPackage方法。
API:https://api.xposed.info/reference/packages.html
/**
* xposed关键类,实现IXposedHookLoadPackage,在handleLoadPackage中,
* 通过XposedHelpers.findAndHookMethod来hook具体的方法。
*/
public class MethodHook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) {
if (loadPackageParam == null) return;
initPrivacyHook(loadPackageParam);
}
private void initPrivacyHook(XC_LoadPackage.LoadPackageParam lpparam) {
XposedHelpers.findAndHookMethod(
android.telephony.TelephonyManager.class.getName(),
lpparam.classLoader,
"getImei",
new MethodSettle(lpparam.processName, lpparam.packageName));
XposedHelpers.findAndHookMethod(
android.telephony.TelephonyManager.class.getName(),
lpparam.classLoader,
"getImei",
int.class,
new MethodSettle(lpparam.processName, lpparam.packageName));
}
}
通过MethodSettle打印调用方法的堆栈。
public class MethodSettle extends XC_MethodHook {
private final String processName;
private final String packageName;
public MethodSettle(String processName, String packageName) {
this.processName = processName;
this.packageName = packageName;
}
@Override
protected void beforeHookedMethod(MethodHookParam param) {
XposedBridge.log("[" + packageName + "][" + processName + "]" + param.method.getName() + "()");
}
@Override
protected void afterHookedMethod(MethodHookParam param) {
StringBuilder stringBuilder = new StringBuilder("---------------start----------------\n");
Throwable ex = new Throwable();
StackTraceElement[] stackElements = ex.getStackTrace();
for (int i = 0; i < stackElements.length; i++) {
stringBuilder.append("[Dump Stack]")
.append("[").append(i).append("]").append(stackElements[i].getClassName())
.append("->").append(stackElements[i].getFileName())
.append("(").append(stackElements[i].getLineNumber()).append(")")
.append("->").append(stackElements[i].getMethodName())
.append("\n");
}
stringBuilder.append("---------------over----------------\n");
XposedBridge.log(stringBuilder.toString());
}
}
4、在assets目录下新建文件xposed_init,内容为IXposedHookLoadPackage实现类的路径,本文路径为:com.niiiico.xposedplugin.hook.MethodHook
其他
1、部分方法类名和方法名:
2、项目地址:https://github.com/Timey729/XPosedPlugin
3、参考:https://blog.csdn.net/cjs1534717040/article/details/118731361