Hook技术——拦截系统Intent

首先说下什么是 Hook (钩子函数):

钩子函数其实一段程序,在系统的调用中挂载到系统,在没有调用该函数之前,钩子程序先捕获该消息,这样钩子函数先得到控制权,这样钩子函数就可以加工处理该函数的执行从而改变消息的传递。


Hook技术实现的过程:(java层)

1) 找到Hook点

① hook的过程是一个找方法的过程,我们要找到微信怎么登录的,就需要找到微信登录的方法。

② 需要满足的条件 :对象一定是静态

2)找到hook方法执行前的代码



一、 找到拦截系统Intent 的 Hook点

Activity的启动过程 我们了解到,在开启一个Activity的时候,会调用若干的方法,仔细一点我们发现其中有一个

int result = ActivityManagerNative.getDefault()
                                    .startActivity(whoThread,
                                    who.getBasePackageName(),
                                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                                    token, 
                                    target, 
                                    0, 
                                    null, 
                                    options);

在ActivityManagerNative.getDefault() 中返回了一个对象,虽然是一个静态方法,但是我们需要一个静态对象:

static public IActivityManager getDefault() {
        return gDefault.get();
    }

再来看下 gDefault 对象:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

看到 private static final 我们知道这是一个静态的final类型的成员变量,而Singleton是个什么呢?按照字面意思,该类是一个单例类,具体:

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

通过单例的方式来让继承实现其中的create() 方法,返回IActivityManager,但是IActivityManager只是Singleton的成员变量,不过Singleton既然是静态单例,所以也能反射拿到其中的成员。


好了,到此我们就找到了系统的hook点,下面实现:

先还原 gDefault 对象
try {
    // 还原 gDefault() 成员
    Class activityManagerNative = Class.forName("android.app.ActivityManagerNative");
    // 获取到成员变量
    Field gDefault = activityManagerNative.getDeclaredField("gDefault");
    gDefault.setAccessible(true);
    // 获取类成员变量,直接传空,因为是静态变量,所以获取到的是系统值,
    // 得到Singleton 静态类,
    Object defaultValue = gDefault.get(null);
    //mInstance对象
    Class<?> singletonClass=Class.forName("android.util.Singleton");
    Field mInstance = singletonClass.getDeclaredField("mInstance");
    mInstance.setAccessible(true);
    // 获取到成员变量
    Object iActivityManagerObject = mInstance.get(defaultValue);
} catch (Exception e) {
  e.printStackTrace();
}

上面获取到了IActivityManager对象,接下来我们要将我们的代码插入到其中,相当于拦截系统的操作,执行我们的逻辑代码,而实现该操作有两种方式,一个是 动态代理, 另外一个是 实现接口的方式,而动态代理是万能的,实现接口需要将hook到的对象实现一个接口,但是我们获取到的IActivityManager对象本事就是一个接口,不能再实现接口,所以这里我们只能用动态代理的方式进行插入,这里我们用到系统的Proxy

// 实现该接口
Class iActivityManagerIntercept = Class.forName("android.app.IActivityManager");
StartActivity startActivity = new StartActivity(iActivityManagerObject);
/**
 * ClassLoader loader  当前的类加载器
 * Class<?>[] interfaces  返回的类将会实现的接口
 * InvocationHandler h 实现了InvocationHandler 接口的代理类,以便实现系统分发出来的方法,实现拦截操作
 */
Object oldIActivityManager = Proxy.newProxyInstance(
               Thread.currentThread().getContextClassLoader(),
               new Class[]{iActivityManagerIntercept},
               startActivity
);
// 将我们获取到的值设置进去
mInstance.set(defaultValue, oldIActivityManager);

看下StartActivity

  /**
     * 拦截类
     */
    class StartActivity implements InvocationHandler {

        private Object iActivityManager;

        public StartActivity(Object iActivityManager) {
            this.iActivityManager = iActivityManager;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Log.i("Ellison", " =========  invoke   =========");

            if ("startActivity".equals(method.getName())) {
                Log.d("Ellison", "---------startActivity----------");
            }

            return method.invoke(iActivityManager, args);
        }
    }


// 打印的结果:
 =========  invoke   =========getActivityDisplayId
 =========  invoke   =========setTaskDescription
 =========  invoke   =========checkPermission
 =========  invoke   =========checkPermission
 =========  invoke   =========getActivityOptions
 =========  invoke   =========getActivityOptions
derer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true

       [ 04-20 08:53:02.868  5687: 5687 D/         ]
       HostConnection::get() New Host Connection establi
 =========  invoke   =========activityResumed
 =========  invoke   =========activityIdle
 =========  invoke   =========getContentProvider
 =========  invoke   =========startActivity
 ---------startActivity----------
  =========  invoke   =========activityPaused
  =========  invoke   =========getActivityDisplayId
  =========  invoke   =========setTaskDescription
  =========  invoke   =========getActivityOptions
  =========  invoke   =========getActivityOptions
  =========  invoke   =========activityResumed
nderer: endAllStagingAnimators on 0xb2b7c780 (RippleDrawable) with handle 0xae59
  =========  invoke   =========activityIdle
  =========  invoke   =========activityStopped

到此,我们可以Hook到系统的API~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值