Here's me.

Android 系统内有一个名为 “service“ 的命令,在终端内输入 service -h,可以得知其用法:

Usage: service [-h|-?]
    service list
    service check SERVICE
    service call SERVICE CODE [i32 INT | s16 STR] ...
Options:
  i32: Write the integer INT into the send parcel.
  s16: Write the UTF-16 string STR into the send parcel.

运行 service list 得到可用列表:
photo_2018-06-08_21-32-20.jpg

我们本需要的运行的是

IPackageManager.setApplicationEnabledSetting(String,int,int,String);

查阅上面的 list,知道了对应的 service 是 package 。

有趣的是, service call SERVICE CODE [i32 INT | s16 STR] 中的 CODE,在不同安卓机器上是不同的,但我们可以通过反射获取到:

@SuppressLint("PrivateApi")
    private static int getCode() {
        Class localObject = Class.forName("android.content.pm.IPackageManager$Stub");
        Field localField = localObject.getDeclaredField("TRANSACTION_setApplicationEnabledSetting");
        return localField.getInt(localObject);
    }
在 Android 9 以上,无法使用非 SDK 接口,所以我们使用另一个奇技淫巧来读取。这里不再赘述。

获取到 CODE 之后即可构造字符串

str = "service call package " + CODE + " s16 " + packageName + " i32 " + (freeze ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER : PackageManager.COMPONENT_ENABLED_STATE_ENABLED);

然后到随便一个是 UID.SHELL 或是 ROOT 权限的进程里跑就行了。

Q&A:
Q:为什么不直接用 “pm disable-user package Name”呢?
A:很慢。

当然了,也可以使用 service 命令做一些奇技淫巧的事情,比如不申请权限就能获取 IMEI,不申请权限就能发送短信等等。但是你的应用得有 ROOT 或是 SHELL 权限。

使用此原理的软件有:小黑屋,冰箱。

标签: none

添加新评论