第九章 Android 系统信息与安全机制

玩了这么久的Android设备,作为一个开发者,其实需要比普通用户知道更多关于Android 系统的信息,就算不知道,也需要知道怎么轻松获取的方式

  • Android系统信息的获取
  • PackageManager的使用
  • ActivityManager的使用
  • Android安全机制
Android系统信息的获取

由于android手机的开源性,手机的配置各种各样,那些优化大师之类的东西,都可以跑分和看配置信息,那他们是从哪里知道这些信息的呢?遥想获取系统的配置信息,通常可以从以下两个方面获取

  • android.os.Build
  • SystemProperty
1.android.os.Build

android.os.Build类里面的信息非常的丰富,它包含了系统编译时的大量设备,配置信息,我们列举一点

  • Build.BOARD——主板
  • Build.BRAND——Android系统定制商
  • Build.SUPPORTED_ABIS——CPU指令集
  • Build.DEVICE——设备参数
  • Build.DISPLAY——显示屏参数
  • Build.FINGERPRINT——唯一编号
  • Build.SERIAL——硬件序列号
  • Build.ID——修订版本列表
  • Build.MANUFACTURER——硬件制造商
  • Build.MODEL——版本
  • Build.HARDWARE——硬件名
  • Build.PRODUCT——手机产品名
  • Build.TAGS——描述Build的标签
  • Build.TYPE——Builder类型
  • Build.VERSION.CODENAME——当前开发代号
  • Build.VERSION.INCREMENTAL——源码控制版本号
  • Build.VERSION.RELEASE——版本字符串
  • Build.VERSION.SDK_INT——版本号
  • Build.HOST——host值
  • Build.USER——User名
  • Build.TIME——编译时间

上面的一些参数没有注释,他们来自系统的RO值中,这些值都是手机生产商配置的只读的参数值,根据厂家的配置不同而不同,接下来我们再来看一下另一个存储设备软硬件信息的类——SystemProperty

2.SystemProperty

SystemProperty类包含了许多系统配置属性值和参数,很多信息和上面通过android.os.Build获取的值是相同的,我们列举一些常用的

  • os.version——OS版本
  • os.name——OS名称
  • os.arch——OS架构
  • user.home——home属性
  • user.name——name属性
  • user.dir——Dir属性
  • user.timezone——时区
  • path.separator——路径分隔符
  • line.separator——行分隔符
  • file.separator——文件分隔符
  • java.vendor.url——Java vender Url属性
  • java.class.path——Java Class属性
  • java.class.version——Java Class版本
  • java.vendor——Java Vender属性
  • java.version——Java版本
  • java.home——Java Home属性
3. Android系统信息实例

废话不多说,直接上例子吧

        textView = findViewById(R.id.textView);

        stringBuilder = new StringBuilder();
        stringBuilder.append("\n Build.BOARD ==="+ Build.BOARD);
        stringBuilder.append("\n Build.BRAND ==="+ Build.BRAND);
        stringBuilder.append("\n Build.SUPPORTED_ABIS ==="+ Build.SUPPORTED_ABIS);
        stringBuilder.append("\n Build.DEVICE ==="+ Build.DEVICE);
        stringBuilder.append("\n Build.DISPLAY ==="+ Build.DISPLAY);
        stringBuilder.append("\n Build.FINGERPRINT ==="+ Build.FINGERPRINT);
        stringBuilder.append("\n Build.SERIAL ==="+ Build.SERIAL);

        stringBuilder.append("\n Build.HOST ==="+ Build.HOST);
        stringBuilder.append("\n Build.USER ==="+ Build.USER);
        stringBuilder.append("\n Build.TIME ==="+ Build.TIME);
        stringBuilder.append("\n ================================");
        stringBuilder.append("\n version ==="+ System.getProperty("os.version"));
        stringBuilder.append("\n name ==="+ System.getProperty("os.name"));
        stringBuilder.append("\n arch ==="+ System.getProperty("os.arch"));
        stringBuilder.append("\n home ==="+ System.getProperty("user.home"));
        stringBuilder.append("\n name ==="+ System.getProperty("user.name"));
        stringBuilder.append("\n dir ==="+ System.getProperty("user.dir"));
        stringBuilder.append("\n timezone ==="+ System.getProperty("user.timezone"));
        stringBuilder.append("\n path separator ==="+ System.getProperty("path.separator"));
        stringBuilder.append("\n line separator ==="+ System.getProperty("line.separator"));
        stringBuilder.append("\n file separator ==="+ System.getProperty("file.separator"));
        stringBuilder.append("\n java.vendor.url ==="+ System.getProperty("java.vendor.url"));
        stringBuilder.append("\n java.class.path ==="+ System.getProperty("java.class.path"));
        stringBuilder.append("\n java.class.version ==="+ System.getProperty("java.class.version"));
        stringBuilder.append("\n java.vendor ==="+ System.getProperty("java.vendor"));
        stringBuilder.append("\n java.version ==="+ System.getProperty("java.version"));
        stringBuilder.append("\n java.home ==="+ System.getProperty("java.home"));

        textView.setText(stringBuilder);

