Android Hook简单应用

知识点

  • 反射
  • activity 启动过程
拦截 startActivity

问你正常启动一个 Activity 常见代码

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
        button.setOnClickListener({
            startActivity(Intent(this, TestActivity::class.java))
        })
    }
}

而我需要再 startActivity的时候输出一句话怎么办?这里面就需要比较熟悉反射机制了。

class HookUtil {

    fun hookAms() {
        //一路反射,直到拿到IActivityManager的对象
        try {
            val activityManagerNativeClass = Class.forName("android.app.ActivityManagerNative")
            val defaultFile = activityManagerNativeClass.getDeclaredField("gDefault")
            defaultFile.isAccessible = true
            val defaultValue = defaultFile.get(null)
            val singletonClass = Class.forName("android.util.Singleton")
            val mInstance = singletonClass.getDeclaredField("mInstance")
            mInstance.isAccessible = true
            val activityManagerObject = mInstance.get(defaultValue)
            val iActivityManagerIntercept = Class.forName("android.app.IActivityManager")
            val handler = AmsInvocationHandler(activityManagerObject)
            val proxy = Proxy.newProxyInstance(Thread.currentThread().contextClassLoader, arrayOf(iActivityManagerIntercept), handler)
            mInstance.set(defaultValue, proxy)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    class AmsInvocationHandler(private val iActivityManagerObject: Any) : InvocationHandler {
        override fun invoke(p0: Any?, method: Method?, args: Array?): Any? {
            if (method != null && args != null) {
                if ("startActivity".contains(method.name)) {//我要在这里搞点事情
                    Log.e("HookUtil", "Activity已经开始启动")
                    Log.e("HookUtil", "HookUtil ${method.name}!!!")
                }
                Log.i("HookUtil", method.name)
                return method.invoke(iActivityManagerObject, *args)
            }
            return null
        }
    }

}

然后我们点击这个buttonlog 就会输入我们刚刚的 log。

Android Hook简单应用_第1张图片

接下来来一个猛一点的,我们知道在 Android 中所以 activity 都是需要再清单文件里面注册的,如果没有注册启动就会抛出错误,那么我们没有注册的 activity 能否启动呢?
既然都问了,那么答案肯定是肯定的。

如何启动未注册的Activity

我们看看正常我们启动未注册的 activity 。
嗯 奔溃了。。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
        button.setOnClickListener({
//            startActivity(Intent(this, TestActivity::class.java))
            startActivity(Intent(this, TargetActivity::class.java))
        })
    }
}

初学时多么令人难过又开心的错误
Android Hook简单应用_第2张图片
奔溃了
思路

上面已经拦截了启动Activity流程,在invoke中我们可以得到启动参数intent信息,那么就在这里,我们可以自己构造一个假的Activity信息的intent,这个Intent启动的Activity是在清单文件中注册的,当真正启动的时候(ActivityManagerService校验清单文件之后),用真实的Intent把代理的Intent在调换过来,然后启动即可。

既然有思路了我们就一步一步来

  • 先得到启动的 intent 信息

你可能感兴趣的:(Android Hook简单应用)