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