Before the dielectric

I don’t know if it bothers you, but as the project gets bigger and bigger. Trying to locate a piece of implementation logic in a sea of code is like looking for a needle in a haystack.

solution

Xposed intercepts some of the core of the key method, and then the information will be collected, we can quickly locate the code!

Look at the finished product

The source code

Source code here, to a quality 3

How do you use it?

  1. Activate the Xposed plug-in
  2. Select the application to be analyzed (preferably only 1)
  3. Open the MAC program
  4. Input orderadb forward tcp:8000 localabstract:app_hook

Github has packaged off-the-shelf software.

Source code analysis

The entrance

Core.kt is responsible for xposed entry, main purpose to initialize & intercept.

/** * app-level hook */
fun appHook(application: Application) {
    val context = application.applicationContext
    val app = application
    val classLoader = application.classLoader
    Utils.init(app)
    SharedPreferencesUtils.init(context)
    CallActionManager.init()
    WebSocketManager.onOpen(context)
    LocationHookUtils.startHook(classLoader)
// DexHelper.loadDex(context)
    InitManager.init(app)
    HookManager.register()
    HookManager.hookAll(classLoader)
    log("Hook completed!!!!!")}Copy the code

The virtual orientation

The main package is in LocationHookUtils.

Intercepting events such as Activity creation

Encapsulated in ActivityAction.

Vclass ActivityAction : BaseAction<Activity, ActivityOnCreateData>() {
    override fun hook(classLoader: ClassLoader) {
        MethodHook
            .Builder()
            .setClass(Activity::class.java)
            .methodName("onCreate")
            .parameterTypes(Bundle::class.java)
            .afterHookedMethod {
                val activity = it.thisObject as Activity
                send(parsingData(activity))}.build(a)
            .execute(a)}... }Copy the code

View event interception

  1. Click on the eventViewClickEventActionTo hook all viewsperformClickMethod, and then reflect the View’smOnClickListenerOutputs the click listener for the corresponding View.
  2. Long press eventViewLongClickEventActionTo hook all viewsperformLongClickInternalMethod, and then reflect the View’smOnLongClickListenerOutputs the click listener for the corresponding View.

Fragment create interception

FragmentCreateAction Intercepts the life cycle of all fragments.

class FragmentCreateAction : BaseAction<Any.FragmentData> (){
    override fun hook(classLoader: ClassLoader) {
        / / to distinguish fragments
        val xFragment = ReflectUtils.findClass(classLoader, "androidx.fragment.app.Fragment")
        if(xFragment ! =null) {
            hookFragment("androidx.fragment.app.Fragment", xFragment)
        }
        val fragment = ReflectUtils.findClass(classLoader, "android.app.Fragment")
        if(fragment ! =null) {
            hookFragment("android.app.Fragment", fragment)
        }

        val v4fragment = ReflectUtils.findClass(classLoader, "android.support.v4.app.Fragment")
        if(v4fragment ! =null) {
            hookFragment("android.app.Fragment", v4fragment)
        }
    }
}
Copy the code

The startActivity method intercepts

StartActivityAction intercepts the execStartActivity method of the Instrumentation.

class StartActivityAction : BaseAction<Intent.StartActivityOnCreateData> (){
    override fun hook(classLoader: ClassLoader) {
        MethodHook
            .Builder()
            .setClass(Instrumentation::class.java)
            .methodName("execStartActivity")
            .isHookAll(true)
            .afterHookedMethod {
                log("To start the activity: ${it. The args. The size}")
                if (it.args.size == 7) {
                    val context = it.args[0] as Context
                    val intent = it.args[4] as Intent
                    val data = parsingData(intent)
                    data.startContext = context.javaClass.name
                    data.stack = Log.getStackTraceString(Throwable())
                    send(data)
                }
            }
            .build()
            .execute()
    }
}
Copy the code

Data communications

After the WebSocketManager interceptor application is started, a WebSocket service is created on the mobile end.

object WebSocketManager : SimpleEndpoint, CoroutineScope by GlobalScope {
    private lateinit var mServer: LocalSocketServer
    private lateinit var context: Context

    val conns = mutableListOf<SimpleSession>()

    fun onOpen(context: Context) {
        this.context = context
        try {
            log("Start!!!!!")
            mServer = LocalSocketServer(
                "app_hook"."app_hook",
                LazySocketHandler(ForwardSocketHandlerFactory(context, this))
            )
            GlobalScope.launch(Dispatchers.IO) {
                try {
                    mServer.run()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        } catch (e: Exception) {
            log("Error: ${e.m essage}")}}... }Copy the code

In the adb forward command, the mobile port is insinuated to the client. This allows mobile and client communication!

Desktop applications

I’ll write desktop applications with Flutter!

conclusion

All right! Analysis APP can be happy! Detailed code everyone see!