Android上隐藏应用程序浅析

手机上有秘密不想被同事、朋友或爱人看到?现在各大主流的手机安全软件纷纷推出“私密空间”或“隐私信箱”等功能,用来存放私密文件。“私密空间”可隐藏你的短信、电话、照片等内容,甚至可以隐藏程序本身,使得该程序的图标从桌面上消失。这就引入了两个问题:

1、  该应用真的“彻底”的从手机设备上消失了吗,用户无法找到该应用的任何信息?

2、  该应用仅仅可以隐藏自己,它能够隐藏其他应用吗?

    下面将对这两个问题进行深入分析。

 

   一、 案例分析

以“网秦安全”推出的一款“私密空间”为例,其可以设置隐身模式,隐身模式开启后,私密空间的图标将从手机中消失,这样别人就不知道您在使用私密空间了。在隐身模式下,可以通过拨打“##私密空间密码”快速进入私密空间。

首先回答上面提出的第一个问题。以私密空间为例,在“设置”->“应用”中可查到该


应用仍然存在,且正在运行。如下图所示。

Android上隐藏应用程序浅析

我们来大胆分析“私密空间”的实现原理:

1、           它调用安卓提供的一个SDK接口setComponentEnabledSetting()将自己的入口activity disable了,这样,它的图标就会从launcher界面消失。

2、          同时,setComponentEnabledSetting()输入参数中的有一个flag位用来标志是否杀死该进程,私密空间在disable自己的同时,选择的是DONT_KILL_APP,我们通过在framework层加入log证实了以上几点。而在PMS的内部逻辑中,对于DONT_KILL_APP这个标志位,在enable或者disable的时候,会发送pending broadcast来广播这件事,这也就解释了为什么在“私密空间”中更改隐身状态(从非隐身变成隐身,或从隐身状态变成非隐身)后,该应用图标的出现或者消失会需要一段时间才能生效(而网秦安全的私密空间要求用户重启设备,实际上这是不必要的,只是需要一段时间才能生效)。

3、    通过shell到手机设备上,可看到,在/data/system/users/xxx/package-restrictions.xml(其中xxxuserId)中,会记录被enabledisablecomponent。下面两张图就是“网秦安全”的“私密空间”在隐身和非隐身状态下的记录。

Android上隐藏应用程序浅析

Android上隐藏应用程序浅析

存在缺陷:

1、  此方法需要被隐藏的应用在自己的代码中有相应的逻辑处理,比如,disable状态下的组件,需要先被enable起来,才能启动。因此,在启动并运行后,若退出该应用,则该应用图标会出现在主界面上。因此,对于“私密空间”,我们大胆猜测,在该应用退出之前,会判断自己是否处于隐身状态,若是,则先把自己disable,再退出。因此,目标应用(需要被隐藏的应用)的隐藏需要自身代码的逻辑处理,也就造成了该功能的局限性。

2、  SDK接口在framework中的内部权限检查只允许rootsystem用户或应用程序自己使用该方法。这也就回答了上面的第二个问题,一个普通的第三方应用不能对其他应用调用该API,从而导致使用此方法只能达到隐藏自己的作用,无法隐藏其他应用。

而我们的目标是:能够随意地隐藏掉手机设备上的任意一个应用,而不需要该应用的配合,让它从launcher界面上消失,但又不影响它的运行,并通过合适的方式把它启动起来。

二、突破和改进

目前,我们的技术可以实现这一目标:对于所有出现在launcher界面的应用,让用户选择哪些需要被隐藏,对于被隐藏的应用,我们可以让用户通过一定的形式,直接启动该应用,退出应用后,该应用仍然处于“隐身”状态。若该应用被卸载再安装,仍不会出现在launcher界面。

我们不需要通过第三方应用实现,这样就避免了第三方应用申请root权限,从而导致系统因为root而造成的安全性降低。我们必须有手机厂商对Android系统进行定制化修改,添加一个具有root权限的service来管理设置被隐藏应用的包名(以下简称为黑名单)。其他进程可通过这个service获得黑名单。App应用则必须遵循一定的协议和授权才能和这个service沟通,以达到安全的目的。

