要让Android应用获得Root权限,首先Android设备必须已经获得Root权限。

应用获取Root权限的原理:让应用的代码执行目录获取最高权限。在Linux中通过chmod

777 [代码执行目录]

代码如下:

publicstaticbooleanupgradeRootPermission(String pkgCodePath) {

Process process = null;

DataOutputStream os = null;

try{

String cmd="chmod 777 "+ pkgCodePath;

process = Runtime.getRuntime().exec("su");//切换到root帐号

os = newDataOutputStream(process.getOutputStream());

os.writeBytes(cmd + "\n");

os.writeBytes("exit\n");

os.flush();

process.waitFor();

} catch(Exception e) {

returnfalse;

} finally{

try{

if(os !=null) {

os.close();

}

process.destroy();

} catch(Exception e) {

}

}

returntrue;

}

调用代码:

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

//当前应用的代码执行目录

upgradeRootPermission(getPackageCodePath());

}

执行上述代码后,系统会弹出对话框“是否允许获取Root权限”,此时选择允许即可。

附Android安全机制

Android是一个基于Linux内核的移动操作系统。Linux是一个支持多用户的系统,系统中的文件的访问权限是通过用户ID(UID)和用户组ID(GID)来控制的。换句话说,就是Linux的安全机制是基于UID和GID来实现的。Android在Linux内核提供的基于UID和GID的安全机制的基础上,又实现了一套称为Permission的安全机制,如图1所示:

图1 Linux的UID/GID安全机制与Android的Permission安全机制

那么,这两个安全机制是如何对应起来的呢?

我们首先看一下Linux基于UID和GID的安全机制,它包含三个基本角色:用户、进程和文件,如图2所示:

图2 Linux基于UID/GID的安全机制的三个角色

Linux中的每一个用户都分配有一个UID,然后所有的用户又按组来进划分,每一个用户组都分配有一个GID。注意,一个用户可以属于多个用户组,也就是说,一个UID可以对应多个GID。在一个用户所对应的用户组中,其中有一个称为主用户组,其它的称为补充用户组。

Linux中的每一个文件都具有三种权限:Read、Write和Execute。这三种权限又按照用户属性划分为三组:Owner、Group和Other。如图3所示:

图3 Linux的文件权限划分

从图3就可以看出文件acct:1. 所有者为root,可读可写可执行;2.

所有者所属的主用户组为root,在这个组中的其它用户可读可执行;3. 其余的用户可读可执行。

Linux中的每一个进程都关联有一个用户,也就是对应有一个UID,如图4所示:

图4 Linux的进程

由于每一个用户都对应有一个主用户组,以及若干个补充用户组,因此,每一个进程除了有一个对应的UID之外,还对应有一个主GID,以及若干个Supplementary

GIDs。这些UID和GID就决定了一个进程所能访问的文件或者所能调用的系统API。例如,在图4中,PID为340的进程一般来说,就只能访问所有者为u0_a19的文件。

一个进程的UID是怎么来的呢?在默认情况下,就等于创建它的进程的UID,也就是它的父进程的UID。Linux的第一个进程是init进程,它是由内核在启动完成后创建的,它的UID是root。然后系统中的所有其它进程都是直接由init进程或者间接由init进程的子进程来创建。所以默认情况下,系统的所有进程的UID都应该是root。但是实际情况并非如此,因为父进程在创建子进程之后,也就是在fork之后,可以调用setuid来改变它的UID。例如,在PC中,init进程启动之后,会先让用户登录。用户登录成功后,就对应有一个shell进程。该shell进程的UID就会被setuid修改为所登录的用户。之后系统中创建的其余进程的UID为所登录的用户。

进程的UID除了来自于父进程之外,还有另外一种途径。上面我们说到,Linux的文件有三种权限,分别是Read、Wirte和Execute。其实还有另外一个种权限,叫做SUID。例如,我们对Android手机进行root的过程中,会在里面放置一个su文件。这个su文件就具有SUID权限,如图5所示:

