Android系统信息与安全机制

查看Android系统信息的软硬件信息

学习内容

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

由于Android手机的可开发性,市场上“拼配置”也成了手机厂商重要宣传点。
要获取系统的配置信息,通常从以下两个方面获取

  • android.os.Build
  • SystemProperty

9.1.1android.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:编译时间

1.2SystemProperty

包含了许多系统配置属性值和参数,很多信息与上面通过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属性

1.3Android系统信息实例

二:Android Apk应用信息获取之PackgeManager

2.1PackageManager

AndroidMainifest结点中的信息被PackageInfo来进行封装。Android系统也提供了PackageManager来负责管理所有已安装的App。

-ActivityInfo
ActivityInfo封装在了Mainfest文件中的< activity >和< eceiver>之间的所有信息,包括name、icon、label、launchMode等。
ServiceInfo
ServiceInfo与ActivityInfo类似,封装了< service>之间的所有信息。
ApplicationInfo
它封装了< application>之间的信息,特别的是,ApplicationInfo包含了很多Flag
FLAG_SYSTEM表示为系统应用
FLAG_EXTERNAL_STORAGE表示为安装在SDcard上的应用
PackageInfo
PackageInfo与前面三个Info类类似,都是用于封装Manifest文件的相关节点信息,而PageageInfo包含了所有的Activity和Service信息。
ResolveInfo
ResolveInfo包含了< intent>信息的上一级信息,所以它可以返回ActivityInfo、ServiceInfo等包含了< 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

下面通过一个实际的例子通过PackageManager筛选不同类型的App,利用ApplicationInfo中的FLAG_SYSTEM来判断:

app.flags & ApplicationInfo.FLAG_SYSTEM

如果当前应用的flags & ApplicationInfo.FLAG_SYSTEM != 0则为系统应用
如果flags & ApplicationInfo.FLAG_SYSTEM <= 0 则为第三方应用
特殊的,当系统应用升级后,也将会成为第三方应用: flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0
如果当前应用的flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0 则为安装在SDCard上的应用
我们封装一个Bean来保存我们所需的字段:

public class PMAppInfo {

    private String appLabel;
    private Drawable appIcon;
    private String pkgName;

    public PMAPPInfo(){
    }

    public String getAppLabel() {
        return appLabel;
    }

    public void setAppLabel(String appLabel) {
        this.appLabel = appLabel;
    }

    public Drawable getAppIcon() {
        return appIcon;
    }

    public void setAppIcon(Drawable appIcon) {
        this.appIcon = appIcon;
    }

    public String getPkgName() {
        return pkgName;
    }

    public void setPkgName(String pkgName) {
        this.pkgName = pkgName;
    }
}

接下来,通过上面所说的判断方法来判断各种类型的应用:

