Android Hook 一 Hook CloseGuard

3 篇文章 0 订阅
2 篇文章 0 订阅

一、抛出问题

在上一篇 dalvik.system.CloseGuard 介绍了CloseGuard的原理和作用,并在文中提到

APP端可以利用Hook REPORTER 在来实现客制化的上报提示信息

本章通过代码来学一下怎样Hook这个REPORTER来定制上报信息功能。

二、案例分析

直接上代码:

package com.peterzhang.androidhookdemo;

import android.database.CursorWindow;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private volatile static Object sOriginalReporter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("HookCloseGuard");
    }

    private void testAllocate(){
        CursorWindow cursorWindow = new CursorWindow("test");
    }

    public void allocate(View view){
        testAllocate();
    }

    public void hook(View view){
        tryHook();
    }

    private boolean tryHook() {
        try {
            Class<?> closeGuardCls = Class.forName("dalvik.system.CloseGuard");
            Class<?> closeGuardReporterCls = Class.forName("dalvik.system.CloseGuard$Reporter");
            Field fieldREPORTER = closeGuardCls.getDeclaredField("REPORTER");
            Field fieldENABLED = closeGuardCls.getDeclaredField("ENABLED");
            fieldREPORTER.setAccessible(true);
            fieldENABLED.setAccessible(true);
            sOriginalReporter = fieldREPORTER.get(null);
            fieldENABLED.set(null, true);
            ClassLoader classLoader = closeGuardReporterCls.getClassLoader();
            if (classLoader == null) {
                return false;
            }
            fieldREPORTER.set(null, Proxy.newProxyInstance(classLoader,
                    new Class<?>[]{closeGuardReporterCls},
                    new IOCloseLeakDetector(sOriginalReporter)));
            fieldREPORTER.setAccessible(false);
            return true;
        } catch (Throwable e) {
            Log.e(TAG, "tryHook exp=%s", e);
        }

        return false;
    }

    class IOCloseLeakDetector implements InvocationHandler {
        private final Object originalReporter;
        public IOCloseLeakDetector(Object originalReporter) {
            this.originalReporter = originalReporter;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if (method.getName().equals("report")) {
                Log.d(TAG,"invoke hook method");
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"invoke hook method",Toast.LENGTH_LONG).show();
                    }
                });
                return null;
            }
            return method.invoke(originalReporter, args);
        }
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG,"onDestroy");
        super.onDestroy();
    }
}

说明:

  1. 界面上两个按钮,分别是hook和allocate。hook的作用是通过反射修改App运行环境中CloseGuard实例中的REPORTER对象,allocate是在方法体中创建一个局部变量,类型是CursorWindow,为什么用CursorWindow,因为它的源码接入了CloseGuard机制。
  2. 分别点击hook和allocate,然后点返回按键
  3. 等一会会发生gc,触发CloseCuard中的warnIfOpen方法,warnIfOpen方法中又会调用REPORTER的report方法,由于我们预先hook了REPORTER,因此这里会走到IOCloseLeakDetector的invoke方法,这里是通过动态代理实现了一个REPORTER的代理对象。
  4. 弹出Toast提示

四、总结

通过案例学习到了:

  1. 如何通过Hook来定制REPORTER实现自己的上报逻辑
  2. 进一步了解CloseGuard的使用机制

最后附上工程代码

五、参考

Tencent Matrix

dalvik.system.CloseGuard

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值