Xposed series framework introduction

A. VirtualXposed concise

VirtualXposed is based on VirtualApp and Epic in the non-root environment run Xposed module implementation (support 5.0~10.0).

Compared to the Xposed, currently VirtualXposed has two limitations:

System modification is not supported (you can modify the call to system API in common APP), so gravity toolbox and application controller cannot be used. Resource hooks are not currently supported, so resource hooks do not have any effect. Module using resource HOOK, corresponding function does not take effect.

2. VirtualApp profile

VirtualApp(VA) is a sandbox product that runs on the Android operating system. It can be understood as a lightweight “Android Virtual machine”. Its product form is a highly extensible, customizable integrated SDK that allows you to develop all kinds of seemingly impossible projects based on or using VA customization. At present, VA is widely used in plug-in development, no perceptual heat update, cloud control automation, multi-open, mobile game rental number, mobile game handle activation free, block chain, mobile office security, military and government secrecy, mobile phone simulation information, script automation, automated testing and other technical fields.

3. Introduction of Epic

Epic is a Java Method-granular runtime AOP Hook framework at the virtual machine level. In simple terms, Epic is Dexposed on ART (support Android 5.0 ~ 11). It can intercept almost any Java method call within the process, and can be used to implement AOP programming, runtime staking, performance analysis, security auditing, and so on.

Epic is used by VirtualXposed and Tai Chi to implement the Xposed function in non-root scenarios, has been verified quite extensively.

4. EdXposed profile

Riru-based ART Hook framework (originally for Android Pie), Provides the same API as the original Xposed, hook with YAHFA (SandHook), Supports Android 8.0 to 11.

Xposed framework is a set of open source, in Android high authority mode running framework services, can not modify the APK file under the circumstances of the modification of the program running, based on it can make many powerful modules, and in the case of functional conflict at the same time

2. HOOK the system API

1. Hook Application

Hook by attachBaseContext method of ContextWrapper. You can initialize the app at startup and get the app pair instance of the application object

