為了實(shí)現(xiàn)靜默卸載, 學(xué)了下android的安全體系,記錄如下
最近在做個(gè)東西,巧合碰到了sharedUserId的問(wèn)題,所以收集了一些資料,存存檔備份。
安裝在設(shè)備中的每一個(gè)apk文件,Android給每個(gè)APK進(jìn)程分配一個(gè)單獨(dú)的用戶(hù)空間,其manifest中的userid就是對(duì)應(yīng)一個(gè)Linux用戶(hù)都會(huì)被分配到一個(gè)屬于自己的統(tǒng)一的Linux用戶(hù)ID,并且為它創(chuàng)建一個(gè)沙箱,以防止影響其他應(yīng)用程序(或者其他應(yīng)用程序影響它)。用戶(hù)ID 在應(yīng)用程序安裝到設(shè)備中時(shí)被分配,并且在這個(gè)設(shè)備中保持它的永久性。
通過(guò)Shared User id,擁有同一個(gè)User id的多個(gè)APK可以配置成運(yùn)行在同一個(gè)進(jìn)程中.所以默認(rèn)就是可以互相訪問(wèn)任意數(shù)據(jù). 也可以配置成運(yùn)行成不同的進(jìn)程, 同時(shí)可以訪問(wèn)其他APK的數(shù)據(jù)目錄下的數(shù)據(jù)庫(kù)和文件.就像訪問(wèn)本程序的數(shù)據(jù)一樣.
對(duì)于一個(gè)APK來(lái)說(shuō),如果要使用某個(gè)共享UID的話(huà),必須做三步:
1、在Manifest節(jié)點(diǎn)中增加android:sharedUserId屬性。
2、在Android.mk中增加LOCAL_CERTIFICATE的定義。
如果增加了上面的屬性但沒(méi)有定義與之對(duì)應(yīng)的LOCAL_CERTIFICATE的話(huà),APK是安裝不上去的。提示錯(cuò)誤是:Package com.test.MyTest has no signatures that match those in shared user android.uid.system; ignoring!也就是說(shuō),僅有相同簽名和相同sharedUserID標(biāo)簽的兩個(gè)應(yīng)用程序簽名都會(huì)被分配相同的用戶(hù)ID。例如所有和media/download相關(guān)的APK都使用android.media作為sharedUserId的話(huà),那么它們必須有相同的簽名media。
3、把APK的源碼放到packages/apps/目錄下,用mm進(jìn)行編譯。
舉例說(shuō)明一下。
系統(tǒng)中所有使用android.uid.system作為共享UID的APK,都會(huì)首先在manifest節(jié)點(diǎn)中增加android:sharedUserId="android.uid.system",然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可以參見(jiàn)Settings等
系統(tǒng)中所有使用android.uid.shared作為共享UID的APK,都會(huì)在manifest節(jié)點(diǎn)中增加android:sharedUserId="android.uid.shared",然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可以參見(jiàn)Launcher等
系統(tǒng)中所有使用android.media作為共享UID的APK,都會(huì)在manifest節(jié)點(diǎn)中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以參見(jiàn)Gallery等。
另外,應(yīng)用創(chuàng)建的任何文件都會(huì)被賦予應(yīng)用的用戶(hù)標(biāo)識(shí),并且正常情況下不能被其他包訪問(wèn)。當(dāng)通過(guò)getSharedPreferences(String,int)、openFileOutput(String、int)或者openOrCreate Database(String、int、SQLiteDatabase.CursorFactory)創(chuàng)建一個(gè)新文件時(shí),開(kāi)發(fā)者可以同時(shí)或分別使用MODE_WORLD_READABLE和MODE_WORLD_RITEABLE標(biāo)志允許其他包讀/寫(xiě)此文件。當(dāng)設(shè)置了這些標(biāo)志后,這個(gè)文件仍然屬于自己的應(yīng)用程序,但是它的全局讀/寫(xiě)和讀/寫(xiě)權(quán)限已經(jīng)設(shè)置,所以其他任何應(yīng)用程序可以看到它。
關(guān)于簽名:
build/target/product/security目錄中有四組默認(rèn)簽名供Android.mk在編譯APK使用:
1、testkey:普通APK,默認(rèn)情況下使用。
2、platform:該APK完成一些系統(tǒng)的核心功能。經(jīng)過(guò)對(duì)系統(tǒng)中存在的文件夾的訪問(wèn)測(cè)試,這種方式編譯出來(lái)的APK所在進(jìn)程的UID為system。
3、shared:該APK需要和home/contacts進(jìn)程共享數(shù)據(jù)。
4、media:該APK是media/download系統(tǒng)中的一環(huán)。
應(yīng)用程序的Android.mk中有一個(gè)LOCAL_CERTIFICATE字段,由它指定用哪個(gè)key簽名,未指定的默認(rèn)用testkey.
對(duì)于使用eclipse編譯的apk,可以使用signapk.jar來(lái)手動(dòng)進(jìn)行簽名,其源碼在build/tools/signapk下,編譯后在out/host/linux-x86/framework/signapk.jar,也可以從網(wǎng)上下載。使用方法,以platform為例:java -jar ./signapk platform.x509.pem platform.pk8 input.apk output.apk (platform.x509.pem platform.pk8在build/target/product/security獲取)
1 pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH
2 pm uninstall [-k] PACKAGE
pm命令可以通過(guò)adb在shell中執(zhí)行,同樣,我們可以通過(guò)代碼來(lái)執(zhí)行。
01 public static void execCommand(String... command) {
02 Process process = null;
03 try {
04 process = new ProcessBuilder().command(command).start();
05 //對(duì)于命令的執(zhí)行結(jié)果我們可以通過(guò)流來(lái)讀取
06 // InputStream in = process.getInputStream();
07 // OutputStream out = process.getOutputStream();
08 // InputStream err = process.getErrorStream();
09 } catch (IOException e) {
10 e.printStackTrace();
11 } finally {
12 if (process != null)
13 process.destroy();
14 }
15 }
1 execCommand("pm", "install", "-f", filePath);//安裝apk,filePath為apk文件路徑,如/mnt/sdcard/ApiDemos.apk
2 execCommand("pm", "uninstall", packageName);//卸載apk,packageName為包名,如com.example.android.apis
編譯生成apk時(shí),要在你的manifest文件下添加android:sharedUserId="android.uid.system",編譯完成之后還無(wú)法正常安裝,會(huì)出現(xiàn)Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE錯(cuò)誤,此時(shí),要為apk重新簽名。
在android源碼\build\target\product\security中找platform.pk8和platform.x509.pem兩個(gè)文件,在android 編繹目錄out下找到 signapk.jar 這個(gè)包(源碼目錄\build\tools\signapk),并把編譯好的apk(如PMDemo.apk)放在同一目錄下,在重新簽名之前,用rar文件打開(kāi)apk文件,進(jìn)入META-INF目錄下,將CERT.SF和CERT.RSA這兩個(gè)文件刪除掉,然后在命令行中執(zhí)行以下命令:
1 java -jar signapk.jar platform.x509.pem platform.pk8 PMDemo.apk NewPMDemo.apk
安裝前先把舊的apk卸載,這樣重新簽名之后的apk就可以正常安裝了。
Android相關(guān)內(nèi)容: