0%

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

项目地址

完整项目见MIUICustom

注意:该模块仅测试于手机管家5.4.05.6.07.2.1),其他版本未测试。

如果模块未生效,可自行反编译apk,查找并替换Hook点,自行编译Xposed模块。

概述

每次修改系统设置(设置通知使用权、允许app安装未知应用、开启无障碍功能等),都会有10秒倒计时,使用起来很不方便。

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

倒计时类型

主要有以下两种:

查看前台Activity:

1
adb shell dumpsys activity activities | findstr "mFocused"

可以发现两个对话框都来自手机管家,分别对应:
com.miui.permcenter.privacymanager.SpecialPermissionInterceptActivity
com.miui.permcenter.install.AdbInputApplyActivity

后者已经有分析文章了,见MIUI 12稳定版系统中的开发者选项限制解除
也可以直接改配置文件,见需root,无需xp和frida,miui开发者选项限制解除

7.2.1 Hook点

com.miui.permcenter.privacymanager.InterceptBaseFragmentn函数,主动调用d函数。

Frida脚本验证

1
2
3
4
5
6
Java.perform(function () {
Java.use("com.miui.permcenter.privacymanager.InterceptBaseFragment").n.overload()
.implementation = function () {
this.d(true);
};
})

5.6.0 Hook点

com.miui.permcenter.privacymanager.fn函数,主动调用d函数。

快速定位

搜索SpecialPermissionInterceptActivity类,定位到判断函数(开头调用getStringExtra("permName"))。

1
2
3
4
5
6
7
8
9
10
11
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

1
2
3
4
5
6
7
8
9
10
11
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@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脚本

1
2
3
4
5
6
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:

1
2
3
4
5
6
7
8
9
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则直接退出):

1
2
3
4
5
6
7
8
9
10
11
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类,其中包含权限数组:

1
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函数:

1
2
3
4
5
6
7
8
9
10
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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$aonClick函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

1
2
3
4
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

1
2
3
4
5
6
Java.perform(function () {
Java.use("com.miui.permcenter.privacymanager.d").c.overload()
.implementation = function () {
this.a(true);
};
})

Xposed

反射调用a函数即可

1
2
3
4
5
6
7
8
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;
}
});

参考

MIUI9绕开联网和插卡打开未知来源