图5 su的SUID和SGID

一个可执行文件一旦被设置了SUID位,那么当它被一个进程通过exec加载之后,该进程的UID就会变成该可执行文件的所有者的UID。也就是说,当上述的su被执行的时候,它所运行在的进程的UID是root,于是它就具有最高级别的权限,想干什么就干什么。

与SUI类似,文件还有另外一个称为SGID的权限,不过它描述的是用户组。也就是说,一个可执行文件一旦被设置了GUID位,么当它被一个进程通过exec加载之后,该进程的主UID就会变成该可执行文件的所有者的主UID。

现在,小伙伴们应该可以理解Android手机的root原理了吧:一个普通的进程通过执行su,从而获得一个具有root权限的进程。有了这个具有root权限的进程之后,就可以想干什么就干什么了。su所做的事情其实很简单,它再fork另外一个子进程来做真正的事情,也就是我们在执行su的时候,后面所跟的那些参数。由于su所运行在的进程的UID是root,因此由它fork出来的子进程的UID也是root。于是,子进程也可以想干什么就干什么了。

不过呢,用来root手机的su还会配合另外一个称为superuser的app来使用。su在fork子进程来做真正的事情之前,会将superuser启动起来,询问用户是否允许fork一个UID是root的子进程。这样就可以对root权限进行控制,避免被恶意应用偷偷地使用。

在传统的UNIX以及类UNIX系统中,进程的权限只划分两种:特权和非特权。UID等于0的进程就是特权进程,它们可以通过一切的权限检查。UID不等于0的进程就非特权进程,它们在访问一些敏感资源或者调用一个敏感API时,需要进行权限检查。这种纯粹通过UID来做权限检查的安全机制来粗放了。于是,Linux从2.2开始,从进程的权限进行了细分,称为Capabilities。一个进程所具有Capabilities可以通过capset和prctl等系统API来设置。也就是说,当一个进程调用一个敏感的系统API时,Linux内核除了考虑它的UID之外,还会考虑它是否具有对应的Capability。

以上就是Linux基于UID/GID的安全机制的核心内容。接下来我们再看Android基于Permission的安全机制,它也有三个角色:apk、signature和permission,如图6所示:

图6 Android的Permission安全机制

Android的APK经过PackageManagerService安装之后,就相当于Linux里面的User,它们都会被分配到一个UID和一个主GID,而APK所申请的Permission就相当于是Linux里面的Supplementary

GID。

我们知道,Android的APK都是运行在独立的应用程序进程里面的,并且这些应用程序进程都是Zygote进程fork出来的。Zygote进程又是由init进程fork出来的,并且它被init进程fork出来后,没有被setuid降权,也就是它的uid仍然是root。按照我们前面所说的,应用程序进程被Zygote进程fork出来的时候,它的UID也应当是root。但是,它们的UID会被setuid修改为所加载的APK被分配的UID。

参照Android应用程序进程启动过程的源代码分析一文的分析,ActivityManagerService在请求Zygote创建应用程序进程的时候,会将这个应用程序所加载的APK所分配得到的UID和GID(包括主GID和Supplementary

GID)都收集起来,并且将它们作为参数传递给Zygote进程。Zygote进程通过执行函数来fork应用程序进程:

staticpid_t forkAndSpecializeCommon(constu4* args,boolisSystemServer)

{

pid_t pid;

uid_t uid = (uid_t) args[0];

gid_t gid = (gid_t) args[1];

ArrayObject* gids = (ArrayObject *)args[2];

......

pid = fork();

if(pid == 0) {

......

err = setgroupsIntarray(gids);

......

err = setgid(gid);

......

err = setuid(uid);

......

}

.....

returnpid;

}

参数args[0]、args[1]和args[]保存的就是APK分配到的UID、主GID和Supplementary