Android Apk 应用信息获取之 PackageManager

  • PackageManager


    Package结构

最里面的框就代表整个Activity的信息,系统提供了ActivityInfo类来进行封装
而Android提供了PackageManager来负责管理所有已安装的App,PackageManager可以获得AndroidManifest中不同节点的封装信息,下面是一些常用的封装信息:

  • ActivityInfo

ActivityInfo封装在了Mainfest文件中的< activity >和< receiver>之间的所有信息,包括name、icon、label、launchMode等。

  • ServiceInfo

ServiceInfo与ActivityInfo类似,封装了< service>之间的所有信息。

  • ApplicationInfo

它封装了< application>之间的信息,特别的是,ApplicationInfo包含了很多Flag,FLAG_SYSTEM表示为系统应用,FLAG_EXTERNAL_STORAGE表示为安装在SDcard上的应用,通过这些flag可以很方便的判断应用的类型。

  • PackageInfo

PackageInfo包含了所有的Activity和Service信息。

  • ResolveInfo

ResolveInfo包含了< intent>信息的上级信息,所以它可以返回ActivityInfo、ServiceInfo等包含了< intent>的信息,经常用来帮助找到那些包含特定intent条件的信息,如带分享功能、播放功能的应用。
有了这些封装的信息后,还需要有特定的方法来获取它们,下面就是PackageManager中封装的用来获取这些信息的方法:

  • getPackageManager()——通过这个方法可以返回一个PackageManager对象。

  • getApplicationInfo()——以ApplicationInfo的形式返回指定包名的ApplicationInfo。

  • getApplicationIcon()——返回指定包名的Icon。

  • getInstalledApplications()——以ApplicationInfo的形式返回安装的应用。

  • getInstalledPackages()——以PackageInfo的形式返回安装的应用。

  • queryIntentActivities()——返回指定Intent的ResolveInfo对象、Activity集合。

  • queryIntentServices()——返回指定Intent的ResolveInfo对象、Service集合。

  • resolveActivity()——返回指定Intent的Activity。

  • resolveService()——返回指定Intent的Service。

根据ApplicationInfo的flag来判断App的类型:

  • 如果当前应用的flags & ApplicationInfo.FLAG_SYSTEM != 0则为系统应用

  • 如果flags & ApplicationInfo.FLAG_SYSTEM <= 0 则为第三方应用

  • 特殊的当系统应用升级后也会成为第三方应用,此时 flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0;

  • 如果flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0 则为安装在SDCard上的应用。

主要代码粘过来,很简单的

package com.example.androidsystem;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

/**
* Created by Younger on 2018/3/12.
*/
public class PMManageActivity extends AppCompatActivity implements View.OnClickListener {
   private PackageManager mPackageManager;

   private ListView mListView;
   private PackageAdapter mAdapter;
   List<PMBean> result;
   @Override
   protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main_list_activity);
       mPackageManager = getPackageManager();
       mListView = (ListView) findViewById(R.id.mListView);
       mAdapter = new PackageAdapter(this);
       mListView.setAdapter(mAdapter);
       findViewById(R.id.btn_all).setOnClickListener(this);
       findViewById(R.id.btn_other).setOnClickListener(this);
       findViewById(R.id.btn_system).setOnClickListener(this);

   }

   @Override
   public void onClick(View view) {
       switch (view.getId()) {
           case R.id.btn_all:
               result = getAppInfo(R.id.btn_all);
               break;
           case R.id.btn_other:
               result = getAppInfo(R.id.btn_other);
               break;
           case R.id.btn_system:
               result = getAppInfo(R.id.btn_system);
               break;
           default:
               result = new ArrayList<>();
       }
       mAdapter.addAll(result);
   }

   private List<PMBean> getAppInfo(int flag) {
       List<ApplicationInfo> appInfos = mPackageManager.getInstalledApplications(
               PackageManager.GET_UNINSTALLED_PACKAGES);
       List<PMBean> list = new ArrayList<>();
       //根据不同的flag来切换显示不同的App类型
       switch (flag) {
           case R.id.btn_all:
               list.clear();
               for (ApplicationInfo appInfo : appInfos) {
                   list.add(makeAppInfo(appInfo));
               }

               break;
           case R.id.btn_other:
               list.clear();
               for (ApplicationInfo appInfo : appInfos) {
                   if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                       list.add(makeAppInfo(appInfo));
                   } else if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0){
                       list.add(makeAppInfo(appInfo));
                   }
               }
               break;
           case R.id.btn_system:
               list.clear();
               for (ApplicationInfo appInfo : appInfos) {
                   if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                       list.add(makeAppInfo(appInfo));
                   }
               }
               break;
       }
       return list;
   }

   private PMBean makeAppInfo(ApplicationInfo appInfo) {
       PMBean info = new PMBean();
       info.setAppIcon(appInfo.loadIcon(mPackageManager));
       info.setAppLabel(appInfo.loadLabel(mPackageManager).toString());
       info.setPkgName(appInfo.packageName);
       return info;
   }

}

