Android11 framework 禁止三方应用开机自启动

Android11应用自启动限制

大纲

  • Android11应用自启动限制
  • 分析
  • 验证猜想:Android11 AOSP是否自带禁止三方应用监听`BOOT_COMPLETED`​
  • 方案
    • 禁止执行非系统应用监听到`BOOT_COMPLETED`​后的代码逻辑
    • 在执行启动时判断其启动的广播接收器
    • 一棍子打死方案(慎用)
    • 补充!!!!!!!

分析

按理说三方应用应该收不到开机启动广播(后文会证实这个说法是假的),但是很神奇的是还是有应用能自启动,体现为比如秋秋,启动后通过ps命令能看到其进程存活,但是静置后进程会启动失败,从而导致被清理

在这里插入图片描述

07-18 05:59:02.132367 938 967 I ActivityManager: Start proc 1930:com.tencent.mobileqq:MSF/u0a110 for broadcast {com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}

log如上

参照这篇博客Android系统层面限制应用开机自启动详解,此时通过Android Studio查看其apk的manifest,其NetConnInfoCenter​内容如下

可以看到其监听了开机广播外,还监听了各种各样的广播,比如TIMEZONE_CHANGED​,看起来是时区变换的广播,这边尝试了一下在没有启动秋秋的情况下,去切换时区,果然打印了启动秋秋的log,虽然没有启动成功,但是之前在这个项目中,自己遇到过秋秋启动成功的情况,所以还是要处理

在这里插入图片描述

<receiverandroid:name="com.tencent.mobileqq.msf.core.NetConnInfoCenter"android:exported="false"android:process=":MSF"><intent-filterandroid:priority="2147483647"><actionandroid:name="android.intent.action.BOOT_COMPLETED" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.MY_PACKAGE_REPLACED" /></intent-filter><intent-filter><actionandroid:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.TIME_SET" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.TIMEZONE_CHANGED" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.rdm.report" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.receiveofflinepush" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.offlinepushclearall" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.receiveofflinepushav" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.offlinepushclearallav" /></intent-filter><intent-filter><actionandroid:name="com.tencent.mobileqq.msf.startmsf" /></intent-filter><intent-filter><actionandroid:name="android.intent.action.MEDIA_BAD_REMOVAL" /><actionandroid:name="android.intent.action.MEDIA_EJECT" /><actionandroid:name="android.intent.action.MEDIA_MOUNTED" /><actionandroid:name="android.intent.action.MEDIA_REMOVED" /><actionandroid:name="android.intent.action.MEDIA_SCANNER_FINISHED" /><actionandroid:name="android.intent.action.MEDIA_SCANNER_STARTED" /><actionandroid:name="android.intent.action.MEDIA_SHARED" /><actionandroid:name="android.intent.action.MEDIA_UNMOUNTED" /><dataandroid:scheme="file" /></intent-filter><intent-filter><actionandroid:name="android.net.wifi.WIFI_STATE_CHANGED" /></intent-filter></receiver>

验证猜想:Android11 AOSP是否自带禁止三方应用监听BOOT_COMPLETED

因为前面提到Android11三方应用到底能不能监听开机广播,这边写了个demo,仅监听BOOT_COMPLETED​,重启后验证,进程会正常被创建,所以Android11并没有原生的禁止三方监听BOOT_COMPLETED​的策略。至少AOSP没有,国内手机带此功能是手机厂商自己实现的

public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {Intent mIntent = new Intent(context, MainActivity.class);mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(mIntent);          // 启动你的应用程序}}
}<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED" /><receiver android:name=".BootReceiver"android:exported="false"><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter>
</receiver>

在这里插入图片描述

在这里插入图片描述

结论:Android11上普通三方应用是可以接收到开机广播的,此时如果应用去自启动,后台会有进程存活,因此需要做处理

方案

禁止执行非系统应用监听到BOOT_COMPLETED​后的代码逻辑

在处理广播的地方 过滤掉所有的三方应用,并预留白名单

在AMS的broadcastIntentLocked​方法中