1、  init.rc中添加一个service,并授予它root权限。该service起来之后,等待client端的请求。并对client端暴露了一套SDK接口,app应用通过调用这套API接口,与service通信,设置被隐藏应用黑名单,获取黑名单等操作。

以下是我们提供的部分SDK API接口:

public boolean setHideAppPolicy(String pkgName, boolean flag);//设置被隐藏应用

public boolean getHideAppPolicy(String pkgName);//获取应用的隐藏状态

public List queryHideAppPolicy();//获取被隐藏应用黑名单

2、  Android framework层的PackageManagerServicePMS)中设置hook点,每当用户设置了黑名单后,黑名单被传递给PMS,我们在PMS的某些关键函数(比如installPackageLIscanPackageLI)的入口处进行hook,根据黑名单中的各个应用的包名,解析出该包内是否含有在launcher上有入口的组件,若有,则修改组件信息。

3、  当包括launcher在内的任何程序需要获取主界面上的组件信息时,都无法获得黑名单上应用的组件信息,从而达到“隐藏”它们的效果。当用户希望取消某个应用的隐藏状态时,我们再通过一定的方式在PMS中还原该应用的入口组件信息。

4、  通过PMS获取每个被隐藏应用的入口组件信息,并传递回serviceapp层可通过与service通信获取该信息,即可通过显示startActivity的方式将各个处于被隐藏状态的应用启动起来,同时也保证不会影响它们在launcher上的显示状态。SDK提供的API接口为:

public Map queryHideAppInfo();//获取被隐藏应用黑名单入口信息

 

我们从系统级入手,不依靠某一个应用程序来完成隐藏应用的功能,而是通过修改目标应用(用户希望隐藏的应用)的信息,使得即使更换桌面浏览器,也依然无法显示它们。同时,在用户不需要隐藏它们时,再将它们的信息还原,并且保证在这一系列操作中,不破坏或影响被隐藏应用的使用

当然,我们的实现方式并不是唯一的,也不是最全面的。由于隐藏应用程序这一功能尚未有明确的标准和定位,市场上的类似功能也不多见,因此存在着一定的争议:

1、对于被隐藏的应用,需不需要让其在设备上“彻底”消失?即:不管是普通用户通过手机上的“设置”->“应用”,还是开发工程师通过调用SDK API接口查询PackageInfo,都无法得到被隐藏应用的信息。只有设置隐藏应用这一操作的手机用户自己可以通过我们的一个加密入口,才能找到被自己隐藏了的应用,并可将它们启动起来。从技术上说,我们可以通过修改packageInfo来达到这个目的。

2、针对被隐藏的应用,在隐身状态下,需不需要仍在后台运行?

2.1) 若维持被隐藏应用在后台运行,其目的也就是手机用户希望手机上的某些应用虽然在运行,但不能被他人随便launch起来。这就牵扯到两点:

i) 被隐藏应用在后台运行,但不发送消息,比如通知栏消息,toast等。屏蔽通知栏消息,并在被隐藏应用取消隐藏状态后,重新恢复通知栏消息推送,这是技术可行的。我们目前并未实现这一点,是由于用户需求的不明确。

ii) 被隐藏应用在后台运行,但可以接收、发送消息。比如微信、陌陌、qq等在接收到新消息后,可以发送通知栏消息以提示用户,用户可以随时launch它们。又例如用户希望某些被隐藏应用在后台继续下载东西。我们已经实现了这一点。

2.2) 禁止被隐藏应用在后台运行。一旦某个应用被隐藏,则直接kill掉该process,停止其工作。这一举措可以节省系统资源、省电等,但用户在需要使用它们的时候必须重新启动这些应用程序。


用户的潜在需求是推动技术进步的动力,然而对于这样一个尚未成型的新技术,用户的潜在需求总是比我们能想到的多。若各位看官有独到的见解或特殊的需求,若大家对这一技术感兴趣,欢迎共同商讨,以寻找更有价值的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值