Android Apk 应用信息获取之 ActivityManager

PackageManager 重点在于获得应用的包信息,ActivityManager 重点在于获取运行的应用程序信息, 同PackageManager一样,ActivityManager也封装了不少的Bean对象,我们选几个重点来说一下

  • ActivityManager.MemoryInfo

MemoryInfo有几个非常重要的字段:availMem(系统可用内存),totalMem(总内存),threshold(低内存的阈值,即区分是否低内存的临界值),lowMemory(是否处于低内存)。

  • Debug.MemoryInfo

这个MemoryInfo用于统计进程下的内存信息。

  • RunningAppProcessInfo

运行进程的信息,存储的字段有:processName(进程名),pid(进程pid),uid(进程uid),pkgList(该进程下的所有包)

  • RunningServiceInfo

运行的服务信息,在它里面同样包含了一些服务进程信息,同时还有一些其他信息。activeSince(第一次被激活的时间、方式),foreground(服务是否在后台执行)。

获取ActivityManager
activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
/**
     * 正在运行
     * @return
     */
    private List<ActivityManager.RunningAppProcessInfo> getRunningProcossInfo(){
        mAMProcessInfo = new ArrayList<>();
        List<ActivityManager.RunningAppProcessInfo>appRunningList = activityManager.getRunningAppProcesses();

        for (int i = 0;i<appRunningList.size();i++){
            ActivityManager.RunningAppProcessInfo info = appRunningList.get(i);
            int pid = info.pid;
            int uid = info.uid;
            String procossName = info.processName;
            int[]memoryPid = new int[]{pid};
            Debug.MemoryInfo[] memoryInfos = activityManager.getProcessMemoryInfo(memoryPid);

            int memorySize = memoryInfos[0].getTotalPss();

            AMProcessInfo processInfo = new AMProcessInfo();
            processInfo.setPid(""+pid);
            processInfo.setUid(""+uid);
            processInfo.setMemorySize(""+memorySize);
            processInfo.setProcessName(procossName);
            appRunningList.add(processInfo);
        }
        return  appRunningList;
    }
解析Packages.xml获取系统信息

熟悉Android开机启动流程的朋友大概知道,在系统初始化到时候,packagemanager的底层实现类packagemanagerService会去扫描系统的一些特定目录,并且解析其中的Apk文件,同时Android把他获取到的应用信息保存到xml中,做成一个应用的花名册,就是data/system/apckages.xml,我们用adb pull命令把他导出来,里面的信息也太多了,但是我们只要知道结果根节点就可以了

  • < permissions>标签

permissions标签定义了现在系统所有的权限,也分两类,系统定义的和app定义的

  • < package>标签

package代表的是一个apk的属性

其中各节点的信息含义大致为

  • name:APK的包名
  • cadePath:APK安装路径,主要在system/app和data/app两种,前者放系统级别的,后者放系统安装的
  • userid:用户ID
  • version:版本
  • < perms>标签

通过这个xml文件的标签,可以获取到很多手机应用的信息,通常在进行系统层开发的时候,可以通过这个xml获取更多有意义的东西

Android安全机制
  • 第一道防线

代码安全机制——代码混淆proguard
由于java语言的特殊性,即使是编译成apk的应用程序也存在反编译的风险,而proguard则是在代码从上对app的第一道程序,他混淆关键代码,替换命名,让破坏者阅读难,同样也可以压缩代码,优化编译后的字节

  • 第二道防线

应用接入权限控制——清单文件权限声明,权限检查机制,
任何app在使用Android受限资源的时候,都需要显示向系统生命权限,只有当一个应用app具有相应的权限,才能申请相应的资源,通过权限机制的检查并且使用并且使用系统的Binder对象完成对系统服务的调用,但是这道防线也有先天的不足,如以下几项

  • 被授予的权限无法停止
  • 在应用声明app使用权限的时候,用户无法针对部分权限进行限制
  • 权限的判断机制与用户的安全理念相关

