Pay attention to my public number Android program Yuan get more technical dry goods ~!

In the recent wechat data backup project, some of the “black technology” explored can achieve silent uninstall third-party APP, silent clear third-party APP data, silent downgrade app installation and other functions

First, these require system signatures or root permissions to do so, and second, reflection calls to the system’s hidden API to do so. The hidden API, as its name implies, is not normally called, so some special method is needed to call it.

0. Reflection method

The general method for reflection is provided here, from which the sample code will be called and used as an Util utility class.

public class ReflectUtil {
    // Use reflection to call the target instance method
    public static Object callObjectMethod(Object target, String method, Class
       [] parameterTypes, Object... values)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Class<? extends Object> clazz = target.getClass();
        Method declaredMethod = clazz.getDeclaredMethod(method, parameterTypes);
        return declaredMethod.invoke(target, values);
    }

  // Get the instance object by reflection
    public static Object callStaticObjectMethod(Class
        clazz, String method, Class
       [] parameterTypes, Object... values)
            throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method declaredMethod = clazz.getDeclaredMethod(method, parameterTypes);
        declaredMethod.setAccessible(true);
        return declaredMethod.invoke(null, values); }}Copy the code

1. Uninstall

First installation uninstall related logic framework layer system exists, the path is/frameworks/base/services/core/Java/com/android/server/PM/PackageManagerService. Java, Namely the PMS. Through the Android source code (here is a recommended online look at the source siteAndroidxref.com/), you can know how to uninstall…

As you can see, the parameters required for this method are packageName, versionCode, Observer (get this class from AIDL, mentioned later), userId, and Flags.

The IPackageDeleteObserver class is an AIDL callback notification interface that can be found in the source code:

package android.content.pm;

/**
 * API for deletion callbacks from the Package Manager.
 *
 * {@hide} * /
oneway interface IPackageDeleteObserver {
    void packageDeleted(in String packageName, in int returnCode);
}
Copy the code

Placing the AIDL file in the project source code according to the above Package: Android.content.pm hierarchy will automatically generate the class file for invocation. The generated file is shown below:Once this has been successfully generated, you can use reflection to implement the unload operation. Directly on the code:

// Uninstall operation
  try {
          // 拿到PackageName对应的PackageInfo
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(yourPackageName, 0);
            PackageDeleteObserver observer = new PackageDeleteObserver();
           // Get the IBinder object by reflection
            IBinder pgmService = (IBinder) ReflectUtil.callStaticObjectMethod(Class.forName("android.os.ServiceManager"), "getService".new Class[]{String.class}, "package");
           // Get the IPackageManager object by reflection
           Object mIPm = ReflectUtil.callStaticObjectMethod(Class.forName("android.content.pm.IPackageManager$Stub"),
                    "asInterface".new Class[]{IBinder.class}, pgmService);
           // Use reflection to call the deletePackageAsUser method in the PackageManagerService using the IPackageManager interface
          // The first two zeros are passed in as the userId. The first one is passed as the userId, and the second one is the flag.
            ReflectUtil.callObjectMethod(mIPm, "deletePackageAsUser".new Class[]{String.class, int.class, IPackageDeleteObserver.class, int.class, int.class},
                    yourPackageName, packageInfo.versionCode, observer, 0.0);
        } catch (Exception e) {
            
        }


// Override the packageDeleted method of IPackageDeleteObserver to monitor application uninstallation
private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {

        @Override
        public void packageDeleted(String packageName, int returnCode) {
            Log.d(TAG, "packageName:"+packageName+" returnCode:"+returnCode);
            if (returnCode == 1) {
                //returnCode = 1 succeeds}}}Copy the code

Then add two lines of permissions to the androidmanifest.xml file:

    <uses-permission android:name="android.permission.DELETE_PACKAGES"/>
    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
Copy the code

You can silently uninstall third-party APPS.


2. Clear data

Clear the data by calling the PackageManagerService method clearApplicationUserData.It can be seen that the method needs to pass in packageName, IPackageDataObserver, userId and other parameters, where IPackageDataObserver is the same as the IPackageDeleteObserver access method above, the code is as follows:

package android.content.pm;

/** * API for package data change related callbacks from the Package Manager. * Some usage scenarios include deletion of  cache directory, generate * statistics related to code, data, cache usage(TODO) * {@hide} * /
oneway interface IPackageDataObserver {
    void onRemoveCompleted(in String packageName, boolean succeeded);
}
Copy the code

Compiled can get normal IPackageDataObserver. Class, you can call clearApplicationUserData method through reflection, the code is as follows:

// Add data
  try {
            DeleteUserDataObserver observer = new DeleteUserDataObserver();
            IBinder pgmService = (IBinder) ReflectUtil.callStaticObjectMethod(Class.forName("android.os.ServiceManager"),
                    "getService".new Class[]{String.class}, "package");
            Object mIPm = ReflectUtil.callStaticObjectMethod(Class.forName("android.content.pm.IPackageManager$Stub"),
                    "asInterface".new Class[]{IBinder.class}, pgmService);
            ReflectUtil.callObjectMethod(mIPm, "clearApplicationUserData".new Class[]{String.class, IPackageDataObserver.class, int.class},
                    yourPackageName, observer, 0);
        } catch (Exception e) {
         
        }

/ / implementation IPackageDataObserver
private class DeleteUserDataObserver extends IPackageDataObserver.Stub {
        @Override
        public void onRemoveCompleted(String packageName, boolean succeeded) {
            Log.d(TAG, "packageName:" + packageName + " isSuccess:"+ succeeded); }}Copy the code

To do this, you need to declare the following permissions:

<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
Copy the code

3. Degrade the installation

Under the inspiration of the leader, the original ADB commands can be found in the source code project corresponding to the execution method. There is a command in ADB to downgrade adb install -r -d

With roots in the source code, process did not show, finally call PackageInstaller. SessionParams setRequestDowngrade method, specific as follows:

As you can see, this is also a hide API that needs to be called with reflection. Install SessionParams (true); install SessionParams (true); install SessionParams (true);

PackageInstaller.SessionParams sp =
                    new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            ReflectUtil.callObjectMethod(sp, "setRequestDowngrade".new Class[]{boolean.class}, true);
Copy the code

4. To summarize

Source code is the best teacher, when there is a stuck place, look at the source code can often solve 99% of the problem. For example, in the process of silent uninstallation, our app has successfully called the reflection method, and no exception is caught, but the effect has not been implemented, and nothing is printed in the Observer. After looking at the source code of MIUI, we found that a whitelist is set in the framework layer of MIUI. Only the app in the whitelist has the permission to call the uninstall method, so we added our APP to the whitelist, and the effect can be normally realized after compilation.