整理Android XposedHook使用中的一些问题
0x00 Xposed安装
网上有很多Xposed安装教程,下面给出我的nexus5真机中系统为Android4.4.4中的安装教程和资源:
https://download.csdn.net/download/wenrennaoda/10733892
网上也有很多类似的教程和资源,这里不再赘述。
0x01 Xposed的配置与demo实现
作者rovo89提供了非常详细的使用方法及其原理简要介绍:
https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
下面这篇文章基本重现了使用方法:
https://www.52pojie.cn/thread-738254-1-1.html
0x02 常用Xposedhook API介绍
Xposed框架提供的API都是静态函数,直接通过类调用函数即可。
一、APP过滤
如Demo中所示模块入口:public interface IXposedHookLoadPackage extends IXposedMod 用于hook应用的代码,自定义的类实现该类并重载 handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam)方法,在内部进行一系列的Hook操作。参数XC_LoadPackage.LoadPackageParam lpparam.packageName:获取包名,用来过滤需要Hook的APP应用。
[code] //过滤包 if (!PACKAGE_NAME.equals(lpparam.packageName)) { return; }
二、定位Hook
1、一般方法
Hook某个函数:通过XposedHelpers.findAndHookMethod静态方法找到类的函数:
Hook类中所有函数名相同的重载函数:XposedBridge.hookAllMethods
2、构造函数
Hook某个构造函数:XposedHelpers.findAndHookConstructor
Hook类中所有构造函数:XposedBridge.hookAllConstructors
若要改变static区域代码中设置的变量值,可Hook构造函数在函数结尾通过反射进行重新设置
三、寻找自定义类型
hook定位函数时参数列表类型经常会遇到APP自定义的类,则需要获取这些类型。通过获取类加载器调用反射函数获取即可。
四、Hook代码实现
在二中的回调中重载下述方法进行代码插桩:
protected void beforeHookedMethod(MethodHookParam param) 在函数开头执行
protected void afterHookedMethod(MethodHookParam param) 在函数结尾执行
参数param有以下用法:
[code]param.args[i];//获取第i个参数 param.setResult(value);//设置返回值 param.getResult(value);//获取返回值 param.thisObject//获取本类对象实例
0x03 找不到类(ClassNotFoundError)的解决方案
如果仅使用上述Demo中所述的方法进行Hook类函数,在很多稍微大点的APK中经常会出现如下错误:
[code]de.robv.android.xposed.XposedHelpers$ClassNotFoundError: java.lang.ClassNotFoundException: XXX.XXX.XXX
发生这种错误一般是由于下述三个原因引起。
1、类名
确保Hook的类名是否书写正确。
2、多dex
一般稍微大点的APK都是多dex的,可通过解压出的APK文件中看是否存在多dex情形。
多dex情形其实多dex是由于dex的文件格式造成的。在dex文件格式的DexHeader部分描述了整个dex文件的结构,其中包括方法的偏移位置methodIdsoff以及从该位置解析的方法个数methodIdsSize。由于个数是u4类型的也就是uint32_t,所以一个dex只能表示2^32=65536个方法。如下所示:
非虫的dex文件格式图片部分一般大型工程中的方法数量很轻易的就会超过最大表示数量,为了支持超量的方法APK,最好的方法就是将dex分割成Multidex,从而避免单个dex的引用超过的限制 。
而一般handleLoadPackage函数中XC_LoadPackage.LoadPackageParam lpparam参数获取的lpparam.classLoader只能Hook到默认的其中一个dex文件中的类,即APK包中的classes.dex。如果要获取其它dex中的类将失败。针对Mutidex情形使用下述方式进行Hook:
[code]public class HookMain implements IXposedHookLoadPackage{ @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { if (!loadPackageParam.packageName.equals("com.XXX.packageName")) return XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook(){ @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { ClassLoader cl = ((Context) param.args[0]).getClassLoader(); Class<?> hookclass = null; try { hookclass = cl.loadClass("XXX.XXX.ClassName"); } catch (Exception e) { Log.e("MutiDex", "寻找XXX.XXX.ClassName失败", e); return; } Log.e("MutiDex", "寻找XXX.XXX.ClassName成功"); XposedHelpers.findAndHookMethod( hookclass, "methodName",//方法名称 args.class,//参数列表 new XC_MethodHook(){ @Override protected void beforeHookedMethod(MethodHookParam param){ //Hook自定义功能 }) ; } }); } }
原理很简单:每个APK运行在加载完所有dex文件后,就会调用Application.attach方法,并且该方法是final无法被覆盖。其参数就是上下文Context,而Context类getClassloader方法可以获取一个类加载器,该加载器能够获取包中存在的所有类,包括所有dex。
Context.getClassLoader Hook多dex原理
参照文章:https://www.geek-share.com/detail/2695569229.html
3、动态加载
最后一种则是动态加载jar、dex和apk中的类,这些类不在本APK中的dex文件中,所以多dex的上下文Context的类加载器也就找不到。通过hook ClassLoader类的 loadclass方法获取需要的类。示例代码如下:
[code]public class IncomeHook implements IXposedHookLoadPackage { public static final String PACKAGE_NAME = "com.XXX.package"; @Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { //过滤包 if (!PACKAGE_NAME.equals(lpparam.packageName)) { return; } findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { if (param.hasThrowable()) return; String classname = (String) param.args[0]; //步骤1 if (classname.equals("XXX.XXX.XXX")) { //步骤2 Class<?> clazz = (Class<?>) param.getResult();//步骤3 findAndHookMethod(clazz, "methodName", args.class, new XC_MethodHook() {//步骤4 @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable {//步骤5 // TODO:自定义功能 } }); } } }); } }
原理也很简单:APK运行需要通过安卓虚拟机将类加载进内存,使用的方法就是ClassLoader.loadClass。所有类的加载都会经过该函数,只要Hook该函数就可以拿到所有加载进内存中类。该方法注释如下:
loadclass用处
原文出处: https://blog.csdn.net/XXOOYC/article/details/80608197
其中直接使用 loadclass方法就能解决多dex的情形,以后在hook函数中其实直接可以使用loadclass的方法去hook,这样不用考虑太多就能Hook成功了。
0x04 免重启框架
网络上的大神提供了两种免重启方案,一种是改变xposed框架中的源码,另一种是使用动态加载实现免重启的方案。直接依次给出链接。
1、https://bbs.pediy.com/thread-223713.htm
2、https://blog.csdn.net/u011956004/article/details/78612502?utm_source=blogxgwz1
0x05 网络协议分析中常用Hook关键点
若要分析网络协议中的一些字段含义或者加密数据,必须需要定位到具体代码进行分析处理流程。例如:
一个HTTP协议如果想要知道data是如何组织出来或者加密的,则需要定位到具体代码进行分析。一般的做法:
1、从点击事件或发生的功能开始往下跟代码。但是代码复杂、工作效率低不建议。
2、对应Http中若有关键字段,可在反编译的JEB中搜索字符串定位处理代码。但是对于没有特征的或者纯TCP加密的数据则无法查找定位。
但是我们了解到大多数数据会使用一些常用的数据操作API,例如
1、Cipher加密类。很多加解密算法DES、AES、RSA等算法都会调用其中国的Dofinal方法开始加密解密。
2、Base64编码
3、程序中也经常用到输入输出流进行数据传输。例如java.io.OutputStream.write方法可能被用于向http发送流中写数据。InputStream.read会读取数据。
4、一些常用的网络库。例如HttpClient中hook函数org.apache.http.impl.client.AbstractHttpClient.execute函数能够定位到发送接受处
5、DatagramSocket.send函数发送udp数据
6、Hook一些socket
通过Hook这些常用的API,打印数据,如果发现是我们需要的数据,则在该处添加堆栈打印函数,重新hook并运行。最后通过打印出的栈进行代码流程分析,最终得到数据处理方法并还原。
Hook点和你平时关注点有关,你想要分析哪类数据,分析其一般处理特征并Hook这些函数进行分析。目标是形成自己的一套定位Hook工具。并随时进行完善,你将发现定位将会变得越来越容易,直接拿来工具定位数据处理位置。
- 使用android兼容包android-support-v4.jar出现的一些问题
- AIR ANE(本机扩展)使用中的一些问题(Android平台)
- android录音机的一些问题整理
- ANDROID动态加载 使用SO库时要注意的一些问题
- android使用第三方*.so库的一些问题
- android学习好的文章及一些问题的解决方法书签整理
- android学习-----使用TabLayout实现Tab选项卡以及遇到的一些问题(一)
- 涉及到android遇到的一些问题整理
- android中遇到的一些问题整理--不断更新中
- Android开发-- 使用ADT23 的一些问题
- androidannotations使用时的一些问题的记录以及获取签名的MD5
- Android DatePicker使用遇到了一些问题
- android ListView在使用中碰得一些问题的解决办法
- 解决爱加密加固之后使用xposed hook的时候log打印不出来的问题
- 解决爱加密加固之后使用xposed hook的时候log打印不出来的问题
- Android使用NDK开发项目时的一些问题
- Android使用NDK开发项目时的一些问题
- 关于Android stdio使用的一些小问题的解决方法
- Android gridview 使用的一些小问题
- Android应用中使用Fragment组件的一些问题及解决方案总结