GID,它们分别通过setuid、setgid和setgroupsIntarray设置给当前fork出来的应用程序进程,于是应用程序进程就不再具有root权限了。

那么,Signature又充当什么作用呢?两个作用:1.

控制哪些APK可以共享同一个UID;2. 控制哪些APK可以申请哪些Permission。

我们知道,如果要让两个APK共享同一个UID,那么就需要在AndroidManifest中配置android:sharedUserId属性。PackageManagerService在安装APK的时候,如果发现两个APK具有相同的android:sharedUserId属性,那么它们就会被分配到相同的UID。当然这有一个前提,就是这两个APK必须具有相同的Signature。这很重要,否则的话,如果我知道别人的APK设置了android:sharedUserId属性,那么我也在自己的APK中设置相同的android:sharedUserId属性,就可以去访问别人APK的数据了。

除了可以通过android:sharedUserId属性申请让两个APK共享同一个UID之外,我们还可以将android:sharedUserId属性的值设置为“android.uid.system”,从而让一个APK的UID设置为1000。UID是1000的用户是system,系统的关键服务都是运行在的进程的UID就是它。它的权限虽然不等同于root,不过也足够大了。我们可以通过Master

Key漏洞来看一下有多大。

Master

Key漏洞发布时,曾轰动了整个Android界,它的具体情况老罗就不分析了,网上很多,这里是一篇官方的文章:http://bluebox.com/corporate-blog/bluebox-uncovers-android-master-key/。现在就简单说说它是怎么利用的:

1.

找到一个具有系统签名的APP,并且这个APP通过android:sharedUserId属性申请了android.uid.system这个UID。

2. 通过Master Key向这个APP注入恶意代码。

3. 注入到这个APP的恶意代码在运行时就获得了system用户身份。

4.

修改/data/local.prop文件,将属性ro.kernel.qemu的值设置为1。

5.

重启手机,由于ro.kernel.qemu的值等于1,这时候手机里面的adb进程不会被setuid剥夺掉root权限。

6.

通过具有root权限的adb进程就可以向系统注入我们熟悉的su和superuser.apk,于是整个root过程完成。

注意,第1步之所以要找一个具有系统签名的APP,是因为通过android:sharedUserId属性申请android.uid.system这个UID需要有系统签名,也就是说不是谁可以申请system这个UID的。另外,/data/local.prop文件的Owner是system,因此,只有获得了system这个UID的进程,才可以对它进行修改。

再说说Signature与Permission的关系。有些Permission,例如INSTALL_PACKAGE,不是谁都可以申请的,必须要具有系统签名才可以,这样就可以控制Suppementary

GID的分配,从而控制应用程序进程的权限。具有哪些Permission是具有系统签名才可以申请的,可以参考官方文档:http://developer.android.com/reference/android/Manifest.html,就是哪些标记为“Not

for use by third-party applications”的Permission。

了解了Android的Permission机制之后,我们就可以知道:

1.

Android的APK就相当于是Linux的UID。

2.

Android的Permission就相当于是Linux的GID。

3.

Android的Signature就是用来控制APK的UID和GID分配的。

这就是Android基于Permission的安全机制与Linux基于UID/GID的安全机制的关系,概括来说,我们常说的应用程序沙箱就是这样的:

图7 Android的Application Sandbox

