Android逆向实战 - MIUI调起三方应用系统拦截弹窗分析

    近期,发现在部分Android手机调起其他应用时,会弹出一个系统弹窗拦截调起,需要用户二次确认。经过内部众测,发现绝大多数是小米手机,而且跟Android版本没有直接关系,猜测是MIUI某次升级引入的功能。这篇文章,我们从MIUI系统源码分析下该弹窗。

    我有一系列Android逆向相关的文章,这是我今年六月份关于反编译腾讯新闻去开屏广告的逆向实战文章,也欢迎大家阅读:

Android逆向实战 - 腾讯新闻去开屏广告_apktool去广告_一个玩游戏的程序猿的博客-CSDN博客文章浏览阅读2.3k次,点赞6次,收藏17次。上次反编译一个工具类app去广告失败,原因是使用了360加固,回编译后无法启动。一般来讲,大厂的app考虑到性能、兼容性、包体积等,通常不用加固。因此,本次我们选一个大一些的app-腾讯新闻。写在前面:本篇博客仅用来研究和学习。如有侵权,请联系我删除,谢谢。_apktool去广告https://blog.csdn.net/qq_21154101/article/details/130409016?spm=1001.2014.3001.5501

目录

一、背景

二、确定弹窗来源

三、反编译手机管家

四、framework代码分析 

1、获取framework

2、miui-services.jar分析

3、miui-framework.jar分析

五、疑似拦截白名单


一、背景

    最近,发现手机在调起淘宝或京东时,有时会弹窗让二次确认。尤其是双11期间,各大厂商app都在疯狂投放阿里、京东等电商app的广告。跟往年大家吐槽一不小心就跳到其他app不一样,今年我们发现很多手机会进行拦截,尤其是小米手机。在这里给小米点个赞,我也是忠实的小米用户。现象如下图:

二、确定弹窗来源

    当弹出该弹窗时,通过mCurrentFocus去确定来源:

adb shell
dumpsys window|grep Focus

    如下: 

