本文为看雪论坛优秀文章
看雪论坛作者ID:珍惜Any
Hi!大家好,我是珍惜。
给大家简单介绍一下,如何用Xposed实现对某个类的替换覆盖。
在不编译源码的情况,直接修改原Class内容。
(之前的这篇帖子,也不错。Xposed实现Native层Hook:Art 模式 实现Xposed Native注入
https://bbs.pediy.com/thread-251171.htm)
当我们在 findClas的时候,其实我们最终都会去dexElements数组里面,去寻找,我们需要的类。
路径为:
ClassLoder.java->
BaseDexClassLoader.java->
DexPathList.java-> dexElements
这个寻找其实是遍历,如下图:
也就是说,我们只需要我们想加载的类放在前面,再通过反射set即可,做到 热修复。
腾讯的Tinker其实大概原理也是这样,阿里的是,动态修改了insns数组,直接修改某个方法的字节码。
这也是热修复。分为冷插拔和热插拔的区分(是否需要二次启动)
后面会详细跟大家说具体原因。
下面给大家简单复现一下流程:
很简单。当我点按钮的时候,会进行Testclass的获取会进行遍历elements数组,生成这个类。
调用方法以后,肯定会崩掉。这种情况xposed无论如何Hook都很无力(可以Try)。
我们先首先生成一份正确的 dex 如下图:
可以看到在Test函数里面我已经将原来的异常换成Log打印。
xposed模块里面写先Hook attach拿到对方进程的classloader。
在 attach 执行完毕。里面进行修复,因为这个时候dex已经加载完毕了,直接进行修复即可。
(需要提前开启,被修复App的sd卡读写权限。因为我是用对方的进程去读写 sd卡内容的。)
在HookMain里面进行class的初始化,拿到每个classloader里面的element数组。
然后进行合并,详细功能可以看一下注释:
将生成的dex放到 sd/dex/目录下面:
先拿到加载正确类的classloader自己手动创建:
然后,开始拿到正确的classloader。传入对应的 classloader,通过反射的方式拿到element数组。
拿到两个classloader里面的elements数组,然后进行合并。
当我们把合并以后的classloader里面的element数组在set原来的回去。
参数1是合并以后的 element数组。
参数2是合并之前两个数组的大小。(用于判断是否合并成功 )
激活xposed模块并运行。
可以看到替换是成功的,壳子的不落地加载也是这个原理。
如果 xposed取消钩子,可以看得到,程序还是老样子进行崩溃了。
这块有几个坑,跟大家说一下。
问题1:为什么我不用一个静态方法作为 Test?如下图:
如果这个方法是静态的,在MianActivity的时候,就会进行初始化,这个时候,这个类已经被初始化了。
在此调用的时候他就不会去findclass,也就不会遍历element数组,所以会修复无效。因为,我现在每一次,都是 new一个新的对象,这个对象是未经过初始化的,所以需要遍历,element数组拿到class这个时候可以完成热修复。
问题2:热修复的方式为什么分为冷插拔和热插拔?Tinker就属于冷插拔。就是在错误的类element数组前面加入我们自己需要的正确的类,这种方式需要App重启才可以。
阿里的就属于热插拔,他是直接修改,错误方法的字节码Insns数组,可以直接修改对应的Bug这种不需要重启。
问题3:这个xposed修复的作用是什么?他有什么价值?
我可以在不编译源码的情况直接修改源码里面的内容,随时可关,随时可开。
只需要拿到系统的classloader,再加载自己修改过以后的内容,如上述操作 即可。具体项目如下:https://github.com/w296488320/XposedTinker
- End -
看雪ID:珍惜Any
https://bbs.pediy.com/user-819934.htm
*本文由看雪论坛 珍惜Any 原创,转载请注明来自看雪社区
推荐文章++++
* Windows内存堆内容整理总结
* 格式化字符串漏洞
* 安卓源码+内核修改编译(修改内核调试标志绕过反调试)
* GlobeImposter3.0 勒索分析
* 恶意样本检测——Mathematics Malware Detected Tools
公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com