Android系统通常按照以下顺序来检查操作者的权限.
首先,判断permission名称.如果为空则直接返回PERMISSION_DENIED
其次。判断Uid,如果为0则为root权限,不做权限控制,如果为systyemsystem service的uid则为系统服务.不做权限控制:如果Uid与参数中的请求uid不同则返回PERMISSION_DENIED
最后,通过调用packagemanageservice.checkUidPermission()方法来判断该uid是否具有相应的权限,该方法会去xml的权限列表和系统级的权限进行查找
通过上面的步骤Android就确定了使用者是否具有某项使用权限

  • 第三道防线

应用签名机制一数字证书。
Android中所有的app都会有个数字证书,这就是app的签名.数字证书用于保护app的作者和其app的信任关系,只有拥有相同数字签名的app,才会在升级时被认为是同一app,而且Android系统不会安装没有签名的App

  • 第四道防线

Linux内核层安全机制一一Uid 访问权限控制。
Animid本质是基于Linux内核开发的,所以Android同样继承了Linux的安全特性,比如Linux文件系统的权限控制是由user,group,other与读,写,执行的不同组合来实现的,同样,Android也实现了这套机制”通常情况下.只有system,root用户才有权限访问到系统文件,而一般用户无法访问。

  • 第五道防线

Android虚拟机沙箱机制——沙箱隔离
Android的App运行在虚拟机中 因此才有沙箱机制,可以让应用之间相互隔离,通常情况下.不同的应用之间不能互相访问.每个App都单独的运行在虚似机中,与其他应用完全隔离.在实现安全机制的基础上,也让应用之间能够互不影响,即时一个应用崩溃,,也不会导致其他应用异常

虽然通过以上的五道防线.仍然不能完全保证Android的核心安全”但却可以在最大程度上给破坏者增加难度,从另一方面来说”这些破坏者的破解也真是推动Android安全机制逐渐健全的动力.

Android系统安全隐患
  • 1.代码漏洞

这个问题存在世界上所有的程序中,没有谁敢保证自己的程序没有bug,有漏洞,如果遇到这种问题,大家只能尽快的升级版本,更新补丁,才能杜绝利用漏洞的攻击装,比如Android的LaunchAnyWhere,FakeId,这些都是bug,就是在编写的时候产生的漏洞,只有期待官方的更新了

    1. root风险

Root权限是指Android的系统管理员权限,类似于windows系统中的Administrator。具有Root权限的用户可以访问和修改手机中几乎所有的文件,“Root”在一段时间内一度成为Android的代名词, 无Root,不Android”。的确,Root掉手机后,可以解锁很多普通用户无法完成的工作,如限制各个应用app的数据流量.系统文件管理丶自定义修改系统等,但同时手机的安全性也会因此大打折扣。随着android系统越来越完善,root的必要性也越来越低普通用户在不root的情况下,完全可以正常使用大部分App。需要Root权限的大多为一些开发者,由于开发的需要,不得不将手机root,而root后的手机,就少了一层Linux的天然屏障,整个系统核心就完全暴露在人侵者面前,在你没有察觉的情况下大肆破坏。所以,针对普通用户,希望都尽量不要Root手机以免带来不必要的损失

    1. 安全机制不健全

由于Android的权限管理机制并不完美,所以很多手机开发商,通常会在RoM中增加自己的一套权限管理工具来帮助用户控制手机中应用的权限,如应用许可

  • 4.用户安全意识

用户对于安全隐患的察觉里也是保护手机安全的一个重要因素。用户可以通过在正规的应用市场下载和安装应用时通过列出来的应用权限申请信息来大致判断一个应用的安全性,比如我们曾经十分喜欢用的xx神器”,其实没有一点技术含量,无非就是在你安装了应用之后遍历一遍你的联系人并发送带有链接的短信而已当用户在安装不明来源的应用时如果一个娱乐类型的app生命权限的时候不仅要联系人又要短信权限,这个时候就需要警惕了,用户也可以在市场上下载一些安全类App,如LEB安全大师,360安全等, 虽然这些软件会加重系统负担,但是为了安全也是值得的

    1. Android开发原则与安全

众所周知,Android与ioS系统一个非常显著的区别就是_一个是开放系统,一个是封闭系统,开放自然有开放的好处,技术进步快,产品丰富,封闭也有封闭的好处,安全性高,可控性高,Google本着开源的精神开放了Android的源代码,但随之而来的各种安全问题也让Android倍受诟病,过度的开放与可定制化,不仅造成了Android的碎片化严重, 同时也给很多不法应用以可乘之机,但可喜的是,随着Android的发展日益壮大,Google也在着手处理开发与安全的问题,相信在不久的将来,这一矛盾会越来越小

Android Apk反编译

关于反编译,看这篇文章就行了 http://unclechen.github.io/2016/09/07/Android%E5%8F%8D%E7%BC%96%E8%AF%91%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/

好了 ,就这些了;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容