android hook入门

本文详细介绍了如何使用Java反射和动态代理实现对Android Activity的hook,通过追踪startActivity源码,找到hook点ActivityManagerNative.getDefault(),并替换为代理对象,实现在Activity生命周期方法执行前后插入自定义逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文hook以activity来讲解,运用Java反射以及代理。

hook技术的难点在于hook到某个点,就是寻找在内存中“不变”的对象,那么静态修饰或者单例就是我们要hook的点,然后实现代理。所以根据这个想法,我们就来找Activity需要hook的点。

一:我们先跟踪 startActivity源码

第一步:
@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

第二步:发现startActivity实际上调用了startActivityForResult

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

第三步:跟进startActivityForResult,发现是 Instrumentation 执行了execStartActivity

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mParent == null) {
        Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
    }
}

第四步:跟踪Instrumentation.execStartActivity(),发现是ActivityManagerNative.getDefault()执行了startActivity,而ActivityManagerNative.getDefault()是静态全局变量,所以,该变量就是我们要hook的点。

public Instrumentation.ActivityResult execStartActivity(***) {
    /**
     * 省略
     */
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

二:通过反射获取ActivityManagerNative.getDefault()属性。并将其中的值替换成代理对象。

public class HookUtil {
    public static void hook() {
        try {
            // AS无法直接调用,所以采用该方式获取ActivityManagerNative.class文件
            Class<?> activityManagerNative = Class.forName("android.app.ActivityManagerNative");
            //获取gDefault属性
            Field gDefaultFiled = activityManagerNative.getDeclaredField("gDefault");
            //将field设置为可访问
            gDefaultFiled.setAccessible(true);
            //由于ActivityManagerNative.gDefault为static类型,所以不需要传ActivityManagerNative对象,该属性为类所有
            Object gDefault = gDefaultFiled.get(null);
            /**
             * gDefault实际上是Singleton对象,所以我们要获取Singleton中的IActivityManager对象
             * private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
             *                 protected IActivityManager create() {
             *                     IBinder b = ServiceManager.getService("activity");
             *                     IActivityManager am = asInterface(b);
             *                     return am;
             *                 }
             *             };
             */
            //Singleton也无法通过AS直接调用,所以也采用该方式获取
            Class<?> SingletonClass = Class.forName("android.util.Singleton");
            Field mInstanceField = SingletonClass.getDeclaredField("mInstance");
            mInstanceField.setAccessible(true);
            Object iActivityManager = mInstanceField.get(gDefault);
            /**
             * 以下将iActivityManager生成代理对象。
             */
            ProxyHander proxyHander = new ProxyHander();
            Object proxyInstance = proxyHander.proxy(iActivityManager);
            //将mInstanceField的值替换成代理对象
            mInstanceField.set(gDefault, proxyInstance);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class ActivityInterceptor {
    public void before() {
        Log.i("ActivityInterceptor", "before= ");
    }

    public void after() {
        Log.e("ActivityInterceptor", "after= ");
    }
}
public class ProxyHander implements InvocationHandler {
    /**
     * 被代理的对象
     */
    private Object object;

    /**
     * activity自定义的拦截器
     */
    private ActivityInterceptor interceptor = new ActivityInterceptor();

    /**
     * 动态生成一个代理类对象
     *
     * @param object
     * @return 返回的是代理对象
     */
    public Object proxy(Object object) {
        this.object = object;
        Object proxyInstance = Proxy.newProxyInstance(object.getClass().getClassLoader(),
                object.getClass().getInterfaces(), this);
        return proxyInstance;
    }

    /**
     * 被代理对象执行方法时会调该方法
     *
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        interceptor.before();
        Object result = method.invoke(this.object, args);
        interceptor.after();
        return result;
    }
}

三:在Application中执行该段代码。

@Override
public void onCreate() {
    super.onCreate();
    HookUtil.hook();
}

四:运行效果,会在activity onCreate等方法执行前后输出 before ,after

总结:

1:通过反射获取到ActivityManagerService中的gDefault对象,并通过反射拿到IActivityManager对象,然后对IActivityManager对象进行代理。

2:该hook技术应用于Android P以下系统,Android P禁用了非公开API的调用。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值