二、Android安全机制之系统防线

1、Android基于Linux内核的访问控制机制

    Android本质是基于Linux内核开发的,所以同样继承了Linux的文件访问机制,Linux文件系统权限控制由user、group、other与读(r)、写(w)、执行(x)的不同组合来实现的。同样,Android也实现了这套机制,通常情况下,只有System、root用户才有权限访问到系统文件。举个例子,做串口开发的时候,普通用户是无法访问/dev下的串口设备,在获取到root权限后,通过执行chmod 777命令即可获得读写执行权限,即可正常使用串口读写。

2、Android虚拟机沙箱机制

    沙箱的概念:对使用者来说可以理解为一种安全环境,对恶意访问者来说是一种限制。

    Android底层是linux,linux中一个用户对应一个uid和gid,而在android中,用户变成了一个个应用。在应用安装的时候,linux会分配给应用独立的空间、系统安装服务PackageManagerService会分配应用的uid和gid,应用在独立的Dalvik虚拟机中运行,即每一个Android应用程序都在它自己的进程中运行,有独立的空间和资源。

    我们知道,APK所运行的进程是由另外一个系统服务ActivityManagerService负责启动的。ActivityManagerService在启动APK进程之前,会先向PackageManagerService查询APK安装时分配到的uidgid。有了APK的uidgid后,ActivityManagerService就向另外一个以root身份运行的Zygote进程发出创建APK进程的请求。Zygote进程收到请求之后,就会fork出一个子进程来作为请求创建的APK进程。而Zygote进程fork出来的子进程,也就是APK进程,在一开始的时候也是以root身份运行的。不过,APK进程在可以执行APK代码之前,会通过系统接口setUid将自己的uid设置为APK安装时分配到的uid。从而改变了身份,即不再是root了,这个过程与传统的Linux系统通过login进程启动用户shell进程的过程非常类似。

    Android允许应用访问属于自己的目录资源和权限允许的资源,理论上不同应用是不能访问属于其他应用的资源。但是可以通过给应用签同样的签名,并且配置相同的uid可以实现资源共享。比如我们在开发系统应用的时候,除了用系统签名然后push到SystemApp目录下这种方式外,还可以在用了系统签名后通过设置android:sharedUserId="android.uid.system"让应用获得系统权限。

    除了共享内存外,安卓中实现进程通信的还有AIDL(底层基于Binder),Messagen(基于AIDL),广播,Intent,Socket,文件共享,ContentProvider,开源框架有HermesEventBus(进程通信级别的事件总线),如果使用NDK,那么还有管道的方式。

3、Android应用权限机制

    任何应用程序App在使用Android受限资源的时候,都需要显示向系统声明所需要的权限,Android权限级别分为4级:

  Normal级申请就可以使用;

  Dangerous级需要安装时由用户确认,6.0后使用前需要用户确认;

  Signature级需要签名相同才能使用;

  SignatureOrSystem级则必须是系统应用才可用。

4Android应用程序签名机制

    做安卓开发的都知道Apk要想安装到系统中就得先签名,签名能保证Apk安全,但是具体怎么保证安全却是不甚了解。那么这里其实就是Android应用程序签名机制来保证的。

    Apk中的签名信息都存储在META-INF中:


    打开META-INF文件夹可以看到有如下三个文件,逐一介绍:


1、MANIFEST.MF


    MANIFEST.MF的作用就是遍历Apk里面的所有文件(不包含META-INF),如果是一个文件,就用SHA256(或者SHA1)消息摘要算法提取出该文件的数字摘要然后进行BASE64编码后,作为“SHA-Digest”属性的值,然后加上此文件在apk包中的路径作为“Name”属性的值一并写入到MANIFEST.MF文件中的一个块中。

    SHA算法是一种数字摘要算法,类似MD5,不可逆,在不考虑碰撞的情况下不同文件的数字签名一定不一样。SHA1输出是160位,SHA256输出256位,SHA256是SHA1升级版,强度高,但速度较慢。可通过-digestalg SHA1来指定使用的算法,默认采用SHA256。


    除了META-INF,只要Apk中的任一文件被修改就会造成MANIFEST.MF不一样,保证了唯一性,因为META-INF是生成存储签名的文件夹,所以其本身不参与签名过程,所以这个文件夹是可以添加和修改文件的,美团的多渠道打包就是据此原理。

2、CERT.SF


CERT.SF的作用有两个:

1,计算这个MANIFEST.MF文件的SHA值,再经过BASE64编码后,记录在CERT.SF的SHA1-Digest-Manifest”属性值下

2,计算MANIFEST.MF文件中每一个块的SHA值,并经过BASE64编码后,记录在CERT.SF中的“name”值相同的块中且属性名字为“SHA-256-Digest”的值下。

3、CERT.RSA

CERT.RSA的内容如下图:


    这里用签名文件里的私钥加密CERT.SF文件,  然后将CERT.SF密文以及公钥一同写入CERT.RSA中。

4、那这三个文件是如何保证Apk唯一的呢,系统安装Apk的时候,会逐一校验这三个文件,每层校验都通过才认为是官方原装正版,允许安装。如果Apk中的任一文件被篡改,系统计算的数字摘要与MANIFEST.MF文件不一样校验失败,停止安装,如果你修改MANIFEST.MF通过了第一层校验,第二层又会导致CERT.SF校验失败,停止安装,如果你修改了CERT.SF通过了第二层校验,那么在第三层的终极BOSS会让你绝望,第三层系统通过RSA公钥解密CERT.SF密文,发现明文不一致,校验失败,停止安装。那CERT.RSA能修改伪造吗?明显是不行了,根据非对称加密原理,在没有私钥的情况下,是无法加密生成能被对应公钥能解密的密文的。此时要想安装成功,只能用非官方的签名文件来签名,但是因为签名文件不一样,在安装到系统中就会被杀毒软件认为是破解版,病毒应用。

 

5、Android内存管理机制

1、Linux与Window的内存管理机制的区别

    Linux进程退出并不会立刻死,而是在系统内存吃紧的时候再来按照优先级杀掉进程,释放内存,Windows的进程在退出时会杀掉进程,将内存释放干净。Android继承前者。

2、Android进程优先级是怎么划分的

    在framework层,ActivityManager的内部类RunningAppProcessInfo里定义了10个进程级别:


  1.前台进程(比如正在显示可交互的Activity所在的进程)
  2.前台服务进程(比如前台Service)
  3.前台休眠进程(比如前台进程锁屏后的状态,1像素保活策略就是居于此)
  4.可见进程(比如系统在当前Activity弹出窗口,Activity进入onPause可见但不可交互)
  5.可感知进程(比如后台播放音乐的进程,某咚播放无声音乐的保活策略就是居于此)
  6.不能保存状态进程(这些进程不能保存状态,所以系统尽量不杀它)
  7.服务进程(比如后台运行的Service进程)
  8.后台进程(比如按Home键后后台运行的进程)
  9.空进程(不包含任何组件的进程,其作用是缓存进程,以便于下次快速启动一个组件)
  10.已死进程
 以上进程划分以api25即安卓7.1版本的代码为例,不同的系统版本有不同的划分,比如8.0版本的代码定义成如下:


    可以看到相比7.1版本的代码,8.0用注解的方式做了类型安全,并且把后台进程和空进程统一归为了缓存进程。这里我们也可以仿照谷歌,在做类型安全的时候尽量避免用枚举,而应采用注解的方式。

3、Android系统内存回收流程

    系统有两个重要的文件,adj和minfree,adj保存着当前系统杀进程的oom_adj_score,minfree则是保存着系统剩余内存对应的阈值(单位:page,1page=4kb),当达到对应阈值则根据对应的进程级别来杀死,它们分别在如下路径

/sys/module/lowmemorykiller/parameters/adj

/sys/module/lowmemorykiller/parameters/minfree


    每个进程都有其对应的oom_adj,oom_adj代表了进程所处的级别可通过下图所示方式查看,进程Activity的可见或者不可见状态其值也不一样,下图分别是在前台和后台时,其oom_adj的值。而进程是否被kill是根据其oom_adj_score的大小来判定的,oom_adj_score是由oom_adj、内存占用、启动时间等多种因素计算出来,值大的优先被kill。


    举个例子,当系统内存剩余为30720*4kb约等于122m的时候开始清oom_adj_score大于529的进程,LMK(lowmemorykiller)遍历所有进程,找到oom_adj_score大于529,且是最大的进程,如果出现值相等的情况则选择占用内存较大的进程,通过发送SIGKILL信号执行kill。

    所以在进程常驻的问题上,其中的一个思路就是尽量提升进程级别,从而降低oom_adj,再者就是优化内存,避免内存泄漏,减少内存的占用,就可以尽量的避免被系统kill了。










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值