805 words
4 minutes
Xposed模块动态作用域

Xposed模块动态申请作用域#

0x00 前言#

最近在做一个小项目,前期的想法是使用xposed进行注入,列出app清单,让用户选择要注入的进程,这里需要勾选才能实现注入(依赖xposed的注入),所以需要运行时动态申请作用域,但是网上搜了一圈都没找到相关的内容,这里感谢我Flash(Layout Inspect作者,Layout Inspect是很不错的插件,没用过的可以试试)哥给了我解决方案

0x01 解决方案#

使用Xposed Api100即可,之前的项目使用的都是Xposed Api82,用的一直没问题,所以一直没换

0x02 环境配置#

0x021 相关库#

xposedApi100

xposedService

modernExample

第一个是api,第二个是service,第三个是官方给的例子

0x022 使用方法#

在使用之前,需要先把上述两个库编译AAR文件,需要JDK21环境,安装完JDK21记得去设置 -> Gradle -> JDK设置成对应版本,然后直接用gradlew命令构建一下即可

上面两个项目会得到三个.aar文件,把他们分别导入到项目里即可,需要注意的是,xposedApi100编译出的aar文件需要用compileOnly引入,剩余的要用implementation引入,就像这样

dependencies {
compileOnly files('libs/api-100.aar') // xposed 100
implementation files('libs/interface-100.aar') // xposed 100 interface
implementation files('libs/service-100-1.0.0.aar') // xposed 100 service
}

这样之后你就可以使用xposedApi100啦,我导入api100的目的是为了实现动态申请作用域,这个东西官方给的例子里写的还是比较清除的,直接抄过来就行

XposedServiceHelper.registerListener(new XposedServiceHelper.OnServiceListener() {
@Override
public void onServiceBind(XposedService service) {
mService = service;
runOnUiThread(() -> {
Toast.makeText(MainActivity.this, "LSPosed服务已连接", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onServiceDied(XposedService service) {
mService = null;
Toast.makeText(MainActivity.this, "服务器断开", Toast.LENGTH_SHORT).show();
}
});
if (mService == null) {
Toast.makeText(this, "LSPosed服务未连接", Toast.LENGTH_SHORT).show();
return;
}
// 请求作用域
mService.requestScope("com.yuuki.unidbg_test", new XposedService.OnScopeEventListener() {
@Override
public void onScopeRequestPrompted(String packageName) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "请求已弹出: " + packageName, Toast.LENGTH_SHORT).show());
}
@Override
public void onScopeRequestApproved(String packageName) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "已批准: " + packageName, Toast.LENGTH_SHORT).show());
}
@Override
public void onScopeRequestDenied(String packageName) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "已拒绝: " + packageName, Toast.LENGTH_SHORT).show());
}
@Override
public void onScopeRequestFailed(String packageName, String message) {
runOnUiThread(() -> Toast.makeText(MainActivity.this, "失败: " + message, Toast.LENGTH_SHORT).show());
}
});

但是如果想让Lsposed管理器知道这个app实际上是个模块,那还是需要做额外的配置的,api100的话,需要我们在项目里创建main/resources/META-INF/xposed/文件夹,然后在里面常见三个文件

  1. java_init.list

    相当于原来的assets/xposed_init,内容是一样的

  2. module.prop

    相当于原本AndroidManifest.xml里的标签,内容长这样

    minApiVersion=100
    targetApiVersion=100
    staticScope=true
  3. scope.list

    相当于原本的res/values/arrays,是作用域列表

然后配置完就搞定了,description的话,现在改成android:description标签了,去清单里配置一下就行

这样之后就全部搞定啦~

0x023 但是#

但是我老版本api用习惯了,所以我只想用新版的api用于动态申请作用域,hook的代码还是想使用老版本(api82)写,那咋办呢?

其实只两个环境叠加起来就可以了,api82的使用方法网上都有,api100的刚刚说过了,都配置在一起就行了,这样就可以用82的hookApi,还能动态申请作用域了

0x03 小结#

我要继续学习了

Xposed模块动态作用域
https://yuuki.cool/posts/dynamicscope/
Author
Yuuki
Published at
2025-12-18
License
CC BY-NC-SA 4.0