使用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) XhyEax 发表于 2021-10-2 14:54
使用Magisk获取root权限后,安装Riru和Xposed框架(如LSPosed)。
对手机管家启用模块,重启手机管家 ...
我用的上 xiaomi.eu_multi_HMK40_POCOF3_21.9.15_v12-11表示用不了。。。
手机管家启用,系统重启也是倒数十秒
加多框架安全核心组件也是一样{:1_937:}
xinziwenqing 发表于 2021-10-2 14:26
请问,怎么用,我也希望跳过这烦人的倒计时,MIUI烦操作的做法我很是厌恶
使用Magisk获取root权限后,安装Riru和Xposed框架(如LSPosed)。
对手机管家启用模块,重启手机管家即可。
由于论坛不能提供成品,请前往Github下载。 谢谢分享 请问,怎么用,我也希望跳过这烦人的倒计时,MIUI烦操作的做法我很是厌恶 貌似有模快 谢谢分享 MIUI这点确实烦 这个功能好,每次要等10秒钟好烦 小米用户,有点意思 学到了,感谢分享