您的位置:首页 > 移动开发 > Android开发

整理Android XposedHook使用中的一些问题

2019-02-14 20:08 1196 查看

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工具。并随时进行完善,你将发现定位将会变得越来越容易,直接拿来工具定位数据处理位置。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: