Android reverse engineering practice - MIUI calls up third-party application systems to intercept pop-up window analysis

    Recently, it was discovered that when some Android phones launch other applications, a system pop-up window will pop up to intercept the launch, requiring the user to confirm twice. After internal public testing, it was found that most of them are Xiaomi phones, and they are not directly related to the Android version. It is speculated that they are functions introduced by a certain MIUI upgrade. In this article, we analyze the pop-up window from the MIUI system source code.

    I have a series of articles related to Android reverse engineering. This is my actual reverse engineering article on decompiling Tencent News to open screen ads in June this year. You are also welcome to read:

Android reverse engineering practice-Tencent News removes open-screen ads_apktool removes ads_A game-playing programmer's blog-CSDN blogThe article has been read 2.3k times, with 6 likes times, collected 17 times. Last time, I failed to decompile a tool app to remove ads. The reason was that 360 degree reinforcement was used and it could not be started after recompiling. Generally speaking, apps from major manufacturers usually do not require reinforcement considering performance, compatibility, package size, etc. Therefore, this time we choose a larger app-Tencent News. Written in front: This blog is only for research and learning. If there is any infringement, please contact me to delete it, thank you. _apktool removes adshttps://blog.csdn.net/qq_21154101/article/details/130409016?spm=1001.2014.3001.5501

Table of contents

1. Background

2. Determine the source of the pop-up window

3. Decompile Mobile Manager

4. Framework code analysis 

1. Get the framework

2. miui-services.jar analysis

3. miui-framework.jar analysis

5. Suspected interception whitelist


1. Background

    Recently, I found that when launching Taobao or JD.com on my mobile phone, a window will sometimes pop up for a second confirmation. Especially during Double 11, major manufacturers’ apps are frantically placing advertisements for e-commerce apps such as Alibaba and JD.com. Unlike previous years when everyone complained about accidentally jumping to other apps, this year we found that many mobile phones will block it, especially Xiaomi phones. Give Xiaomi a thumbs up here, I am also a loyal Xiaomi user. The phenomenon is as follows:

2. Determine the source of the pop-up window

    When this pop-up window pops up, use mCurrentFocus to determine the source:

adb shell
dumpsys window|grep Focus

    as follows: 

mCurrentFocus=Window{c16c09e u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity}
  mFocusedApp=ActivityRecord{83602ab u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity} t5345}
      mPreferredTopFocusableRootTask=Task{5d40ca1 #5345 type=standard A=1000:com.miui.wakepath.ui.ConfirmStartActivit U=0 visible=true visibleRequested=true mode=fullscreen translucent=true sz=1}
      mLastFocusedRootTask=Task{5d40ca1 #5345 type=standard A=1000:com.miui.wakepath.ui.ConfirmStartActivit U=0 visible=true visibleRequested=true mode=fullscreen translucent=true sz=1}
    mFocusedWindow=Window{c16c09e u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity}
  mTopFocusedDisplayId=0

    It can be found that the pop-up window comes from com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity, and securitycenter is the mobile phone manager of Xiaomi mobile phones.​ 

3. Decompile Mobile Manager

    Download the Mobile Butler app and decompile it. Here I am using the latest version (v8.6.2.231116, which is the version on November 16, 2023). The decompilation steps will not be detailed here. After decompilation, search for ConfirmStartActivity:

     

    See the following code: 

    The first part of the code is to obtain the pkgname of the calling app, the pkgname of the called app, UserId and other information from the intent. After obtaining this information, it is useful in the judgment of r0. Take a look at the r0 method, which uses the package name and UserId obtained above to make a series of judgments:

 private boolean r0() {
        PackageInfo n10;
        PackageInfo n11;
        if (Build.VERSION.SDK_INT <= 33) {
            return false;
        }
        boolean z10 = false;
        for (UserHandle userHandle : ((UserManager) getSystemService("user")).getUserProfiles()) {
            if (userHandle.hashCode() == this.f18556g) {
                z10 = true;
            }
        }
        if (z10) {
            Object d10 = sf.e.d(f18552n, this, "getLaunchedFromUid", null, new Object[0]);
            return !(d10 == null || p1.b(((Integer) d10).intValue()) == this.f18557h) || (n10 = x0.n(this.mAppContext, this.f18554e)) == null || p1.b(n10.applicationInfo.uid) != p1.b(this.f18557h) || (n11 = x0.n(this.mAppContext, this.f18555f)) == null || p1.b(n11.applicationInfo.uid) != p1.b(this.f18558i) || this.f18553d == null;
        }
        return true;
    }

    Looking at the AndroidManifest file, the Activity is configured with an ACTION: CHECK_ALLOW_START_ACTIVITY. As the name implies: checks whether the Activity is allowed to be started.

   

    ​ Continuing to look, I saw the method i0 of the pop-up window, and the names of its two button copywriting are "deny" and "accept", so I highly suspect that dp has activated the code to intercept the pop-up window:

    But the pop-up window code only builds part of the UI of the pop-up window, and the place where it is called is not seen in ConfirmStartActivity. Looking at its parent class, it is found that the i0 method is called in onCreate of the parent class AlertActivity: 

    Dialog.show() is called in the l0 method. This method is called by k0 in the subclass ConfirmStartActivity, and k0 is finally called in the onCreate method of the parent class as above:

    In other words, the pop-up window is displayed in onCreate of ConfirmStartActivity. If the variable f10185c is true, then the pop-up window will not be returned. Where is the variable f10185c assigned? The value is assigned in j0 of ConfirmStartActivity. You can look up the code of j0.

4. Framework code analysis 

1. Get the framework

    Through the company's internal public testing, we found that this pop-up window is only available in MIUI. We have not found which version of MIUI it is in. It is now speculated that MIUI version > XXX and Phone Manager version is greater than XXX, both of which are indispensable.

    Let’s take a look at the code of the framework. Here we pull down the framework code under the framework and system_ext:

adb pull /system/framework

adb pull /system/system_ext/framework

    MIUI system, the framework code under system_ext is mainly the framework modified by Xiaomi itself. The more classic ones are miui-framework.jar and miui-services.jar:

2. miui-services.jar analysis

    Directly decompile miui-services.jar and search for ConfirmStartActivity:

    Open the ConfirmStartHelper class and take a look. You don’t see the entry code to start ConfirmStartActivity, but you can see the logic of using the mobile butler, ACTION and ConfirmStartActivity package names and class names in the isAllowStartCurrentActivity method to make judgments:

    The isAllowStartCurrentActivity method is relatively clear:

  • Only relevant judgments need to be made if the Uid is not 1000, otherwise it will be released directly. 1000 represents MIUI system applications (that is, MIUI opens backdoors for its own applications by default)
  • If it is not a system application, it is judged that the Action is CONFIRM_START_ACTIVITY_ACTION, return false, and is not allowed.
  • The source of the Intent is Mobile Butler and the Activity is ConfirmStartActivity, then just return false and not let it go.

    You can see that in the miui-services.jar package, the relevant logic ends here. Searching for isAllowStartCurrentActivity will not show any more information. Therefore, more logic may still be in other framework codes. (Note: The following pages often go back and forth between miui-services.jar and miui-framework.jar)

3. miui-framework.jar analysis

    Decompile miui-framework.jar and search for CHECK_ALLOW_START_ACTIVITY:

    Some Actions of Intent are defined in MiuiIntent. We will not take screenshots and analyze them here. Look at the calls in the SecurityManager class, mainly in the getCheckStartActivityIntent method. This method is relatively long. The first part is to determine whether the Action is PICK or SEND to select gallery pictures or send pictures, and then build the Intent through the buildStartIntent method:

 

    The second part is the scene of our investigation:

The rules are roughly as follows:

  • If the called app has already been started, return null, that is, no interception is performed.
  • If the caller is a system app (uid<10000) and IFAAFaceManager.ERR_FACE_LOCKED!=0, let it go.
  • If the caller is not a system app (uid>=10000), but the callee is a system app and IFAAFaceManager.ERR_FACE_LOCKED!=0, let it go.
  • If the caller and the callee have the same package name, let them go.
  • Otherwise, it is judged by the checkAllowStartActivity method, and the judgment is passed.

 

    mService is a variable of SecurityManager. You can see it is ISecurityManager. Let's take a look at this interface. There are two implementation classes Proxy and Stub in this interface (the proxy mode is used here). Both inherit Binder and implement ISecurityManager. Interface: 

    We know that Binder is used for cross-process communication. Here is a brief introduction to the Binder communication mechanism: 

(1) The server creates a corresponding Binder instance object, receives requests from the client, and registers its own Binder with the ServiceManager.

(2) Create the corresponding mRemote object in the Binder driver.

(3) The client wants to communicate with the server, and finds the Binder of the server through ServiceManager, and then the Binder driver returns the corresponding mRemote object, and the communication has been established.

(4) After establishing communication, the client sends data to the server by calling the transact() method of the mRemote object, and then hangs up to wait for a reply. After receiving the data, the server processes the data in the onTransact() method and returns the result to the client. The client receives the data and restarts the thread. At this point, the inter-process communication is completed.

    Continue to look at the implementation of checkAllowStartActivity in the Proxy class:

    Look at the implementation of the Stub class:

    As we mentioned above, Stub inherits Binder, and the call is in the onTransact method:

     So, let’s briefly summarize the above code:

(1) The client writes the package name, uid and other information of the caller and the callee in _data. This information is passed to the server through the transact() method of the mRemote object.

(2) The server returns to the client after processing, and the client obtains the judgment result through _replay.readBoolean and decides whether to release it.

5. Suspected interception whitelist

    Stub is an abstract class, and its implementation class SecurityManagerService is in miui-services.jar. There is an AccessController object in this class. Depending on its function, there are several methods such as filterIntentLocked, skipActivity, etc.:

 

     Looking further at the call chain of the checkAccessControlPassLockedCore method, you can see the following two methods:

    We took a closer look at the AccessController class and saw the whitelist code that was suspected of being intercepted. First, there is a set of locally hard-coded whitelists, as follows:

    Secondly, it also provides the logic for the server to update the whitelist: 

    Look at the use of mSkipList. In the filterIntentLocked method, it mainly determines whether packageName is in the whitelist: 

     We actually tracked it based on the Intent's Action - CHECK_ALLOW_START_ACTIVITY at the beginning, and located the getCheckStartActivityIntent method. The source of its call is in the following code. The use of the above interception whitelist is not related to our scenario, but in another scenario. The calling entry is as shown in the last line of code in the figure below:

    Therefore, the whitelist is most likely not the scenario where third-party applications are activated, but other scenarios. Just imagine the scenario where third-party application pop-ups are activated: If Xiaomi allowed Alipay and not WeChat or Douyin, wouldn't it cause public outrage? So, I think this must not be the scenario.

Guess you like

Origin blog.csdn.net/qq_21154101/article/details/134622650