Android Hook Activity 的几种姿势

最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
摘要由CSDN通过智能技术生成

将看到以下 log


Hook AMS


上面 hook activity 的两种方法其实都有一定缺陷,比如,第一种方法,只能 hook 住通过 Activity startActivity 的 activity。第二种方法,只能 hook 住通过 getApplicationContext().startActivity 启动的 activity。那有没有一种方法能 hook 上述两种的,其实是有的,那就是 hook AMS。下面让我们一起来看一下。

上面 hook startActivity 其实都是 hook 相应的 mInstrumentation.execStartActivity 方法,因此,我们可以从这里下手,看 mInstrumentation.execStartActivity 里面有没有一些共性的东西,可以 hook。

我们先来 mInstrumentation.execStartActivity 方法

public ActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, Activity target,

Intent intent, int requestCode, Bundle options) {

IApplicationThread whoThread = (IApplicationThread) contextThread;

Uri referrer = target != null ? target.onProvideReferrer() : null;

if (referrer != null) {

intent.putExtra(Intent.EXTRA_REFERRER, referrer);

}

if (mActivityMonitors != null) {

synchronized (mSync) {

final int N = mActivityMonitors.size();

for (int i=0; i<N; i++) {

final ActivityMonitor am = mActivityMonitors.get(i);

ActivityResult result = null;

if (am.ignoreMatchingSpecificIntents()) {

result = am.onStartActivity(intent);

}

if (result != null) {

am.mHits++;

return result;

} else if (am.match(who, null, intent)) {

am.mHits++;

if (am.isBlocking()) {

return requestCode >= 0 ? am.getResult() : null;

}

break;

}

}

}

}

try {

intent.migrateExtraStreamToClipData();

intent.prepareToLeaveProcess(who);

int result = ActivityManager.getService()

.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;

}

这里我们留意 ActivityManager.getService().startActivity 这个方法

public static IActivityManager getService() {

return IActivityManagerSingleton.get();

}

private static final Singleton IActivityManagerSingleton =

new Singleton() {

@Override

protected IActivityManager create() {

final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);

final IActivityManager am = IActivityManager.Stub.asInterface(b);

return am;

}

};

可以看到 IActivityManagerSingleton 是一个单例对象,因此,我们可以 hook 它。

public static void hookAMSAfter26() throws Exception {

// 第一步:获取 IActivityManagerSingleton

Class<?> aClass = Class.forName(“android.app.ActivityManager”);

Field declaredField = aClass.getDeclaredField(“IActivityManagerSingleton”);

declaredField.setAccessible(true);

Object value = declaredField.get(null);

Class<?> singletonClz = Class.forName(“android.util.Singleton”);

Field instanceField = singletonClz.getDeclaredField(“mInstance”);

instanceField.setAccessible(true);

Object iActivityManagerObject = instanceField.get(value);

// 第二步:获取我们的代理对象,这里因为 IActivityManager 是接口,我们使用动态代理的方式

Class<?> iActivity = Class.forName(“android.app.IActivityManager”);

InvocationHandler handler = new AMSInvocationHandler(iActivityManagerObject);

Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new

Class<?>[]{iActivity}, handler);

// 第三步:偷梁换柱,将我们的 proxy 替换原来的对象

instanceField.set(value, proxy);

}

public class AMSInvocationHandler implements InvocationHandler {

private static final String TAG = “AMSInvocationHandler”;

Object iamObject;

public AMSInvocationHandler(Object iamObject) {

this.iamObject = iamObject;

}

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// Log.e(TAG, method.getName());

if (“startActivity”.equals(method.getName())) {

Log.i(TAG, “ready to startActivity”);

for (Object object : args) {

Log.d(TAG, “invoke: object=” + object);

}

}

return method.invoke(iamObject, args);

}

}

执行以下测试代码

try {

HookHelper.hookAMS();

} catch (Exception e) {

e.printStackTrace();

}

startActivity(new Intent(this,TestActivityStart.class));

将会看到以下 log

I/AMSInvocationHandler: ready to startActivity

接下来我们一起来看一下 API 25 Instrumentation 的代码(自 API 26 开始 ,Instrumentation execStartActivity 方法有所改变)

public ActivityResult execStartActivity(

Context who, IBinder contextThread, IBinder token, Activity target,

Intent intent, int requestCode, Bundle options) {

IApplicationThread whoThread = (IApplicationThread) contextThread;

Uri referrer = target != null ? target.onProvideReferrer() : null;

if (referrer != null) {

intent.putExtra(Intent.EXTRA_REFERRER, referrer);

}

if (mActivityMonitors != null) {

synchronized (mSync) {

final int N = mActivityMonitors.size();

for (int i=0; i<N; i++) {

final ActivityMonitor am = mActivityMonitors.get(i);

if (am.match(who, null

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值