android 6 编译 root权限,Android应用获得Root权限相关推荐

  1. android资源编译失败,在android studio中打开一个新项目时,Android资源编译失败

    用我的android studio打开新项目时出现此错误 Android资源编译失败输出:C:\ Projects \ Popular2 \ app \ src \ main \ res \ draw ...

  2. android ndk 编译c++11,Android NDK中的c++ STL

    田海立@CSDN 2020-11-25 Android NDK(Native Development Kit)提供了一套基于c/c++开发Android应用的工具.基于c/c++开发需要STL (St ...

  3. ffmpeg android ndk编译,关于使用Android NDK编译ffmpeg

    由于项目需求,前两天在在ios项目中使用ffmpeg,写下了"关于ios中编译ffmpeg0.9.2库",然后有朋友在咨询,如何编译最新版的ffmpeg,其实最新版的编译也差不多, ...

  4. android 反编译报错,android反编译

    常用反编译方法: 1.先将.apk改为.zip或者.rar用winrar加压得到classes.dex文件 2.用dex2jar工具将.dex转为.jar,然后用jd-gui就可以打开.jar查看源文 ...

  5. android 库编译报错,Android Studio编译项目报错

    编译项目时报以下错误: Error:Execution failed for task ':app:dexDebug'. > mon.internal.LoggedErrorException: ...

  6. sqlite如何在android上编译,如何在Android中使用SQLITE中的准备语句?

    对于Android中准备好的SQLite语句,有SQLiteStatement..准备好的语句可以帮助您提高性能(特别是需要多次执行的语句),还有助于避免注入攻击.看见这篇文章就准备好的发言进行一般性 ...

  7. android ndk 编译c++11,Android NDK的C++11标准支持

    C++11在Android NDK中已经支持了,本文主要介绍如何在NDK中添加C++11标准的支持.android 在开源项目Cocos2d-x中,已经添加了C++11标准的支持.c++ 1.修改Ap ...

  8. android xmlpullparser 编译出错,将Android支持库更新为23.2.0导致错误:XmlPullParserException...

    我尝试将支持库更新到23.2.0并遇到此错误: Exception while inflating org.xmlpull.v1.XmlPullParserException: Binary XML ...

  9. android 反编译 添加 res,Android apk反编译记录

    1.1 解压apk apktool.bat d -f xxx_ifly.apk -o ifly 1.2 错误 S: Could not decode file, replacing by FALSE ...

  10. android控制哪些模块编译,Android不编译某个模块

    Android 5.1 源码,编译相关的文件一般在build目录下 build/target/product 放了很多mk文件:一般不同的产品会有不同的目录 假设我不想编译OpenWnn,在build ...

最新文章

  1. 从numpy开启Python数据科学之旅
  2. (volatile int)(x)与*(volatile int *)(x)
  3. 脑细胞膜等效神经网路训练代码
  4. 用 Java 对 hbase 进行CRUD增删改查操作
  5. USB和串口(COM)的区别,以及相互转换
  6. java中取得上下文路径的方法
  7. 硬盘安装Fedora16
  8. 用管控策略设定多账号组织全局访问边界
  9. xbox one 越狱_如何在Xbox One上播放视频和音乐文件
  10. raid硬盘序列号_磁盘阵列出现坏盘,如何正确更换硬盘?
  11. 德标螺纹规格对照表_多大的螺栓用多大规格的扳手,一文看懂!
  12. 使用这些 HTTP 头保护 Web 应用
  13. Codeforces Round #388 (Div. 2) C. Voting
  14. 多线段几何图形—— 简单几何图形(判断一个点是否在图形的内部)
  15. 思维万能体系——申论
  16. C++直接初始化和复制初始化
  17. 2012~2020年期货全品种TICK数据共享更新至2020.7.24
  18. 开启电脑自带的远程控制
  19. plsql实现1..100累加、奇数之和、偶数之和
  20. 【Cocos2d-x】视线和光线:如何创建 2D 视觉范围效果

热门文章

  1. 看完这篇 教你玩转渗透测试靶机Vulnhub——The Planets:Venus
  2. Spring合集篇|面试官:Spring都讲不明白,自己走还是我送你?
  3. 帧中继(Frame relay /FR)
  4. 七年级上册计算机知识点总结,初一数学上册知识点总结归纳
  5. 国产CPU型号查看命令(鲲鹏cpu、飞腾CPU)
  6. 架构设计——架构概述
  7. 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
  8. Linux常规问题总结
  9. 【考研英语语法及长难句】小结
  10. Novell开放工作组套件(转)