项目地址
完整项目见MIUICustom
注意:该模块仅测试于手机管家 5.4.0
及5.6.0
,其他版本未测试。
如果模块未生效,可自行反编译apk,查找并替换Hook点,自行编译Xposed模块。
概述
每次修改系统设置(设置通知使用权、允许app安装未知应用、开启无障碍功能等),都会有10秒倒计时,使用起来很不方便。
于是考虑使用Frida
绕过倒计时,并开发Xposed
模块。
倒计时类型
主要有以下两种:
查看前台Activity:
adb shell dumpsys activity activities | findstr "mFocused"
可以发现两个对话框都来自手机管家,分别对应:
com.miui.permcenter.privacymanager.SpecialPermissionInterceptActivity
com.miui.permcenter.install.AdbInputApplyActivity
后者已经有分析文章了,见MIUI 12稳定版系统中的开发者选项限制解除。
也可以直接改配置文件,见需root,无需xp和frida,miui开发者选项限制解除
5.6.0 Hook点
com.miui.permcenter.privacymanager.f
的n
函数,主动调用d
函数。
快速定位
搜索SpecialPermissionInterceptActivity
类,定位到判断函数(开头调用getStringExtra("permName")
)。
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
)
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
)
@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脚本
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:
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则直接退出):
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
类,其中包含权限数组:
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
函数:
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
:
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
函数:
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
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
Java.perform(function () {
Java.use("com.miui.permcenter.privacymanager.d").c.overload()
.implementation = function () {
this.a(true);
};
})
Xposed
反射调用a
函数即可
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绕开联网和插卡打开未知来源