Hook初解

作者: 合拍v | 来源:发表于2021-08-24 16:51 被阅读0次

     Hook的核心理论无非是两个:反射和动态代理。简而言之,就是要把目标对象替换成我们想要的东西。
     通过反射可以获取一个类中的方法和变量。获取到的方法可以执行,并且得到返回值;获取到的变量可以对其赋值。如果方法或者变量被设置为private,在处理前需要先修改其访问权限。下面为个人理解的反射代码实现:

        // 获取指定类中的方法
        Method method = 类.class.getDeclaredMethod("方法名");
        // 打开访问权限
        method.setAccessible(true);
        // 执行此方法,并且将对象传入;因为方法需要被对象调用
        Object object = method.invoke(类对象);
        // 获取类中的变量
        Class<?> class = Class.forName("包名+类名");
        // 根据变量名取到变量
        Field field = class.getDeclaredField("变量名");
        // 打开访问权限
        field.setAccessible(true);
    

    所以,Hook的步骤如下:

    1. 确定Hook对象
    2. 找到Hook对象的持有者
    3. 定义代理类
    4. 替换掉要hook的对象

    先举个没有啥用的🌰。在MainActivity中有一个imageView,虽然可以直接修改,但是现在我们就是要用Hook的方式修改它,看看接下来怎么做。


    image.png
    1. 确定Hook对象
      对象自然是imageView
    2. 找到Hook对象的持有者
      MainActivity就是持有者
    3. 定义代理类
      代理类的作用根据实际情况去写,现在就是要在设置Bitmap时输出Bitmap的大小,实现如下。
    public class HookedImageView extends ImageView {
    
        public HookedImageView(Context context) {
          super(context);
        }
    
        public HookedImageView(Context context, @Nullable AttributeSet attrs) {
          super(context, attrs);
        }
    
        public HookedImageView(Context context, @Nullable AttributeSet attrs,
            int defStyleAttr) {
          super(context, attrs, defStyleAttr);
        }
    
        @Override
        public void setImageBitmap(Bitmap bm) {
          super.setImageBitmap(bm);
          if (bm != null) {
            Log.d(TAG, "setImageBitmap: " + bm.getByteCount());
          }
        }
      }
    
    1. 替换掉要hook的对象
      现在需要写一个hook函数替换对象,为了方便直接就把这个方法写在MainActivity中了,这时是可以直接拿到持有者即此Activity,所以不需要通过反射的方式获取。所以方法实现中只通过反射拿到了类中的变量并进行了替换。
    private void hook(Activity activity) {
        try {
          Class<?> listnerInfoClz = Class.forName("com.ke.demo.MainActivity");
          Field field = listnerInfoClz.getDeclaredField("imageView");
          field.setAccessible(true);
          HookedImageView proxy = new HookedImageView(activity);
          field.set(activity, proxy);
        } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
          e.printStackTrace();
        }
      }
    

    最后打开这个页面,使用 setImageBitmap设置图片后就看到了如下日志。
    需要注意的是替换对象一定要在对象初始化之后,并且在自定义方法前。

    image.png

    https://blog.csdn.net/gdutxiaoxu/article/details/81459830

    相关文章

      网友评论

        本文标题:Hook初解

        本文链接:https://www.haomeiwen.com/subject/uthmbltx.html