Android Hook

什么是Hook

拦截事件并监控事件的传输。

常用的Hook框架

  • 要root权限,直接Hook系统,可以干掉所有的App
  • 免root权限,但是只能Hook自身,对系统其他App无能为力

常见Hook方案

Xposed

通过替换/system/bin/app_process程序控制Zygote,在开机时完成所有的劫持,在原执行前后加上自定义代码。(支持Java代码)

Cydia Substrate

一个代码修改平台,可以修改任何进程的代码。(支持Java、C/C++)

Legend

免Root的一个Apk Hook框架。直接构造出新旧方法对应的虚拟机数据结构,然后替换信息写到内存中。

使用Java反射实现API Hook

通过对Android平台的虚拟机注入和Java反射的方式,来改变Android虚拟机调用函数的方式(ClassLoader),从而达到Java函数重定向的目的。

使用反射Hook setOnClickListener

新建一个OnClickListener类,传入原本的OnClickListener,通过代理,在原先的onCLick之前和之后,可执行相关的代码。 然后,通过反射,替换View的setOnClickListener中的ListenerInfo 。

class HookedOnClickListener implements View.OnClickListener {
    private View.OnClickListener origin;
    HookedOnClickListener(View.OnClickListener origin) {
        this.origin = origin;
    }
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "hook click", Toast.LENGTH_SHORT).show();
        Log.i(TAG,"Before click, do what you want to to.");
        if (origin != null) {
            origin.onClick(v);
        }
        Log.i(TAG,"After click, do what you want to to.");
    }
}

使用Hook拦截应用内的通知

可以通过替换NotificationManager的sService这个静态变量,并使用动态代理,来拦截不需要的通知(有些SDK会自己发通知)。

动态代理部分代码如下:

new InvocationHandler() {
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {         
        if (args != null && args.length > 0) {
            for (Object arg : args) {
              log.debug("type:{}, arg:{}", arg != null ? arg.getClass() : null, arg);
            }
        }
        // 操作交由 sService 处理,不拦截通知
        // return method.invoke(sService, args);
        // 拦截通知,什么也不做
        return null;
        // 或者是根据通知的 Tag 和 ID 进行筛选
    }
});

总结

Hook 的选择点:静态变量和单例,因为一旦创建对象,它们不容易变化,非常容易定位。
Hook 过程:
寻找 Hook 点,原则是静态变量或者单例对象,尽量 Hook public 的对象和方法。
选择合适的代理方式,如果是接口可以用动态代理。
偷梁换柱——用代理对象替换原始对象。
Android 的 API 版本比较多,方法和类可能不一样,所以要做好 API 的兼容工作。

其他

详见 https://www.jianshu.com/p/4f6d20076922

源码

猜你喜欢

转载自blog.csdn.net/EthanCo/article/details/80032323