diff --git a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
index f26ae929ef..6b906ced4f 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16736,7 +16736,30 @@ public class ActivityManagerService extends IActivityManager.Stubfinal int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,@Nullable String callerFeatureId, Intent intent, String resolvedType,IIntentReceiver resultTo, int resultCode, String resultData,Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,int realCallingPid, int userId, boolean allowBackgroundActivityStarts,@Nullable int[] broadcastWhitelist) {...if (receivers != null) {String skipPackages[] = null;if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())|| Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {Uri data = intent.getData();if (data != null) {String pkgName = data.getSchemeSpecificPart();if (pkgName != null) {skipPackages = new String[] { pkgName };}}} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            }
+            // add by xumaoxin start
+            } else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+                //Resources res = mContext.getResources();
+                //String[] blacklist = res.getStringArray(com.android.internal.R.array.blacklist_boot_receiver);
+                List<String> skipList = new ArrayList<>();
+                Set<String> whitelist = new ArraySet<>();
+                whitelist.add("com.example.test11");
+
+                for (int i = 0, j = receivers.size(); i < j; i++) {
+                    ResolveInfo curt = (ResolveInfo) receivers.get(i);
+                    String curPkgName = curt.activityInfo.packageName;
+                    if ((curt.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        //Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is system app, allow!");
+                    } else if (!whitelist.contains(curPkgName)) {
+                        Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is not system app and not whitelist, not allow!");
+                        skipList.add(curPkgName);
+                    }else {
+                        Slog.i("ActivityManager", "xumaoxin: " + curPkgName + " is not system app but is whitelist, allow!");
+                    }
+                }
+                skipPackages = skipList.toArray(new String[0]);
+                Slog.i("ActivityManager", "xumaoxin: skipPackages= " + Arrays.toString(skipPackages));
+                //add by xumaoxin end
+            } if (skipPackages != null && (skipPackages.length > 0)) {for (String skipPackage : skipPackages) {if (skipPackage != null) {

判断是不是系统应用

curt.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 //是系统应用

注意:此处只能禁止执行skipPackages中的应用去监听到BOOT_COMPLETED后的执行逻辑,如果应用只做了这一个监听来自启,比如我前面写的demo,这样就足够了,但是国内三方app一般会想方设法地自启动,这边验证了秋秋还是会启动起来,会有进程存在,继续处理。

在执行启动时判断其启动的广播接收器

注意:同样需要处理秋秋的同学请一定看到最后,这一节的方案不完善

基于log

ActivityManager: Start proc 2962:com.tencent.mobileqq:MSF/u0a112 for broadcast {com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}

这里秋秋自己的广播接收器叫com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter​,我们先找到这行log打印的地方

ActivityManager为tag的,在server/am下去grep就好,找到其文件

frameworks\base\services\core\java\com\android\server\am\ProcessList.java

    boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,long expectedStartSeq, boolean procAttached) {mPendingStarts.remove(expectedStartSeq);final String reason = isProcStartValidLocked(app, expectedStartSeq);if (reason != null) {Slog.w(TAG_PROCESSES, app + " start not valid, killing pid=" +pid+ ", " + reason);app.pendingStart = false;killProcessQuiet(pid);Process.killProcessGroup(app.uid, app.pid);noteAppKill(app, ApplicationExitInfo.REASON_OTHER,ApplicationExitInfo.SUBREASON_INVALID_START, reason);return false;}......StringBuilder buf = mStringBuilder;buf.setLength(0);buf.append("Start proc ");buf.append(pid);buf.append(':');buf.append(app.processName);buf.append('/');UserHandle.formatUid(buf, app.startUid);if (app.isolatedEntryPoint != null) {buf.append(" [");buf.append(app.isolatedEntryPoint);buf.append("]");}buf.append(" for ");buf.append(app.hostingRecord.getType());if (app.hostingRecord.getName() != null) {buf.append(" ");buf.append(app.hostingRecord.getName());}

能看到buf.append("Start proc ");​这里开始的buf记录和我们log是一样的,所以后面的app.hostingRecord.getType()​对应log中的广播接收器broadcast​,而app.hostingRecord.getName()​对应log中的{com.tencent.mobileqq/com.tencent.mobileqq.msf.core.NetConnInfoCenter}

那就好处理了,判断其name,如果是NetConnInfoCenter​,那就不允许启动。

代码往前,能看到原生有一个退出的逻辑,通过final String reason = isProcStartValidLocked(app, expectedStartSeq);​赋值

isProcStartValidLocked​方法中加入秋秋的判断,返回一个reason,这样此次启动能通过原生的逻辑进行拦截,比较安全

diff --git a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
index 9d4deb4d5b..271f99138f 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2462,6 +2462,14 @@ public final class ProcessList {@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;
+        if (app.hostingRecord.getName() != null) {
+            String name = app.hostingRecord.getName();
+            Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
+            if (name.contains("NetConnInfoCenter")) {
+                if (sb == null) sb = new StringBuilder();
+                sb.append("dont allow qq auto start");
+            }
+        }if (app.killedByAm) {if (sb == null) sb = new StringBuilder();sb.append("killedByAm=true;");

编译push验证,秋秋在设备重启后不会再重启,会被拦截

在这里插入图片描述

抑制秋秋自启动成功!同时不会影响用户手动点击图标等方式的启动

应用多了可以写成白名单,并配置到xml中

注意:此方案的弊端就是只能对特定的应用单独加判断逻辑,不能适用于所有应用

一棍子打死方案(慎用)

观察三方应用是否都是通过broadcast​类型进行自启动的,能否判断type​是否是broadcast​来进行通用过滤?风险就是这样一来一棍子打死了,等于不再允许三方应用通过广播方式进行启动

diff --git a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
index 9d4deb4d5b..03a4c1ddb2 100644
--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2462,6 +2462,19 @@ public final class ProcessList {@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;
+        /*if (app.hostingRecord.getName() != null) {
+            String name = app.hostingRecord.getName();
+            Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
+            if (name.contains("NetConnInfoCenter")) {
+                if (sb == null) sb = new StringBuilder();
+                sb.append("dont allow qq auto start");
+            }
+        }*/
+        if (((app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) && "broadcast".equals(app.hostingRecord.getType())) {
+            String name = app.hostingRecord.getName();
+            if (sb == null) sb = new StringBuilder();
+            sb.append("dont allow thirdapp auto start by broadcast: " + name);
+        }if (app.killedByAm) {if (sb == null) sb = new StringBuilder();sb.append("killedByAm=true;");

编译后验证秋秋确实是没有问题,主要不确定其他的广播场景会不会被拦截下来,毕竟一棍子打死的办法杀伤面有点大

在这里插入图片描述

尽量还是使用第一种+第二种,不让三方应用执行开机广播逻辑+特殊应用特殊过滤。第三种方案慎用!

补充!!!!!!!

对于秋秋前面通过广播想启动的只是其一个子进程,在登陆的时候会用到,如果一直不让其自动启动,会导致登陆超时。
所以还需要加入判断,启动的时候秋秋主进程是否存活,如果存活,我们认为秋秋不是在后台想自启动,而是通过正常途径启动子进程。
而进行是否存活的判断调用较频繁,而我们的系统应用不需要进行此判断,所以调用前再加入是否系统应用的判断。实现代码diff如下

--- a/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@@ -2459,14 +2459,27 @@ public final class ProcessList {return success ? app : null;}+    public boolean isAppRunning(String packageName) {
+        List<ActivityManager.RunningAppProcessInfo> runningProcesses = mService.getRunningAppProcesses();
+        if (runningProcesses.size() > 0) {
+            for (ActivityManager.RunningAppProcessInfo info : runningProcesses) {
+                if (info.processName.equals(packageName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+@GuardedBy("mService")private String isProcStartValidLocked(ProcessRecord app, long expectedStartSeq) {StringBuilder sb = null;// add by sprocomm start
-        if (app.hostingRecord.getName() != null) {
+		 //非系统应用执行if中的逻辑
+        if (((app.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) && app.hostingRecord.getName() != null) {String name = app.hostingRecord.getName();
-            Slog.i("ActivityManager", "xumaoxin: broadcast= " + name);
-            if (name.contains("NetConnInfoCenter")) {
+			 //秋秋是否存活,这个包名,可以动态到白名单中,和NetConnInfoCenter这个组件名放一起
+            boolean isRunning = isAppRunning("com.tencent.mobileqq");
+            Slog.i("ActivityManager", "xumaoxin: com.tencent.mobileqq isRunning= "+ isRunning + ", broadcast= " + name);
+            if (!isRunning && name.contains("NetConnInfoCenter")) {if (sb == null) sb = new StringBuilder();sb.append("dont allow qq auto start");}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

矩阵形式的bezier曲线

本文分享一段矩阵形式的bezier代码&#xff1a; clc clear% 控制点 P [25;10;5;13]; %% 获得M矩阵 n length(P) - 1; M zeros(n1,n1); for i 1:n1for j 1:n1if(ij<n3)M(i,j) (-1)^(n -i-j2)*nchoosek(n,n-i1)*nchoosek(n-i1,j-1);elseM(i,j) 0;endend end t_temp l…

buu做题(5)

目录 [GXYCTF2019]禁止套娃 方法一: 方法二: [NCTF2019]Fake XML cookbook [GXYCTF2019]禁止套娃 页面里啥也没有 使用dirsearch 扫一下目录 发现有 git 使用工具githack拉取源码 <?php include "flag.php"; echo "flag在哪里呢&#xff1f;<br&g…

PostgreSQL使用(三)

说明&#xff1a;本文介绍PostgreSQL的数据类型和运算符&#xff1b; 数据类型 常用的数据类型如下&#xff1a; 运算符 如下&#xff1a; 运算符的优先级如下&#xff1a; 不需要强记硬背&#xff0c;只需要记住括号可以提高运算符的优先级即可&#xff1b; 总结 本文介绍…

【JavaEE进阶】——Spring AOP

目录 &#x1f6a9;Spring AOP概述 &#x1f6a9;Spring AOP快速⼊⻔ &#x1f393;引入AOP依赖 &#x1f393;编写AOP程序 &#x1f6a9;Spring AOP 详解 &#x1f393;Spring AOP核⼼概念 &#x1f393;通知类型 &#x1f393;PointCut &#x1f393;切⾯优先级 Ord…

【JavaScript 算法】拓扑排序:有向无环图的应用

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、算法原理二、算法实现方法一&#xff1a;Kahn算法方法二&#xff1a;深度优先搜索&#xff08;DFS&#xff09;注释说明&#xff1a; 三、应用场景四、总结 拓扑排序&#xff08;Topological Sorting&#xff09;是一种…

核函数支持向量机(Kernel SVM)

核函数支持向量机&#xff08;Kernel SVM&#xff09;是一种非常强大的分类器&#xff0c;能够在非线性数据集上实现良好的分类效果。以下是关于核函数支持向量机的详细数学模型理论知识推导、实施步骤与参数解读&#xff0c;以及两个多维数据实例&#xff08;一个未优化模型&a…

笔记 3 : 继续彭老师课本第 3 章的 arm 的汇编指令

&#xff08;26&#xff09; 指令 LDR &#xff1a; &#xff08;27&#xff09; STR &#xff1a; 可见&#xff0c;从语法上将&#xff0c; &#xff01; 提示编译器进行更复杂的编译&#xff0c;对应内涵更复杂的指令。 &#xff08;28&#xff09; LDR 与 STR 指令还可…

Android C++系列:Linux信号(三)

可重入函数 不含全局变量和静态变量是可重入函数的一个要素可重入函数见man 7 signal在信号捕捉函数里应使用可重入函数在信号捕捉函数里禁止调用不可重入函数例如:strtok就是一个不可重入函数,因为strtok内部维护了一个内部静态指针,保存上一 次切割到的位置,如果信号的捕捉…

echarts实现3d柱状效果

代码如下&#xff0c;单个的调第一个方法&#xff0c;多个柱状的调第二个方法&#xff0c;具体情况修改参数或者二次开发即可 //3d柱状图 export function getEcharts3DBar (xAxisData:string[][name1,name2,name3], data:number[][1,2,3], colorObj:IBaseObject{topStartColo…

通过albumentation对目标检测进行数据增强(简单直接)

albumentation官方文档看不懂&#xff1f;xml文件不知道如何操作&#xff1f;下面只需要修改部分代码即可上手使用 要使用这个方法之前需要按照albumentation这个库还有一些辅助库,自己看着来安装就行 pip install albumentation pip install opencv-python pip install json…

MKS流量计软件MFC通讯驱动使用于C和P系列MFC控制USB接口W10系统

MKS流量计软件MFC通讯驱动使用于C和P系列MFC控制USB接口W10系统

使用VuePress-Reco快速搭建博客(保姆级)

简介&#xff1a;VuePress-Reco 一款简洁的 vuepress 博客 & 文档 主题&#xff0c;可以自由搭建自己的风格&#xff0c;比较方便简洁。 链接&#xff1a;vuepress-reco 准备环境&#xff1a; Node.Js >20.5.0&#xff0c;Npm > 10.8.2 OR Yarn > 1.22.19 注&am…

Kafka介绍及Go操作kafka详解

文章目录 Kafka介绍及Go操作kafka详解项目背景解决方案面临的问题业界方案ELKELK方案的问题日志收集系统架构设计架构设计组件介绍将学到的技能消息队列的通信模型点对点模式 queue发布/订阅 topicKafka介绍Kafka的架构图工作流程选择partition的原则ACK应答机制Topic和数据日志…

0718,TCP协议,三次握手,四次挥手

目录 上课喵&#xff1a; TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;的状态迁移图 TCP连接的状态迁移图 状态迁移说明&#xff1a; 注意&#xff1a; big_htonl.c 字节序转换 addr.c IP地址的转换 作业喵&#xff1a; …

前端组件化实践:Vue自定义加载Loading组件的设计与实现

摘要 随着前端技术的飞速发展&#xff0c;组件化开发已成为提高开发效率、降低维护成本的重要方法。本文介绍了前端Vue自定义加载Loading组件的设计思路与实现过程&#xff0c;该组件通过设置gif动画实现加载效果&#xff0c;可广泛应用于页面请求加载场景。通过该组件的实践&…

2024年度上半年中国汽车保值率报告

来源&#xff1a;中国汽车流通协会&精真估 近期历史回顾&#xff1a; 2024上半年房地产企业数智化转型报告.pdf 2024国产院线电影路演数据洞察报告.pdf 空间数据智能大模型研究-2024年中国空间数据智能战略发展白皮书.pdf 2024年全球资产管理报告 2024年中型律师事务所的法…

VMware中Ubuntu磁盘空间的清理

最近发现Ubuntu占用空间过大&#xff0c;在网上找了一些方法&#xff0c;在这里总结一下。 1.删除快照 把不需要的快照删除&#xff0c;但要注意删除快照可能会影响到后续的快照链。每个快照依赖于前面的快照。如果删除一个中间快照&#xff0c;虚拟机可能无法找到完整的差异…

零基础入门:创建一个简单的Python爬虫管理系统

摘要&#xff1a; 本文将手把手教你&#xff0c;从零开始构建一个简易的Python爬虫管理系统&#xff0c;无需编程基础&#xff0c;轻松掌握数据抓取技巧。通过实战演练&#xff0c;你将学会设置项目、编写基本爬虫代码、管理爬取任务与数据&#xff0c;为个人研究或企业需求奠…

第2章 矩阵

A 乘以此列向量&#xff0c;1的位置依次往下&#xff0c;所以A的列向量全为0 B C、D 取BE 要统一

通过libx246 libfaac转换推送RTMP音视频直播流

一、RTMP简介及rtmplib库&#xff1a; RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写&#xff0c;它是由Adobe公司提出的一种应用层的协议&#xff0c;用来解决多媒体数据传输流的多路复用&#xff08;Multiplexing&#xff09;和分包&#xff08;packetizing…