XhyEax 发表于 2021-10-2 13:45

使用Frida绕过MIUI 12系统设置倒计时

本帖最后由 XhyEax 于 2022-5-11 18:36 编辑

## 项目地址
完整项目见(https://github.com/XhyEax/MIUICustom)

注意:该模块仅测试于手机管家 `5.4.0`及`5.6.0`,其他版本未测试。

如果模块未生效,可自行反编译apk,查找并替换Hook点,自行编译Xposed模块。
## 概述
每次修改系统设置(设置通知使用权、允许app安装未知应用、开启无障碍功能等),都会有10秒倒计时,使用起来很不方便。

于是考虑使用`Frida`绕过倒计时,并开发`Xposed`模块。

## 倒计时类型
主要有以下两种:

| ![](https://xhy-1252675344.cos.ap-beijing.myqcloud.com/imgs/miui-dialog-1.jpg) | ![](https://xhy-1252675344.cos.ap-beijing.myqcloud.com/imgs/miui-dialog-2.jpg) |
| :----------------------------------------------------------------------------: | :----------------------------------------------------------------------------: |

查看前台Activity:
```
adb shell dumpsys activity activities | findstr "mFocused"
```
可以发现两个对话框都来自手机管家,分别对应:
`com.miui.permcenter.privacymanager.SpecialPermissionInterceptActivity`
`com.miui.permcenter.install.AdbInputApplyActivity`

后者已经有分析文章了,见(https://www.52pojie.cn/thread-1274517-1-1.html)。
也可以直接改配置文件,见[需root,无需xp和frida,miui开发者选项限制解除](https://www.52pojie.cn/thread-1282827-1-1.html)

## 5.6.0 Hook点
`com.miui.permcenter.privacymanager.f`的`n`函数,主动调用`d`函数。

### 快速定位
搜索`SpecialPermissionInterceptActivity`类,定位到判断函数(开头调用`getStringExtra("permName")`)。
```java
protected void r() {
    int v0 = d.a(((Activity)this).getIntent().getStringExtra("permName"));
    if(v0 == -1) {
      ((Activity)this).finish();
    }

    t v1 = this.getSupportFragmentManager().b();
    g v0_1 = d.c(v0) ? g.a(((Activity)this).getIntent()) : h.a(((Activity)this).getIntent());
    v1.b(0x1020002, v0_1);
    v1.b();
}
```
进入三元运算符的返回值类`g v0_1`,查看其父类`f`,搜索`setOnClickListener`,该函数即为Hook点(`n`)
```java
public void n() {
    Button v0 = this.btnConfirm;
    if(v0 != null) {
      v0.setOnClickListener(this.e);
    }

    Button v0_1 = this.c;
    if(v0_1 != null) {
      v0_1.setOnClickListener(this.e);
    }
}
```
查看`this.e`的实现代码,即可找到主动调用函数名(`d`)
```java
    @Override// android.view.View$OnClickListener
    public void onClick(View arg3) {
      boolean v0;
      f v3;
      if(arg3.getId() == 0x7F0B041A) {
            v3 = this.a;
            v0 = true;
            v3.d(v0);
            return;
      }

      if(arg3.getId() == 0x7F0B041E) {
            v3 = this.a;
            v0 = false;
            v3.d(v0);
            return;
      }

      this.a.h(arg3.getId());
    }
```
### Frida脚本
```js
Java.perform(function () {
    Java.use("com.miui.permcenter.privacymanager.f").n.overload()
      .implementation = function () {
            this.d(true);
      };
})
```

## 分析5.4.0
从`/system/priv-app/SecurityCenter/`提取手机管家apk(版本号`5.4.0`),使用JEB打开,定位到该Activity:
```java
protected void onCreate(Bundle bundle) {
      super.onCreate(bundle);
      Window window = this.getWindow();
      window.setBackgroundDrawable(new ColorDrawable(this.getResources().getColor(0x7F060599)));
      window.setLayout(-1, -1);
      window.addFlags(4);
      this.a();
      this.b();
    }
```
### 其他函数
`a`函数反射调用`setNavigationBarColor`,设置导航栏颜色
`b`函数根据`permName`的值,显示不同的窗口(-1则直接退出):
```java
private void b() {
    int permName = c.a(this.getIntent().getStringExtra("permName"));
    if(permName == -1) {
      this.finish();
    }

    FragmentTransaction fragmentTransaction = this.getFragmentManager().beginTransaction();
    e fragment = c.gt5(permName) ? e.a(this.getIntent()) : f.a(this.getIntent());
    fragmentTransaction.replace(0x1020002, ((Fragment)fragment));
    fragmentTransaction.commitAllowingStateLoss();
}
```
查看`com.miui.permcenter.privacymanager.m.c`类,其中包含权限数组:
```java
c.d = Arrays.asList(new String[]{"perm_notification", "perm_install_unknown", "perm_app_statistics", "perm_device_manager", "miui_open_debug", "miui_barrier_free", "miui_close_optimization", "oaid_close"});
```
可得到以下对应关系:

| permName | 功能             |
| -------- | ---------------- |
| 0      | 通知使用权       |
| 1      | 安装未知应用   |
| 2      | 使用情况访问权限 |
| 3      | 设备管理应用   |
| 4      | 打开USB调试模式|
| 5      | 无障碍功能       |
| 6      | 关闭MIUI优化   |
| 7      | 开启OEM解锁      |

### 核心函数
查看`f.a`函数:
```java
public static f a(Intent intent) {
    f fragment = new f();
    Bundle bundle = new Bundle();
    if(intent != null) {
      bundle.putString("permName", intent.getStringExtra("permName"));
    }

    fragment.setArguments(bundle);
    return fragment;
}
```
`f`类继承自`d`类,且在`c`函数中设置了按钮的`OnClickListener`:
```java
protected View.OnClickListener e;

public d() {
    this.e = new d.a(this);
}

public void c() {
    Button btnConfirm = this.b;
    if(btnConfirm != null) {
      btnConfirm.setOnClickListener(this.e);
    }

    Button btnCancel = this.c;
    if(btnCancel != null) {
      btnCancel.setOnClickListener(this.e);
    }
}
```
查看`com.miui.permcenter.privacymanager.d$a`的`onClick`函数:
```java
public void onClick(View view) {
    boolean v0;
    d fragment;
    if(view.getId() == 0x7F0B03F9) {
      fragment = this.a;
      v0 = true;
      fragment.a(v0);
      return;
    }

    if(view.getId() == 0x7F0B03FD) {
      fragment = this.a;
      v0 = false;
      fragment.a(v0);
      return;
    }

    this.a.b(view.getId());
}
```
判断点击的按钮是确认还是取消,最终调用`a`函数,确认传入`true`,取消传入`false`
```java
public void a(boolean flag) {
    this.getActivity().setResult(flag ? -1 : 0);
    this.getActivity().finish();
}
```
## 绕过
Hook `com.miui.permcenter.privacymanager.d.c`函数(即设置`OnClickListener`的函数),替换其实现,直接调用`a`函数,传入`true`即可
### Frida
```js
Java.perform(function () {
    Java.use("com.miui.permcenter.privacymanager.d").c.overload()
      .implementation = function () {
            this.a(true);
      };
})
```
### Xposed
反射调用`a`函数即可
```java
findAndHookMethod("com.miui.permcenter.privacymanager.d", lpparam.classLoader, "c", new XC_MethodReplacement() {
    @Override
    protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
      Method mtdA = param.thisObject.getClass().getDeclaredMethod("a", boolean.class);
      mtdA.invoke(param.thisObject, true);
      return null;
    }
});
```
## 参考
(https://www.52pojie.cn/thread-675777-1-1.html)

xinziwenqing 发表于 2021-10-2 23:30

XhyEax 发表于 2021-10-2 14:54
使用Magisk获取root权限后,安装Riru和Xposed框架(如LSPosed)。

对手机管家启用模块,重启手机管家 ...

我用的上 xiaomi.eu_multi_HMK40_POCOF3_21.9.15_v12-11表示用不了。。。
手机管家启用,系统重启也是倒数十秒
加多框架安全核心组件也是一样{:1_937:}

XhyEax 发表于 2021-10-2 14:54

xinziwenqing 发表于 2021-10-2 14:26
请问,怎么用,我也希望跳过这烦人的倒计时,MIUI烦操作的做法我很是厌恶
使用Magisk获取root权限后,安装Riru和Xposed框架(如LSPosed)。

对手机管家启用模块,重启手机管家即可。

由于论坛不能提供成品,请前往Github下载。

SUDaBaiCai 发表于 2021-10-2 14:10

谢谢分享

xinziwenqing 发表于 2021-10-2 14:26

请问,怎么用,我也希望跳过这烦人的倒计时,MIUI烦操作的做法我很是厌恶

skyadmin 发表于 2021-10-2 15:00

貌似有模快

dph5199278 发表于 2021-10-2 15:45

谢谢分享

老婆是加藤惠 发表于 2021-10-2 16:37

MIUI这点确实烦

Kae1249 发表于 2021-10-2 17:01

这个功能好,每次要等10秒钟好烦

小丑恶人 发表于 2021-10-2 17:07

小米用户,有点意思

笨鸟不一定先飞 发表于 2021-10-2 17:44

学到了,感谢分享
页: [1] 2 3 4
查看完整版本: 使用Frida绕过MIUI 12系统设置倒计时