为了实现静默卸载, 学了下android的安全体系,记录如下

最近在做个东西,巧合碰到了sharedUserId的问题,所以收集了一些资料,存存档备份。

安装在设备中的每一个apk文件,Android给每个APK进程分配一个单独的用户空间,其manifest中的userid就是对应一个Linux用户都会被分配到一个属于自己的统一的Linux用户ID,并且为它创建一个沙箱,以防止影响其他应用程序(或者其他应用程序影响它)。用户ID 在应用程序安装到设备中时被分配,并且在这个设备中保持它的永久性。

通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中.所以默认就是可以互相访问任意数据. 也可以配置成运行成不同的进程, 同时可以访问其他APK的数据目录下的数据库和文件.就像访问本程序的数据一样.

对于一个APK来说,如果要使用某个共享UID的话,必须做三步:

1、在Manifest节点中增加android:sharedUserId属性。

2、在Android.mk中增加LOCAL_CERTIFICATE的定义。

如果增加了上面的属性但没有定义与之对应的LOCAL_CERTIFICATE的话,APK是安装不上去的。提示错误是:Package com.test.MyTest has no signatures that match those in shared user android.uid.system; ignoring!也就是说,仅有相同签名和相同sharedUserID标签的两个应用程序签名都会被分配相同的用户ID。例如所有和media/download相关的APK都使用android.media作为sharedUserId的话,那么它们必须有相同的签名media。

3、把APK的源码放到packages/apps/目录下,用mm进行编译。

举例说明一下。

系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加android:sharedUserId="android.uid.system",然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可以参见Settings等

系统中所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.uid.shared",然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可以参见Launcher等

系统中所有使用android.media作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。

另外,应用创建的任何文件都会被赋予应用的用户标识,并且正常情况下不能被其他包访问。当通过getSharedPreferences(String,int)、openFileOutput(String、int)或者openOrCreate Database(String、int、SQLiteDatabase.CursorFactory)创建一个新文件时,开发者可以同时或分别使用MODE_WORLD_READABLE和MODE_WORLD_RITEABLE标志允许其他包读/写此文件。当设置了这些标志后,这个文件仍然属于自己的应用程序,但是它的全局读/写和读/写权限已经设置,所以其他任何应用程序可以看到它。

关于签名:

build/target/product/security目录中有四组默认签名供Android.mk在编译APK使用:

1、testkey:普通APK,默认情况下使用。

2、platform:该APK完成一些系统的核心功能。经过对系统中存在的文件夹的访问测试,这种方式编译出来的APK所在进程的UID为system。

3、shared:该APK需要和home/contacts进程共享数据。

4、media:该APK是media/download系统中的一环。

应用程序的Android.mk中有一个LOCAL_CERTIFICATE字段,由它指定用哪个key签名,未指定的默认用testkey.

对于使用eclipse编译的apk,可以使用signapk.jar来手动进行签名,其源码在build/tools/signapk下,编译后在out/host/linux-x86/framework/signapk.jar,也可以从网上下载。使用方法,以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命令可以通过adb在shell中执行,同样,我们可以通过代码来执行。

01 public static void execCommand(String... command) {
02 Process process = null;
03 try {
04 process = new ProcessBuilder().command(command).start();
05 //对于命令的执行结果我们可以通过流来读取
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时,要在你的manifest文件下添加android:sharedUserId="android.uid.system",编译完成之后还无法正常安装,会出现Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误,此时,要为apk重新签名。

在android源码\build\target\product\security中找platform.pk8和platform.x509.pem两个文件,在android 编绎目录out下找到 signapk.jar 这个包(源码目录\build\tools\signapk),并把编译好的apk(如PMDemo.apk)放在同一目录下,在重新签名之前,用rar文件打开apk文件,进入META-INF目录下,将CERT.SF和CERT.RSA这两个文件删除掉,然后在命令行中执行以下命令:

1 java -jar signapk.jar platform.x509.pem platform.pk8 PMDemo.apk NewPMDemo.apk

安装前先把旧的apk卸载,这样重新签名之后的apk就可以正常安装了。 Android相关内容:
  • Android在不同操作系统下不签名编译出来的签名不一样怎么解决
  • android的AsyncTask线程运行完成后跳到另一个activity怎么实现
  • Android上传bitmap图片至Web的方法
  • Android修改源码后,再打包怎么做
  • android.view.ViewGroup.LayoutParams介绍

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  4. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  5. Android目录结构(详解)
  6. 什么特性造就了Android快速启动
  7. 210开发板Android系统串口程序
  8. Android(安卓)重要数据目录
  9. [置顶] Android(安卓)View视图------Android如何创建一个view。

随机推荐

  1. 如何绘制动漫人物头发?简单手绘动漫女生发
  2. 登陆验证码实例、接口初识
  3. Docker 安装 mysql8
  4. Linux 发行版更新软件源
  5. 使用 Packer 创建自定义镜像
  6. Docker 安装 ubuntu、centos
  7. 使用 MongoDB 工具迁移自建数据库上云
  8. RPA 服务端迁移 (从k8s到docker)
  9. kubernetes Event 源码解析
  10. Node.js SDK 核心库安装与调用