MIUI十秒盾绕过

随着最近几次安卓大版本更新,谷歌打着安全的旗号不断地剥夺用户的自由,例如不顾用户体验一刀切地完全禁止应用后台读取剪贴板,而MIUI也不甘其后,追随谷歌的脚步默认用户为大傻子,这个十秒盾就是典型的例子样例用户授予某个应用某些敏感权限(通知使用权、允许安装apk等)或进行其他敏感操作时,MIUI会弹出来一个这样的十秒盾,强行要求用户等待十秒,应该是为了防止不太懂手机的用户收流氓软件蛊惑授予流氓软件敏感权限,虽然我不太明白这有什么用,但是其初心还是好的,不过没有一个关闭按钮就很烦了。

定位 & 修改  

首先找到这个弹窗的出处:

$adb shell dumpsys window windows|grep \# |grep miui

找到当前Activity:

com.miui.permcenter.privacymanager.SpecialPermissionInterceptActivity

然后在系统目录中找到原apk:/system/priv-app/SecurityCenter/,复制出来反编译。
因为在倒计时结束前确认按钮是默认禁用的,所以倒计时结束后肯定会有解除禁用的代码,因此顺藤摸瓜搜索确认按钮的id:0x7f0b03ef,在com.miui.permcenter.privacymanager.j中找到下列代码:

// 为了方便阅读,一些变量名重新命名过
public void a(int i2) {
        if (i2 <= 0) { // 目测i2=10-经过的时间
            // 经过的时间大于10秒
            this.ok_button.setText(0x7f120a2f);
            this.l = true; // 不知道是干啥的
            if (this.agree_checkbox.isChecked()) {
                this.ok_button.setEnabled(true); // 经过的时间大于10秒且勾选选择框后解除禁用
                return;
            }
            return;
        }
        this.ok_button.setText(getString(0x7f120f23, new Object[]{Integer.valueOf(i2)}));
    }

public void a(View view) {
        this.k = view.findViewById(0x7f0b03f6);
        this.g = view.findViewById(0x7f0b03f5);
        this.i = (TextView) view.findViewById(0x7f0b03f1);
        this.ok_button= (Button) view.findViewById(0x7f0b03ef); // 确认
        this.cancel_button = (Button) view.findViewById(0x7f0b03f3); // 取消
        this.agree_checkbox = (CheckBox) view.findViewById(0x7f0b019e); // 是否同意的选择框
        this.ok_button.setEnabled(false); // 勾选前不允许确认
        this.h = new d();
        this.g.setAdapter(this.h);
        if (Build.VERSION.SDK_INT > 23 && getActivity().isInMultiWindowMode()) {
            b(true);
        }
        e();
    }

因为不知道具体流程,所以谨慎起见修改了两处:

public void a(int i2) {
-    if (i2 <= 0) { // 目测i2=10-经过的时间
+    if (i2 >= 0) { // 目测i2=10-经过的时间
         // 经过的时间大于10秒
         this.ok_button.setText(0x7f120a2f);
         this.l = true; // 不知道是干啥的
public void a(View view) {
     this.ok_button= (Button) view.findViewById(0x7f0b03ef); // 确认
     this.cancel_button = (Button) view.findViewById(0x7f0b03f3); // 取消
     this.agree_checkbox = (CheckBox) view.findViewById(0x7f0b019e); // 是否同意的选择框
-    this.ok_button.setEnabled(false); // 勾选前不允许确认
+    this.ok_button.setEnabled(true); // 勾选前不允许确认
     this.h = new d();
     this.g.setAdapter(this.h);

落实到smali,则是这样的:

// 第一处
const/4 v0, 0x1
-if-gtz p1, :cond_1b
+if-lez p1, :cond_1b
iget-object p1, p0, Lcom/miui/permcenter/privacymanager/f;->c:Landroid/widget/Button;
const v1, 0x7f120a2f
invoke-virtual {p1, v1}, Landroid/widget/Button;->setText(I)V
// 第二处
iget-object p1, p0, Lcom/miui/permcenter/privacymanager/f;->c:Landroid/widget/Button;
-const/4 v0, 0x0
+const/4 v0, 0x1
invoke-virtual {p1, v0}, Landroid/widget/Button;->setEnabled(Z)V
new-instance p1, Lcom/miui/permcenter/privacymanager/d;
invoke-direct {p1}, Lcom/miui/permcenter/privacymanager/d;-><init>()V

刷入  

为了保持system分区的纯洁性,还是选择使用magisk模块替换系统文件,模块内容如下:

.
├── META-INF
│   └── com
│       └── google
│           └── android
│               ├── update-binary
│               └── updater-script
├── customize.sh
├── module.prop
└── system
    └── priv-app
        └── SecurityCenter
            └── SecurityCenter.apk

打包刷入即可。