private List<PMAppInfo> getAppInfo(int flag) {
    // 获取PackageManager对象
    pm = this.getPackageManager();
    // 获取应用信息
    List<ApplicationInfo> listAppcations = pm
            .getInstalledApplications(
                    PackageManager.GET_UNINSTALLED_PACKAGES);
    List<PMAppInfo> appInfos = new ArrayList<PMAppInfo>();
    // 判断应用类型
    switch (flag) {
        case ALL_APP:
            appInfos.clear();
            for (ApplicationInfo app : listAppcations) {
                appInfos.add(makeAppInfo(app));
            }
            break;
        case SYSTEM_APP:
            appInfos.clear();
            for (ApplicationInfo app : listAppcations) {
                if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                    appInfos.add(makeAppInfo(app));
                }
            }
            break;
        case THIRD_APP:
            appInfos.clear();
            for (ApplicationInfo app : listAppcations) {
                if ((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
                    appInfos.add(makeAppInfo(app));
                } else if ((app.flags &
                        ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    appInfos.add(makeAppInfo(app));
                }
            }
            break;
        case SDCARD_APP:
            appInfos.clear();
            for (ApplicationInfo app : listAppcations) {
                if ((app.flags &
                        ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                    appInfos.add(makeAppInfo(app));
                }
            }
            break;
        default:
            return null;
    }
    return appInfos;
}

private PMAppInfo makeAppInfo(ApplicationInfo app) {
    PMAppInfo appInfo = new PMAppInfo();
    appInfo.setAppLabel((String) app.loadLabel(pm));
    appInfo.setAppIcon(app.loadIcon(pm));
    appInfo.setPkgName(app.packageName);
    return appInfo;
}

效果图
Android系统信息与安全机制_第1张图片

三:Android Apk应用信息获取之ActivityManager

PackageManager重点在于获取应用的包信息,而ActivityManager在于获取在运行的应用程序信息。

ActivityManager获取应用程序信息封装了不少Bean对象:
ActivityManager.MemoryInfo
MemoryInfo有几个非常重要的字段:availMem(系统可用内存),totalMem(总内存),threshold(低内存的阈值,即区分是否低内存的临界值),lowMemory(是否处于低内存)
Debug.MemoryInfo
这个MemoryInfo用于统计进程下的内存信息
RunningAppProcessInfo
运行进程的信息,存储的字段有:processName(进程名),pid(进程pid),uid(进程uid),pkgList(该进程下的所有包)
RunningServiceInfo
运行的服务信息,在它里面同样包含了一些服务进程信息,同时还有一些其他信息,activeSince(第一次被激活的时间、方式),foreground(服务是否在后台执行)
下面同样通过例子来看看如何使用ActivityManager,我们封装一个Bean来保存我们所需的字段:

public class AMProcessInfo {

    private String pid;
    private String uid;
    private String memorySize;
    private String processName;

    public AMProcessInfo() {
    }

    public String getPid() {
        return pid;
    }

    public void setPid(String pid) {
        this.pid = pid;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getMemorySize() {
        return memorySize;
    }

    public void setMemorySize(String memorySize) {
        this.memorySize = memorySize;
    }

    public String getProcessName() {
        return processName;
    }

    public void setProcessName(String processName) {
        this.processName = processName;
    }
}

接下来,调用getRunningAppProcesses方法,返回当前运行的进程信息,并将我们关心的信息保存到Bean中:

private List<AMProcessInfo> getRunningProcessInfo() {
        mAmProcessInfoList = new ArrayList<AMProcessInfo>();

        List<ActivityManager.RunningAppProcessInfo> appProcessList =
                mActivityManager.getRunningAppProcesses();

        for (int i = 0; i < appProcessList.size(); i++) {
            ActivityManager.RunningAppProcessInfo info =
                    appProcessList.get(i);
            int pid = info.pid;
            int uid = info.uid;
            String processName = info.processName;
            int[] memoryPid = new int[]{pid};
            Debug.MemoryInfo[] memoryInfo = mActivityManager
                    .getProcessMemoryInfo(memoryPid);
            int memorySize = memoryInfo[0].getTotalPss();

            AMProcessInfo processInfo = new AMProcessInfo();
            processInfo.setPid("" + pid);
            processInfo.setUid("" + uid);
            processInfo.setMemorySize("" + memorySize);
            processInfo.setProcessName(processName);
            mAmProcessInfoList.add(processInfo);
        }
        return mAmProcessInfoList;
    }

效果图
Android系统信息与安全机制_第2张图片

四:解析Packages.xml获取系统信息

系统初始化的时候,PackagesManager的底层实现类PackageManagerService会去扫描系统中的一些特定的目录,并解析其中的Apk文件。同时,Android把它获得的应用信息,保存在XML文件中,做成一个应用的花名册,当系统安装,删除,升级时,它也会更新。这个花名册就是位于/data/system/目录下的——packages.xml文件,
通过ADB Pull命令把它导出到本地,如图

Android系统信息与安全机制_第3张图片
packages.xml文件包含的信息点标签

< permissions>标签
permissions标签定义了目前系统所有的权限,并分为两类:系统定义的和Apk定义的。

< package>标签
package代表的是一个apk的属性,其中各节点的信息含义大致为
name:APK的包名
cadePath:APK安装路径,主要在system/app和data/app两种,前者是厂商定制的Apk,后者是用户安装的第三方Apk
userid:用户ID
version:版本

< perms>标签
对应Apk的AndroidManifest文件中的< uses-permission>标签,记录Apk的权限信息

五:Android安全机制

Google建立了一层层堡垒,保护Android的核心安全,免遭外界的攻击。

5.1Android安全机制简介

5道防线来保护Android系统的安全。

  1. 第一道防线——代码安全机制——代码混淆proguard——由于Java语言的特殊性,即使是编译成Apk的应用程序也存在被反编译的风险。而proguard则是在代码层面上对Android应用程序App的第一重保护,它可以混淆关键代码,替换命名让破坏者阅读困难,同时可以压缩代码,优化编译后的字节码。

  2. 第二道防线——应用接入权限控制——AndroidMainifest文件权限声明,权限检查机制——任何应用程序App在使用Android受限资源的时候,都需要显示向系统声明所需要的权限,只有当一个应用app具有相应的权限,才能在申请受限资源的时候,通过权限机制的检查并使用系统的BInder对象完成对系统服务的调用。但是也有先天性的不足,如下

  • 被授予的权限无法停止
  • 在应用声明app使用权限时,用户无法针对部分权限进行限制
  • 权限的声明机制与用户的安全理念相关
    首先判断名称如果为空,直接返回PERMISSION_DENIED.。
    其次判断Uid。如果为0,则为Root权限,不做权限限制;如果为system server的uid则为系统服务,不做权限限制;如果Uid与参数中的请求Uid不同,则返回PERMISSION_DENIED.
    最后,通过调用PackageManagerService.checkUidPermission()方法判断该uid是否具有相应的权限。该方法会去XML的权限列表和系统级的platform.xml中进行查找。
    通过上面的步骤,Android就确定了使用者是否具有某项使用权限。
    3.第三道防线——应用签名机制——数字证书。
    Android中所有的App都会有一个数字证书,这就是App的签名,数字证书用于保护App的作者对其App的信任关系,只有拥有相同数字签名的App,才会在升级时被认为是同一个App。而且Android系统不会安装没有签名的App。
    4.第四道防线——Linux内核层安全机制——Uid,访问权限控制——Android本质是基于Linux内核开发的,所以Android同样继承了Linux的安全特性,比如文件访问机制,Linux 文件系统的权限控制是由user,group,other与读(r),写(w),执行(x)的不同组合来实现的。同样,Android也实现了这套机制,通常情况下,只有System,root用户才有权限访问到系统文件,一般用户访问不到。
    5.第五道防线——Android虚拟机沙箱机制——沙箱隔离——Android的App运行在虚拟机中,因此才有沙箱机制,可以让应用之间隔离。通常情况下,不同应用之间不能互相访问,每个App都有与之对应的Uid,每个App也运行在单独的虚拟机中,与其他应用完全隔离。在实现安全机制的基础上,也让应在这里插入代码片用之间能够互不影响,即使一个应用崩溃,也不会导致其他应用异常。

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

5.2Android系统安全隐患

  1. 代码漏洞——任何程序都有代码漏洞,只能通过升级系统OS版本,更新补丁,才能杜绝利用漏洞的攻击者。
  2. Root风险——Root权限是指Android的系统管理员权限,类似于Windows中的Administrator.具有Root权限的用户可以访问和修改手机中几乎所有的文件。Root掉手机后可以解锁很多普通用户无法完成的工作,比如限制各个应用App的数据流量,系统文件管理,自定义修改系统等,但同时手机的安全性也会因此大打折扣。随着Android系统越来越完善,需要Root的必要性也越来越低,普通用户在不Root的情况下,完全可以正常使用大多数App。需要Root权限的大多数为一些开发者,由于开发的需要,不得不将手机Root。而Root后的手机,就少了一层Linux的天然屏障,整个系统核心就完全暴露在入侵者面前,在你没有察觉的时候大肆破坏。
  3. 安全机制不健全——由于Android权限管理机制并不完美,所以很多手机开发商,通常会在ROM中增加自己的一套权限管理工具来帮助用户控制手机中应用的权限,比如三星手机的应用程序许可。
  4. 用户安全意识——用户对应用申请的权限应有自我判断。
  5. Android开发原则与安全——Android与iOS系统非常显著的区别就是一个是开放系统一个是封闭系统,开放:技术进步快,产品丰富;封闭:安全性高,可控性高。Google本着开源的精神开放了Android的源代码,但随之而来的各种安全问题也让Android饱受诟病,过渡的开放与可定制化,不仅造成了android的碎片化严重,同时也给很多不法应用以可乘之机。

5.3Android Apk反编译

Android应用程序apk文件,就是一个压缩文件,。先使用解压工具解压apk文件,会发现资源文件等xml文件基本无法打开,即使打开也是乱码,乱码是经过android进行加密过的文件。且找不到源代码文件src。

三个反编译工具,负责反编译不同的部分。

  1. apktool
  2. dex2jar
  3. jdgui

apktool.jar可以把xml那些资源文件解析出来,dex2jar可以把dex文件转成jar文件,最后通过jdgui把jar文件转成src源代码(自己在网上下载的akptoolaid)

5.4Android Apk加密

由于Java字节码的特殊性,使得它非常容易被反编译。为了更好的对Java Class文件进行一些保护,通常会使用ProGuard来对Apk进行混淆处理,用无意义的字母来重命名类,字段,方法和属性。当然ProGuard不仅仅可以用来混淆代码,还可以删除无用的类,字段,方法,和属性,以及删除无用的注释,最大限度地优化字节码文件。

Android Studio中,可以非常方便地使用ProGuard,在Gradle Scripts文件夹下,打开build.gradle(Module:app)文件,显示如下所示

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

minifyEnabled设置为true就可以打开ProGur=ard功能,getDefaultProguardFile是系统默认的混淆规则,它位于SDK目录 /tools/proguard/proguard-android.txt目录下,大部分情况使用这个默认的混淆规则就可以了;后面一部分是项目中自定义的混淆文件
Android系统信息与安全机制_第4张图片
在这个文件里可以定义引入第三方依赖包的混淆规则。配置好后使用AS导出Apk,就可以生成混淆。

你可能感兴趣的:(群英传读书笔记)