Android群英傳知識點回顧——第九章:Android系統信息與安全機制
- 9.1 Android系統信息獲取
- 9.1.1 android.os.Build
- 9.1.2 SystemProperty
- 9.1.3 Android系統信息實例
- 9.2 Android Apk應用信息獲取之PackageManager
- 9.2.1 PackageManager
- 9.3 Android Apk應用信息獲取之ActivityManager
- 9.4 解析Packages.xml獲取系統信息
- 9.5 Android安全機制
- 9.5.1 Android安全機制簡介
- 9.5.2 Android系統安全隱患
- 9.5.3 Android Apk反編譯
- 9.5.4 Android Apk加密
要獲取系統的配置信息,通常可以從以下兩個方面獲取:
- android.os.Build
- SystemProperty
該類包含系統編譯時大量設備、配置信息:
- 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:編譯時間
SystemProperty包含了許多系統配置屬性值和參數:
- 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屬性
上面列舉了那麽多,讓我們通過代碼獲取他們的系統信息:
我們還可以通過命令行模式查看系統信息:
- 命令行模式進入system/build.prop文件目錄,使用cat build.prop命令查看文件信息
我們還可以通過adb shell的getprop來獲取對應的屬性值:
- 進入adb shell,使用getprop ro.build.id獲取信息
還有一個非常重要的目錄存儲系統信息,那就是/proc目錄:
- 命令行模式進入/proc文件目錄,使用cat cpuinfo命令打開cpuinfo文件查看系統信息
看了這麽多系統信息,應該看Apk應用信息了,在ADB Shell命令中,有兩個非常強大的助手,PM和AM,PM主宰著應用的包管理,而AM主宰著應用的活動管理
- 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來判斷:
- 如果當前應用的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來保存我們所需的字段:
接下來,通過上面所說的判斷方法來判斷各種類型的應用:
ActivityManager獲取應用程序信息封裝了不少Bean對象:
- ActivityManager.MemoryInfo
MemoryInfo有幾個非常重要的字段:availMem(系統可用內存),totalMem(總內存),threshold(低內存的閾值,即區分是否低內存的臨界值),lowMemory(是否處於低內存)- Debug.MemoryInfo
這個MemoryInfo用於統計進程下的內存信息- RunningAppProcessInfo
運行進程的信息,存儲的字段有:processName(進程名),pid(進程pid),uid(進程uid),pkgList(該進程下的所有包)- RunningServiceInfo
運行的服務信息,在它裏面同樣包含了一些服務進程信息,同時還有一些其他信息,activeSince(第一次被激活的時間、方式),foreground(服務是否在後臺執行)下面同樣通過例子來看看如何使用ActivityManager,我們封裝一個Bean來保存我們所需的字段:
接下來,調用getRunningAppProcesses方法,返回當前運行的進程信息,並將我們關心的信息保存到Bean中:
在系統初始化的時候,PackageManager的底層實現類PackageManagerService會去掃描系統的一些特定目錄,並且解析其中的Apk文件,同時,Android把它獲取到的應用信息,保存到XML文件中,做成一個應用的花名冊,當系統中的APK安裝、刪除、升級時,它也會被更新
這個packages.xml位於/data/system/目錄下,我們用adb pull命令把他導出來,進行查看分析:
- < 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的權限信息
無知識點
- 第一道防線:代碼安全機制——代碼混淆proguard
proguard可以混淆關鍵代碼、替換命名讓破壞者閱讀難,同樣也可以壓縮代碼,優化編譯後的Java字節碼- 第二道防線:應用接入權限控制——清單文件權限聲明,權限檢查機制
任何App在使用Android受限資源的時候,都需要顯示向系統聲明所需的權限,只有當一個應用App具有相應的權限,才能申請受限資源的時候,通過權限機制的檢查並使用系統的Binder對象完成對系統服務的調用,但是這道防線也有先天性不足,如以下幾項:
- 被授予的權限無法停止
- 在應用聲明App使用權限的時,用戶無法針對部分權限進行限制
- 權限的聲明機制與用戶的安全理念相關
Android系統通常按照以下順序來檢查操作者的權限:
- 首先,判斷permission名稱,如果為空則直接返回PERMISSION_DENIED
- 其次,判斷Uid,如果為0則為root權限,不做權限控制,如果為System Service的Uid則為系統服務,不做權限控制,如果Uid與參數中的請求Uid不同則返回PERMISSION_DENIED
- 最後,通過調用packagemanageservice.checkUidPermission()方法來判斷該Uid是否具有相應的權限,該方法會去XML的權限列表和系統級的platform.xml中進行查找
- 第三道防線:應用簽名機制一數字證書
Android中所有的App都會有一個數字證書,這就是App的簽名,數字證書用於保護App的作者和其App的信任關系,只有擁有相同數字簽名的App,才會在升級時被認為是同一App,而且Android系統不會安裝沒有簽名的App- 第四道防線:Linux內核層安全機制一一Uid 訪問權限控制
Animid本質是基於Linux內核開發的,所以Android同樣繼承了Linux的安全特性,托福和雅思比如文件系統的權限控制是由user,group,other與讀(r),寫(w),執行(x)的不同組合來實現的,同樣,Android也實現了這套機制,通常情況下,只有System、root用戶才有權限訪問到系統文件,而一般用戶無法訪問- 第五道防線:Android虛擬機沙箱機制——沙箱隔流
Android的App運行在虛擬機中,因此才有沙箱機制,可以讓應用之間相互隔離,通常情況下,不同的應用之間不能互相訪問,每個App都有與之對應的Uid,每個App也運行在單獨的虛似機中,與其他應用完全隔離,在實現安全機制的基礎上,也讓應用之間能夠互不影響,即時一個應用崩潰,,也不會導致其他應用異常
- 代碼漏洞
- Root風險
- 安全機制不健全
- 用戶安全意識
- Android開發原則與安全
書本列舉的幾個點相信大家也都比較熟悉,所以不做解釋了
這裏個人的博客有簡單的介紹:Android四大組件——Activity切換效果、殺死進程、殺死所有Activity、安裝及反編譯
為了能夠對編譯好的JavaClass文件進行一些保護,通常會用ProGuard混淆代碼:
- ProGuard:用無意義的字母來重命名類、字段、方法和屬性
- 刪除無用的類、字段、方法和屬性,以及刪除沒用的註釋,最大限度地優化字節碼文件
使用ProGuard也簡單,在Android Studio中可以打開build.gradle(Module:app):
這裏的minifyEnabled就是打開ProGuard的開關,proGuardFiles屬於配置混淆文件,分為兩部分:
- 使用默認的混淆文件,位於< SDK目錄>/tools/proguard/proguard-android.txt目錄下
- 使用自定義混淆文件,可以在項目的App文件夾找到這個文件,在這個文件裏可以定義引入的第三方依賴包的混淆規則
Android群英傳知識點回顧——第九章:Android系統信息與安全機制