反射+代理实现 API Hook(以 ActivityManager 为例)

news/2024/5/19 6:39:49 标签: 反射, 代理, hook, ActivityManager, InvocationHandler

最近看Android招聘信息,发现一个自己不太会的点 hook 机制,查了一下资料,现在整理一下。特别感谢acxingyun同学提供了详细的姿势。点击地址

什么是 Hook

hook翻译过来是钩子的意思。 目的就是在事件传送到终点前截获并监控事件的传输,像个钩子钩上事件一样,并且能够在钩上事件时,处理一些自己特定的事件。而代理模式正好可以做到这种效果。

代理对象

了解了hook的目的,下面就是怎样勾上整个事件,来监测事件的每一步。
拿 Activity 来举例,Activity 的相关的启动方法在IActivityManager接口里面都已经定义好了,但正常情况下我们无法获取相关的对象的信息,更无法修改,所以在这里我们要借用反射来获取到相应的 Class 对象,将IActivityManager的实例替换为我们自己的代理对象,在代理对象里面去做我们想做的事情。
无图无真相。上图
在这里插入图片描述

ActivityManagerNative的实例持有一个Singleton<IActivityManager>类型的对象 gDefault,gDefault持有IActivityManager的实例mInstance,
正常状态持有的mInstance实例 我们通过 Proxy.newProxyInstance()做出一个代理对象来,再利用反射机制重新给 gDefault对象,这样我们就能在InvocationHandler中监听整个事件并处理。

具体实现

public class APIHook {

    /**
     * ActivityManager 替换为代理
     * @throws ClassNotFoundException
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public void hookAM() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class<?> amnClass = Class.forName("android.app.ActivityManagerNative");
        //获取单例对象 Singleton<IActivityManager> ,变量名 gDefault 私有
        Field gDefaultField = amnClass.getDeclaredField("gDefault");
        //禁止JAVA 进行语言访问检查,private 等修饰的就可以访问操作了
        gDefaultField.setAccessible(true);
        //If the underlying field is a static field, the obj argument is ignored; it may be null.
        //静态属性,直接传入 Null。获取ActivityManagerNative 中的 gDefault
        Object gDefault = gDefaultField.get(null);

        Class<?> singletonClass = Class.forName("android.util.Singleton");
        Field mInstanceField = singletonClass.getDeclaredField("mInstance");
        mInstanceField.setAccessible(true);

        //调用 Singleton 的 get方法 取出 instance 对象
        //instance 对象即 ActivityManager
        Object instance = mInstanceField.get(gDefault);

        //创建代理 handler
        ActivityManagerHandler handler = new ActivityManagerHandler(instance);
        //反射 IActivityManager接口 Class 文件
        Class<?> amClass = Class.forName("android.app.IActivityManager");
        //创建代理对象
        Object amProxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{amClass}, handler);

        //将gDefault中的 Instance 置换为代理
        mInstanceField.set(gDefault,amProxy);
    }
    /**
     * 代理对象回调
     */
    private class ActivityManagerHandler implements InvocationHandler {
        private Object am;

        public ActivityManagerHandler(Object am) {
            this.am = am;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Log.e("APIHook","正在调用的方法--->"+method.getName());
            return method.invoke(am,args);
        }
    }
}

知识点:对于 private 修饰的变量,我们需要调用Field.setAccessible(true);来禁止 JAVA 语法检查才能给变量赋值哟

这个代码是可以直接用的,把玩时在 Application 的 onCreate 中调用

new APIHook().hookAM();

就写到这里啦,权当又复习了一遍代理反射,大家一起加油啊


http://www.niftyadmin.cn/n/1568396.html

相关文章

Android动态生成UI

android 动态创建布局及关于LayoutParams 解释 其实这个LayoutParams类是用于child view&#xff08;子视图&#xff09; 向 parent view&#xff08;父视图&#xff09;传达自己的意愿的一个东西&#xff08;孩子想变成什么样向其父亲说明&#xff09;其实子视图父视图可以简单…

排序算法之选择排序(Java 版本)

选择排序 最近在看《算法导论》&#xff0c;半路出家的我看的着实头痛&#xff0c;先记录下心得&#xff0c;难得的好书。 PS&#xff1a;看不懂的书才是好书? 基础内容 描述&#xff1a;选择排序是每一次从待排序的数据元素中选出最小&#xff08;或最大&#xff09;的一个元…

android使用socket使底层和framework通信

一般的native和framework的通信是通过jni&#xff0c;但是这一般只是framework调用native&#xff0c;native如果有消息要怎样通知上层呢&#xff1f;android中GSP模块提供一种解决思路&#xff0c;但是实现有些复杂&#xff0c;这里介绍一种使用socket通信的方法可以使native和…

排序算法之归并排序(Java 版本)

排序算法之归并排序 归并排序是分治策略的应用之一&#xff0c;分而治之。 时间复杂度为 O(n log n) 归并排序的思想是:将队列拆分为子队列直到不可分,再将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列有序&#xff0c;再使子序列段间有序。…

Android监听apk安装、卸载、替换的事件类型

Android监听apk安装、卸载、替换的事件类型如下&#xff1a; android.intent.action.PACKAGE_ADDED android.intent.action.PACKAGE_REMOVED android.intent.action.PACKAGE_REPLACED

算法之分治策略与应用

归并排序中我们利用了分治策略&#xff0c;在分治策略中&#xff0c;我们递归求解一个问题&#xff0c;在每层递归中应用如下三个步骤&#xff1a; 分解&#xff1a;将问题划分为一些子问题&#xff0c;子问题的形式与原问题一样&#xff0c;只是规模更小。解决&#xff1a;递归…

android service介绍

很简单一个例子&#xff1a; Android开发中&#xff0c;当需要创建在后台运行的程序的时候&#xff0c;就要使用到Service。Service 可以分为有无限生命和有限生命两种。特别需要注意的是Service跟Activities是不同的&#xff08;简单来说可以理解为后台与前台的区别&#xff…

排序算法之堆排序(Java 版本)

堆排序&#xff0c;使用一种称为堆的数据结构来进行信息管理。堆不仅用在堆排序中&#xff0c;它还可以构造一个有效的优先队列。时间复杂度O(nlogn) 堆 &#xff08;二叉&#xff09;堆是一个数组&#xff0c;可以被看成一个近似的完全二叉树。书上的每个节点对应数组中的一个…