Xposed 模块开发
前言
是的,我又写前言了。
什么是Xposed
开发者(项目仓库也在主页):https://github.com/rovo89
来自维基百科:
Xposed(也被称作Xposed框架、XP框架、Xposed framework),是一个运行于Android操作系统的钩子框架。其通过替换Android系统的关键文件,可以拦截几乎所有Java函数的调用,并允许通过Xposed模块中的自定义代码更改调用这些函数时的行为。因此,Xposed常被用来修改Android系统和应用程序的功能。
Xposed Installer是Xposed框架的官方安装器,可以在拥有root)权限的设备上安装Xposed框架。Xposed Installer也提供模块的下载、管理、日志显示等功能。
工作原理
Xposed框架主要通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。与采取传统的Inhook方式相比,Xposed在开机的时候完成对所有的Hook Function的劫持,在原Function执行的前后加上自定义代码。
为什么需要这么做呢?
Android基于Linux,第一个启动的进程自然是init进程,该进程会启动所有Android进程的父进程——Zygote(孵化)进程,该进程的启动配置在 /init.rc脚本中,而Zygote进程对应的执行文件是/system/bin/app_process, 该文件完成类库的加载以及一些函数的调用工作。在Zygote进程创建后, 再fork出SystemServer进程和其他进程。Xposed Framework,就是用自己实现的app_process替换掉了系统原本 提供的app_process,加载一个额外的jar包,然后入口从原来的: com.android.internal.osZygoteInit.main()被替换成了: de.robv.android.xposed.XposedBridge.main(),
然后创建的Zygote进程就变成Hook的Zygote进程了,而后面Fork出来的进程 也是被Hook过的。
这个Jar包在: /data/data/de.rbov.android.xposed.installer/bin/XposedBridge.jar 目录下。
通过原理我们可以看出,要使用Xposed框架,那么手机必须要拥有最高权限(就是root权限),当然现在还出现了VirtualXposed,这个框架的话就相当于给你的手机开了一个平行空间,这个空间和你的手机系统一样,就相当于一个副本,所以当你在这个空间使用xposed的话,就不需要root,但是在这个空间你需要重新安装你想修改的程序,因为它刚创建出来的时候是什么都没有的,也因此你在这个空间修改并不会影响到你的手机本来的应用,就相当于双开应用。
值得注意的是,既然给出了最高权限,那么别人就可以做很多坏事了,比如获取你的账号密码,还有一些私密的文件,因此对于别人写的Xposed模块可以看看他是不是开源的再决定用不用,如果不是开源的,建议不要使用。当然如果不想承担这么大的风险又不嫌麻烦的话,可以使用上面介绍的virtualXposed框架。
————————————————
来自:https://blog.csdn.net/baidu_38661691/article/details/95977655
官方教程
WIKI:https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
中文翻译:https://vbill.github.io/2015/02/10/xposed-1/
Xposed Framework API :https://api.xposed.info/reference/packages.html
开发环境:
Windows10
Android studio 4.0.1
夜神模拟器:6.6.1.7
开始
声明这是一个Xposed模块
AndroidManifest.xml
<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="OA助手" />
<meta-data
android:name="xposedminversion"
android:value="51" />
</application>
声明启动类
src/main/assets/xposed_init
top.jsls9.oa.HookMain
需要引入的包
compileOnly("de.robv.android.xposed:api:82")
具体编写hook代码
...
应用反编译
反编译网上教程很多,把dex转成jar,查看jar代码
反编译后的代码都是混肴的怎么办?
答:hook时不需要源代码的类名、方法名,用你反编译后的即可。
不过需要注意,比如b.java 里除了本身还有一个b class。
jdk-gui查看jar时会有这种情况,而载MT管理器
上会显示b$b
这样的,要以b&b
如我在hook一个class时是下方这样的写法:
//点击结算按钮
try {
hookclass = mAppClassLoader.loadClass("com.huluxia.framework.base.widget.dialog.b$a$1");
} catch (Exception e) {
XposedBridge.log("com.huluxia.framework.base.widget.dialog.b$a$1报错");
return;
}
XposedBridge.log("寻找com.huluxia.framework.base.widget.dialog.b$a$1成功");
XposedHelpers.findAndHookMethod(hookclass,
"onClick",
//int.class,
View.class,
new XC_MethodHook(){
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
TextView view = null;
XposedBridge.log("=====hook方法前=====");
if(param != null && param.args.length > 0){
//XposedBridge.log("查看参数");
for (int i = 0; i < param.args.length; i++) {
//XposedBridge.log("arg:" + param.args[i]);
//参数类型明明是TextVie偏偏转不成View,奇奇怪怪的
if(param.args[i] instanceof TextView){
view = (TextView) param.args[i];
if(UI.OA_BUTTON.equals(view.getText())){
settlement(String.valueOf(postId), context);
}
//Toast.makeText(context, "点击了一下,postId"+postId, Toast.LENGTH_SHORT).show();
}
}
XposedBridge.log("========拦截前完毕=====");
}
}
});
怎么定位hook的点?
答:
- 需要hook的app至少自己是熟悉大致功能的,方便查看反编译后的代码;可以通过一些app页面上的关键字、抓到到的接口去搜索,逐步去找到类、方法等。当然,需要有一些开发上的封装,或者某些Android的原理(我不懂Android,只是会写点Java,在这上面吃了大亏)。
- 暴力遍历,通过一些特定的方法,去遍历输出你操作时的类、方法、参数。总不能全部输出到Xposed上,移动设备要连接在电脑上的,Android studio可以查看起来。当然你能通过1来定位到大致位置的话遍历起来更方便一些。这个方法还是需要懂一些Android,不然就去搜索,还是有一些的。
上面那个代码片段就是我常用的(我本来也就刚写了几天,写了个demo,所以也就这一个)
- 使用DDMS录制行为轨迹
DDMS的使用具体可以百度,连接上设备不能查看进程可以参考最下放的链接。
这个方式很好用的,你肯定知道在怎么操作app的时候要修改app什么。所以准备好你要的操作,使用DDMS录制轨迹,查看轨迹,比如你点击了个按钮,那你就在轨迹里搜索click
。
遇到的问题以及解决方案
1、Android studio打包的时候编译不通过,这个我觉得也就我自己会遇到这个问题了,只是编码(jdk1.8的路径以及gradle奇奇怪怪的版本号)的问题,在下方选择GBK。
2、DDMS不显示进程:https://www.cnblogs.com/hally/p/12659508.html
3、DDMS启动的路径(Android studio上找不到这个Tools了):https://blog.csdn.net/qq_42023080/article/details/105842271
4、对我帮助最大的开发项目(demo架子是参考的这个项目):https://github.com/dreamncn/Qianji_auto
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。