mCurrentFocus=Window{c16c09e u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity}
  mFocusedApp=ActivityRecord{83602ab u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity} t5345}
      mPreferredTopFocusableRootTask=Task{5d40ca1 #5345 type=standard A=1000:com.miui.wakepath.ui.ConfirmStartActivit U=0 visible=true visibleRequested=true mode=fullscreen translucent=true sz=1}
      mLastFocusedRootTask=Task{5d40ca1 #5345 type=standard A=1000:com.miui.wakepath.ui.ConfirmStartActivit U=0 visible=true visibleRequested=true mode=fullscreen translucent=true sz=1}
    mFocusedWindow=Window{c16c09e u0 com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity}
  mTopFocusedDisplayId=0

    可以发现,弹窗来源于com.miui.securitycenter/com.miui.wakepath.ui.ConfirmStartActivity,securitycenter也就是小米手机的手机管家。 

三、反编译手机管家

    下载手机管家app,反编译。在这里我用的最新的版本(v8.6.2.231116,也就是2023年11月16号的版本)。反编译的步骤在这不细说了,反编译后,搜索ConfirmStartActivity:

     

    看到如下代码: 

    第一部分代码是从intent中获取调起app的pkgname和被调起app的pkgname以及UserId等其他信息,这些信息获取后,在r0这个判断中有用到。看下r0这个方法,就是拿上面拿到的包名和UserId等做了一系列的判断:

 private boolean r0() {
        PackageInfo n10;
        PackageInfo n11;
        if (Build.VERSION.SDK_INT <= 33) {
            return false;
        }
        boolean z10 = false;
        for (UserHandle userHandle : ((UserManager) getSystemService("user")).getUserProfiles()) {
            if (userHandle.hashCode() == this.f18556g) {
                z10 = true;
            }
        }
        if (z10) {
            Object d10 = sf.e.d(f18552n, this, "getLaunchedFromUid", null, new Object[0]);
            return !(d10 == null || p1.b(((Integer) d10).intValue()) == this.f18557h) || (n10 = x0.n(this.mAppContext, this.f18554e)) == null || p1.b(n10.applicationInfo.uid) != p1.b(this.f18557h) || (n11 = x0.n(this.mAppContext, this.f18555f)) == null || p1.b(n11.applicationInfo.uid) != p1.b(this.f18558i) || this.f18553d == null;
        }
        return true;
    }

    在AndroidManifest文件中看,该Activity的配置了一个ACTION:CHECK_ALLOW_START_ACTIVITY,顾名思义:检验是否允许启动Activity。

   

    继续看,看到了弹窗的方法i0,而且其两个按钮文案的命名是"deny"和"accept",因此高度怀疑就是dp调起拦截弹窗代码:

    但是该弹窗代码只是构建弹窗的部分UI,并没有在ConfirmStartActivity中看到其调用的地方,看下其父类,发现在父类AlertActivity的onCreate中调用了i0方法: 

    而l0方法中调用了dialog.show(),该方法是在子类ConfirmStartActivity中k0调用的,k0又是在父类如上的onCreate方法最后调用的:

    也就是说,弹窗是在ConfirmStartActivity的onCreate中展现的。如果f10185c这个变量是true,那就return不出弹窗。f10185c这个变量在哪赋值的呢?又是在ConfirmStartActivity的j0里面赋值的,大家可以往上翻一下j0的代码。

四、framework代码分析 

1、获取framework

    通过公司内部众测我们发现,该弹窗只有在MIUI才有,目前没发现是MIUI的哪个版本有的,现在是猜测需要MIUI版本 > XXX并且手机管家版本大于XXX,二者缺一不可。

    我们看下framework的代码,在这里把framework和system_ext下的framework代码一并pull下来:

adb pull /system/framework

adb pull /system/system_ext/framework

    MIUI系统,system_ext下的framework代码主要是小米自己魔改的framework,比较经典的就是miui-framework.jar和miui-services.jar:

2、miui-services.jar分析

    直接反编译miui-services.jar,搜索ConfirmStartActivity:

    打开ConfirmStartHelper类看下,这里并没有看到启动ConfirmStartActivity的入口代码,但是看到了在isAllowStartCurrentActivity方法中用到手机管家,ACTION和ConfirmStartActivity包名类名进行判断的逻辑:

    isAllowStartCurrentActivity方法比较清晰:

  • 如果Uid不是1000才需要进行相关的判断,否则直接放行。1000代表的是MIUI系统应用(也就是MIUI对自己的应用默认开后门
  • 如果不是系统应用,判断Action是CONFIRM_START_ACTIVITY_ACTION,return false,不放行。
  • Intent的来源是手机管家并且Activity是ConfirmStartActivity,那就直接return false,不放行。

    可以看到,在miui-services.jar包中,相关的逻辑也就到此为止了。再搜索isAllowStartCurrentActivity也看不到更多的信息。因此,更多的逻辑可能还是在其他的framework代码里。(注意:以下篇幅也是经常在miui-services.jar和miui-framework.jar来回折腾

3、miui-framework.jar分析

    反编译miui-framework.jar,搜索CHECK_ALLOW_START_ACTIVITY:

    MiuiIntent中定义了Intent的一些Action,在这里不截图分析。看SecurityManager类中的调用,主要就在getCheckStartActivityIntent这个方法。这个方法比较长,第一部分是通过Action是PICK还是SEND来做挑选图库图片还是发送图片的判断,然后通过buildStartIntent方法去构建Intent:

 

    第二部分则是我们调研的场景:

规则大致如下:

  • 如果被调起的app已经启动,则return null,也就是不进行拦截。
  • 如果调起者为系统app(uid<10000)并且 IFAAFaceManager.ERR_FACE_LOCKED!=0,放行。
  • 如果调起者不为系统app(uid>=10000),但是被调起者为系统app并且 IFAAFaceManager.ERR_FACE_LOCKED!=0,放行。
  • 如果调起者与被调起者同包名,放行。
  • 否则,通过checkAllowStartActivity方法判断,判断通过放行。

 

    mService是SecurityManager的一个变量,可以看到是ISecurityManager,我们看下这个接口,这接口里面有两个实现类Proxy和Stub(这里就是用的代理模式),二者都继承了Binder,并且实现了ISecurityManager接口: 

    我们知道Binder是用来跨进程通信的,在这里简单说下Binder通信机制: 

(1)服务端创建对应Binder实例对象,接收来自客户端的请求,同时,将自身的Binder注册到ServiceManager。

(2)Binder驱动中创建对应mRemote对象。

(3)客户端想和服务端通信,通过ServiceManager查找到服务端的Binder,然后Binder驱动将对应的mRemote对象返回,至此已经建立完通信。

(4)在建立完毕通信之后,客户端通过调用mRemote对象的transact()方法,将数据发送到服务端,然后挂起自己等待回复。服务端收到数据后在onTransact()方法进行处理后将结果返回给客户端,客户端收到数据,重新拉起线程,至此进程间通信完毕。

    继续看下去Proxy类中checkAllowStartActivity的实现:

    看Stub类的实现:

    上面我们也提到了,Stub继承了Binder,该调用是在onTransact方法中:

     所以,以上代码简单整理一下:

(1)客户端在_data写入了调起者和被调起者的包名、uid等信息,这些信息通过mRemote对象的transact()方法传递给服务端

(2)服务端处理后返回给客户端,客户端通过_replay.readBoolean去获取判断结果,决定是否放行。

五、疑似拦截白名单

    Stub是一个抽象类,其实现类SecurityManagerService在miui-services.jar中。这个类里面有个AccessController对象,看其作用,其中有几个方法例如filterIntentLocked,skipActivity等:

 

     进一步看checkAccessControlPassLockedCore方法的调用链,可以看到是如下两个方法:

    我们进一步看AccessController这个类,看到了疑似拦截的白名单代码。首先,有一套本地写死的白名单,如下:

    其次,还提供了服务端更新白名单的逻辑: 

    看下mSkipList的使用,在filterIntentLocked方法中,主要就是判断packageName是否在白名单中: 

     咱们一开始其实是根据Intent的Action - CHECK_ALLOW_START_ACTIVITY来跟踪的,定位到了getCheckStartActivityIntent方法,其调用来源在这如下代码这。上面的这个拦截白名单的使用并没有跟我们的场景关联起来,而是在另一种场景,其调用的入口如下图的最后一行代码:

    因此,该白名单大概率不是调起三方应用的那个场景,而是其他的场景。 试想一下,针对调起三方应用弹窗的场景:如果小米对支付宝加白放行,没对微信或抖音放行,那么不会引起公愤吗?所以,我认为这必然不是该场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/188878.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV入门教程

本文旨在让你快速入门opencv。 OpenCV OpenCV是计算机视觉中最受欢迎的库&#xff0c;最初由intel使用C和C 进行开发的&#xff0c;现在也可以在python中使用。该库是一个跨平台的开源库&#xff0c;是免费使用的。OpenCV库是一个高度优化的库&#xff0c;主要关注实时应用程…

Another app is currently holding the yum lock; waiting for it to exit...

今天使用yum进行下载的时候报错 解决办法&#xff1a; 执行 rm -f /var/run/yum.pid 然后重新运行yum指令即可&#xff0c;发现已经可以正常下载啦&#xff01;

VScode

一、VSCode设置中文 1、首先我们打开vscode&#xff0c;进入编辑页面后点击左边栏的图示图标进入“EXTENSIONS”面板 2、进入后&#xff0c;在上方搜索“Chinese”&#xff0c;搜索到中文&#xff08;简体&#xff09;后&#xff0c;点击“install”按钮。 3、等待自动下载安装…

STK Components 基础篇

1.开发包 STK Components 访问AGI官网&#xff0c;注册并登录后&#xff0c;从官网下载开发包&#xff1a;https://support.agi.com/downloads/&#xff0c;下载成功后可以申请许可证&#xff0c;AGI会向你注册的邮箱地址发送有效期半年的使用授权许可文件&#xff08;lic文件…

基于 STM32 的温度测量与控制系统设计

本文介绍了如何基于 STM32 微控制器设计一款温度测量与控制系统。首先&#xff0c;我们将简要介绍 STM32 微控制器的特点和能力。接下来&#xff0c;我们将详细讨论温度传感器的选择与接口。然后&#xff0c;我们将介绍如何使用 STM32 提供的开发工具和相关库来进行温度测量和控…

ubuntu20.04配置OpenCV的C++环境

ubuntu20.04配置OpenCV的C环境 这里以opencv-3.4.16为例 复现https://github.com/raulmur/ORB_SLAM2此项目&#xff0c;需安装opencv及其他依赖&#xff0c;可见README.md详情 1.下载opencv源代码 https://opencv.org/releases/ 2.下载OpenCV的扩展包opencv_contrib&#x…

排序算法-----基数排序

目录 前言 基数排序 算法思想 ​编辑 算法示例 代码实现 1.队列queue.h 头文件 2.队列queue.c 源文件 3.主函数&#xff08;radix_sort实现&#xff09; 算法分析 前言 今天我想把前面未更新完的排序算法补充一下&#xff0c;也就是基数排序的一种&#xff0c;这是跟…

小程序如何禁止指定用户访问?如何设置指定用户才能访问?

​有些商家为了价格保密或者实行严格的会员制等原因&#xff0c;希望小程序能够限制某些人的访问或者设置指定人员才能访问。这种功能在小程序中&#xff0c;怎么支持这些功能呢&#xff1f;下面具体介绍。 一、禁止指定用户访问 禁止指定用户访问&#xff0c;可以通过小程序…

【三极管锯齿波电路】2022-3-23

缘由以晶体管作恒流源的锯齿波电路工作原理? - 24小时必答区

【数据结构】树与二叉树(廿六):树删除指定结点及其子树(算法DS)

文章目录 5.3.1 树的存储结构5. 左儿子右兄弟链接结构 5.3.2 获取结点的算法1. 获取大儿子、大兄弟结点2. 搜索给定结点的父亲3. 搜索指定数据域的结点4. 删除结点及其左右子树a. 逻辑删除与物理删除b. 算法DSTc. 算法解析d. 代码实现递归释放树算法DS e. 算法测试 5. 代码整合…

基于C#实现三元组

我们知道矩阵是一个非常强大的数据结构&#xff0c;在动态规划以及各种图论算法上都有广泛的应用&#xff0c;当然矩阵有着不足的地方就是空间和时间复杂度都维持在 N2 上&#xff0c;比如 1w 个数字建立一个矩阵&#xff0c;在内存中会占用 1w*1w1 亿的类型空间&#xff0c;这…

【人工智能】Chatgpt的训练原理

前言 前不久&#xff0c;在学习C语言的我写了一段三子棋的代码&#xff0c;但是与我对抗的电脑是没有任何思考的&#xff0c;你看了这段代码就理解为什么了&#xff1a; void computerMove(char Board[ROW][COL], int row, int col) {while (1){unsigned int i rand() % ROW, …

BC76 [NOIP2008]ISBN号码

#include<stdio.h> int main() {char arr[13]; //存放13位的ISBNint i, j;scanf("%s",arr);int s 0;for(i0, j1; i<11; i){if(arr[i] ! -){s (arr[i]-0)*j; //将字符换成int累加&#xff1a;0162……29158j; //执行if的时候加&#xff0c;不执行不加…

Linxu 进程替换

进程替换的背景&#xff1a; 进程的替换我们需要调用execl这个接口,exxecl在3号手册&#xff0c;属于系统接口。 调用系统命令 execl 为了方便理解execl的作用&#xff0c;我们写一个程序&#xff1a; 单进程替换 我们发现运行结果是通过c库里的exec接口把系统命令 "l…

【深度学习】DAMO-YOLO,阿里,701类通用检测模型,目标检测

https://github.com/tinyvision/DAMO-YOLO/blob/master/README_cn.md DAMO-YOLO是由阿里巴巴达摩院智能计算实验室TinyML团队开发的一个兼顾速度与精度的目标检测框架,其效果超越了目前的一众YOLO系列方法&#xff0c;在实现SOTA的同时&#xff0c;保持了很高的推理速度。DAMO…

Error PostCSS plugin autoprefixer requires PostCSS 8

文章目录 一、情况一二、情况二三、总结 在启动 vue项目时&#xff0c;突然控制台报错&#xff1a; Error: PostCSS plugin autoprefixer requires PostCSS 8。然后依次出现下面几种情况&#xff0c;依次解决完&#xff0c;项目就可以正常启动了 一、情况一 error in ./src/…

【涂鸦T2-U】1、开发环境搭建

前言 本章介绍T2-U的开发环境搭建流程&#xff0c;以及一些遇到的问题。 一、资料 试用网址&#xff1a; 【新品体验】涂鸦 T2-U 开发板免费试用 涂鸦官网文档&#xff1a; 涂鸦 T2-U 开发板 T2-U 模组规格书 T2-U 开发板 淘宝(资料较全)&#xff1a; 涂鸦智能 TuyaOS开发…

软件测试职业规划导图

公司开发的产品专业性较强&#xff0c;软件测试人员需要有很强的专业知识&#xff0c;现在软件测试人员发展出现了一种测试管理者不愿意看到的景象&#xff1a; 1、开发技术较强的软件测试人员转向了软件开发(非测试工具开发)&#xff1b; 2、业务能力较强的测试人员转向了软件…

基于单片机的肺活量检测系统(论文+源码)

1.系统设计 在基于单片机的肺活量检测系统中&#xff0c;在硬件上整个系统通过利用主控制器STC89C52单片机来实现对整个系统进行控制的功能&#xff0c;通过采用LCD1602实现实时液晶显示数据的功能&#xff0c;通过肺活量传感器XGZP6847ADC0832实现监测肺活量的工作&#xff0…

ESP32网络开发实例-远程Web串口监视器

远程Web串口监视器 文章目录 远程Web串口监视器1、应用介绍2、软件准备3、硬件准备4、代码实现在本文中,我们将构建一个 ESP32 网络服务器,用作远程串行监视器。 基于 Web 的串行监视器的工作方式与通常用于调试目的的 Arduino IDE 串行监视器的工作方式相同。 1、应用介绍 …