private inline fun hookAttachBaseContext(loader: ClassLoader, crossinline callback: (Context) -> Unit) {
    findAndHookMethod(
            "android.content.ContextWrapper", loader, "attachBaseContext",
            Context::class.java, object : XC_MethodHook() {
        override fun afterHookedMethod(param: MethodHookParam) { callback(param.thisObject as? Application ? :return)}}}Copy the code

2. Hook the Activity

You can hook all pages of your app by hook the Activity’s onCreate method. And get the runtime object instance of the page,

private inline fun hookActivityOnCreate(loader: ClassLoader, crossinline callback: (Activity) -> Unit) {
    findAndHookMethod(
            "android.app.Activity", loader, "onCreate",
            Bundle::class.java, object : XC_MethodHook() {
        override fun afterHookedMethod(param: MethodHookParam) {
            Log.e("amaya"."hookActivityOnCreate()... param=$param") callback(param.thisObject as? Activity ? :return)}}}Copy the code

3. Hook View

By hook the View onClick method. You can hook all page click events of the app and get the clicked runtime View object instance

private inline fun hookViewOnClick(loader: ClassLoader, crossinline callback: (View) -> Unit) {
    findAndHookMethod(
            "android.view.View", loader, "onClick",
            View::class.java, object : XC_MethodHook() {
        override fun afterHookedMethod(param: MethodHookParam) {
            Log.e("amaya"."hookActivityOnCreate()... param=$param") callback(param.thisObject as? View ? :return)}}}Copy the code

HOOK Broker APP

In the process of hook broker, three ways to hook information are summarized

Get class code information directly by decompiling apK. Hook class methods in real time. Monitor CPU method stack calls through Android Studio

Get the class code information directly by decompiling the shell APK

Through this way, it was found that the core process of peeling was needed, and two specific peeling processes were finally selected.

A is (zhuanlan.zhihu.com/p/45591754) provided by the scheme. The core processing method of this solution is to directly obtain the path from shell removal to DEX through the internal call mechanism of app through hook system classLoader, and then directly export IO to dex path. However, this solution is not applicable now, because the API of DEX has been abandoned due to the Android version upgrade Classes cannot be called in the schema in the new system.

One is to follow the solution to find a solution on GitHub similar to dumpDex(github.com/WrBug/dumpD…) The program to the technical process has been completed, the core operation needs to be shelled to the core so file first copy to data/local/ TMP folder, at the same time, chmod permission operation, and then need to shelled the project to choose the target project after running in the Xposed framework,dumpDex will automatically resolve to the original dex text File and copy it to the project directory, but a permission exception is reported at runtime. The scheme is dead

Ii. Obtain key project information through three-party HOOK project Inspeckage

Inspeckage (github.com/ac-pm/Inspe… :

  • Shared Preferences (log and file);

  • Serialization;

  • Crypto;

  • Hashes;

  • SQLite;

  • HTTP (an HTTP proxy tool is still the best alternative);

  • File System;

  • Miscellaneous (Clipboard, URL.Parse());

  • WebView;

    In line with the reverse-acquisition of APP communication data through the function of supporting HTTP data for investigation, the results found that HTTP monitoring can only monitor the request of Inspeckage itself, unable to monitor the hook project to HTTP request. But everything else will hook up. Including project to all the activity, service, permission, sp and other information

Three. Xposed API active HOOK project method

The relevant data information is obtained through the active hook of the class. At present, the scheme captures login data for login page. At present, the hook of the Application initialization,Activity initialization and View click event has been achieved by facing the hook of the login page, and there are 99 methods in the page:

index=62...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$G0fG_rSTD6s0Q3_lK4GMubnRGrk(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View) index=63...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$I4e_xipeLya3h-eEoZNwjlXQ9Y0(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View) index=64...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$MT5f5uQD8OQ0Y2mqEDEuIB3Mj9I(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View) index=65...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$ODONjH7LpaJk-jcKWuJ7_rRclNY(com.anjuke.android.newbroke r.login.activity.LoginActivity) index=66...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$V2wqee-KOoLgkAI8OeoOT594IuY(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View,boolean)
index=67...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$VBHOvEflsxAytiivtfRytGVTsN0(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View) index=68...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$Z8NppXfEkHh2lmM2WdrzDMKYiMI(com.anjuke.android.newbroke r.login.activity.LoginActivity) index=69...method=public static voidcom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$bebfyOXwVA2Gh9JSl3JFeS_R3qY(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.view.View) index=70...method=public static booleancom.anjuke.android.newbroker.login.activity.LoginActivity.lambda$rp8otnjpbXkr6nBIKj2C7_dVXuI(com.anjuke.android.newbroke r.login.activity.LoginActivity,android.widget.TextView,int,android.view.KeyEvent)
index=71...method=private void com.anjuke.android.newbroker.login.activity.LoginActivity.login()
index=72...method=static float[] [] com.anjuke.android.newbroker.login.activity.LoginActivity.m(com.anjuke.android.newbroker.login.activity.LoginActivity) index=73...method=private void com.anjuke.android.newbroker.login.activity.LoginActivity.nM()
index=74...method=private void com.anjuke.android.newbroker.login.activity.LoginActivity.r(android.os.Bundle)
index=75...method=private boolean com.anjuke.android.newbroker.login.activity.LoginActivity.verify()
index=76...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.ET()
index=77...method=public voidcom.anjuke.android.newbroker.login.activity.LoginActivity.a(com.anjuke.android.newbroker.login.utils.FingerprintLoginHel per,java.lang.String) index=78...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.cl(boolean)
index=79...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.finish()
index=80...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.g(com.anjuke.android.newbrokerlibrary.model.Broker)
index=81...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.ne()
index=82...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.oj()
index=83...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.ol()
index=84...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onActivityResult(int.int,android.content.Intent)
index=85...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.onBackPressed()
index=86...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.onClick(android.view.View)
index=87...method=protected native void com.anjuke.android.newbroker.login.activity.LoginActivity.onCreate(android.os.Bundle)
index=88...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onDestroy()
index=89...method=public voidcom.anjuke.android.newbroker.login.activity.LoginActivity.onFoundUser(com.anjuke.android.newbroker.login.entity.FoundUse rNameEvent) index=90...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onNewIntent(android.content.Intent)
index=91...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onPause()
index=92...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onPostResume()
index=93...method=public native void com.anjuke.android.newbroker.login.activity.LoginActivity.onRequestPermissionsResult(int,java.lang.String[],int[])
index=94...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onResume()
index=95...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.onSafeVerifySuccessed(com.anjuke.apimodule.model.LoginResult)
index=96...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.onSaveInstanceState(android.os.Bundle)
index=97...method=public void com.anjuke.android.newbroker.login.activity.LoginActivity.onWindowFocusChanged(boolean)
index=98...method=protected void com.anjuke.android.newbroker.login.activity.LoginActivity.t(java.lang.String[])
Copy the code

Unable to locate which method of the login callback, a further attempt at the class found that none of the method callbacks with LoginResult fired after the login was clicked. And try all the methods for global hook. But after the global hook will find black screen jammed on entering the login page, this process has a 70% probability of occurrence, occasionally to succeed to the login page, found after click login callback to ck method, this method returns a Boolean parameters only, unable to get to the real data to the API callback. It’s still being studied

Capture method call stack information through CPU runtime monitoring

Through the call information of the CPU monitoring thread, key information such as the call sequence and name of key methods can be clearly obtained. Therefore, this method is the most direct method. You can HOOK the class name and the method name directly. You don’t need to HOOK the class.

Because I do not know whether it is the IDE environment problem or APK encryption that causes the failure of CPU monitoring function under Profiler, I later found the project BDOpener(github.com/riusksk/BDO…) Support to modify the program debugable option

After the installation is completed and the module is started, debugging still cannot be found. Since the project is several years ago and the AS environment is different, version incompatibility cannot be ruled out.

Later thought may be tracking in the Xposed framework may interval a layer of Xposed so unable to debug, in order to simplify the period, I first put the target APP stored in data/ APP below the backup base. Apk copy out and reinstall directly in normal mode for monitoring, found that can be monitored. The following is a screenshot of a call to the method stack detected:

Click to invoke the order shown below. The following figure shows the sequence of events that trigger method calls when the login button is clicked:

The blue box area is the method that the LoginActivity page needs hook. The following figure shows the method call sequence after the login interface calls the API: