作者:bigfog

原文链接:www.bigfog.info

Hook简介

Hook英文翻译即为钩子。windows下的Hook是一种消息处理机制。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,即钩子函数先得到控制权,这时钩子函数就可以对消息进行加工处理。它其实是一个处理消息的程序段。当然在安卓系统中也有Hook技术,和windows下的Hook类似,也是在事件传送到终点前截获并监控事件的传输,并对所钩上的事件作出相应的处理。

xposed框架

原理

Xposed框架是一款对安卓平台的HOOK框架,可以在不修改APK的情况下修改程序的框架服务。通过替换/system/bin/app_process程序控制Zygote进程,从而使app_process在启动过程中加载XposedBridge.jar这个jar包。Zygote进程在启动过程中,会创建一个Dalvik虚拟机实例,还会把java运行时库加载到进程中来,以及注册一些Android核心类的JNI方法来前面创建的Dalvik虚拟机实例中去,应用程序进程会与Zygote一起共享Java运行时库。这就是XposedBridge.jar包可以加载的原因。

安装

Xposed框架本质只是一个apk应用,可安装到手机。相应模块(Hook代码)就需要我们去编写,模块也是apk文件。

  1. 手机必须是具有Root权限的。Root是有一定风险的。所以这里使用的是模拟器。
  2. 实验设备:夜神模拟器+Android4.4.2+XposedInstall.apk(v2.7)+XposedBridge.jar-54。
  3. Xposed框架安装效果如下:
    效果图-1

Xposed使用示例

需要被Hook的程序

程序界面如下

界面-2

源代码如下:

源代码-3

源代码逻辑很简单,输入一段字符串,然后在compare函数中比较。根据返回值判断输入是否正确。因为这只是做一个示例,compare函数中直接用了equals函数来比较。在代码编程中这是很愚蠢的做法,强烈不建议这种写法。

如果想让程序返回正确的值,只要将compare的返回值为true即可。我们这里Hook的就是compare函数,不管输入任意字符,都会显示返回成功。

Hook关键函数介绍

IXposedHookLoadPackage类:加载回调接口,在Xposed入口类继承,实现handleLoadPackage方法。

handleLoadPackage:这个方法用于在加载应用程序的包的时候执行用户的操作。
findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object… parameterTypesAndCallback) hook一个类中的方法
参数:
className: 要hook的方法的所在类
classloader: 要hook的包的classLoader,一般都写loadPackageParam.classLoader
methodName: 要hook的方法
parameterTypesAndCallback: 方法的参数和监听器。

导入lib文件

新建安卓项目,这个应该很简单。需要导入jar文件-XposedBridgeApi-54.jar。

结构图-4

新建文件夹,命名为lib,然后将XposedBridgeApi-54.jar复制过来。右键Add as library。这样就能看到里面的类了。

结构图-5

然后修改build.gradle文件,将compile改为provided。

结构图-6

AndroidManifest.xml文件修改

需要在配置文件中添加一些属性。

<application>
        <meta-data android:name="xposedmodule" android:value="true"/>
        <meta-data android:name="xposeddescription" android:value="模块第一次测试"/>
        <meta-data android:name="xposedminversion" android:value="54"/>
</application>

xposedmodule:判断是否是xposed模块,xposed根据这个来判断是否是模块。

xposeddescription:模块描述,会显示在xposed框架模块列表中。
xposedminversion:最低xposed版本号,lib文件名可知。

入口类编写

创建一个类,实现IXposedHookLoadPackage借口,重写handLoadPackage方法,这里创建了一个xposedmain类。

public class xposedmain implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam Param) throws Throwable {
        if(Param.packageName.equals("com.example.zzwbi.check"))//匹配包名
        {
            XposedBridge.log("Loaded APP:"+Param.packageName);//XposedBridge.log相当于日志输出。
            try {
                findAndHookMethod("com.example.zzwbi.check.MainActivity", Param.classLoader, "compare", String.class, new get_True());
                                  //类名,一般都写Param.classLoader,方法名,参数...,hook的方法
            } catch (Exception e) {
                XposedBridge.log(e);
            }
        }
    }
}
class get_True extends XC_MethodHook {
    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
        XposedBridge.log("beforeHookedMethod userName:" + param.args[0]);
        //hook前的一些操作
    }
    protected void afterHookedMethod(XC_MethodHook.MethodHookParam args) throws Throwable {
        //hook后的一些操作
        args.setResult(true);
        XposedBridge.log("使返回值为true");
    }
}

设置启动入口

新建assets文件夹,在里面新建文件名为xposed_init,写入你自己创建的xposedmain类包名。

启动入口-7

包名+类名

示意图-8

安装激活插件

将apk安装到模拟器上,重启后即可看到插件效果。

启用插件-9

下面看下hook效果

Hook成功-10

总结

这只是对于Xposed学习的一次小尝试。对于其Hook还有很多地方要学习。例如静态field变量,隐藏函数,内部类,匿名内部类,构造函数的Hook都要继续研究。

参考链接:

http://blog.csdn.net/jiabailong/article/details/52368002
http://blog.csdn.net/wxyyxc1992/article/details/17320911
http://www.freebuf.com/articles/terminal/114910.html