Android 操作系统获取Root权限 原理详细解析

android root权限破解分析

许多机友新购来的Android机器没有破解过Root权限,无法使用一些需要高权限的软件,以及进行一些高权限的操作,其实破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/system/bin/或/system/xbin/目录下放置一个可执行文件“su”,这是一个二进制文件,相当于电脑上的exe文件,仅仅在系统中置入这个“su”文件是不会给手机的软件或硬件造成任何故障。

下面的代码是android系统原版的su中的部分代码,可以看出只允许getuid()为AID_ROOT和AID_SHELL的进程可以使用su进行登陆。


复制代码 代码如下:

<SPAN style="FONT-SIZE: 18px"><STRONG>/* Until we have something better, only root and the shell can use su. */
myuid = getuid();
if (myuid != AID_ROOT && myuid != AID_SHELL) {
fprintf(stderr,"su: uid %d not allowed to su\n", myuid);
return 1;
}</STRONG></SPAN>

面在Superuser这个android程序中的su不再有上面的一部分,这样任何进程都可以使用su进行登陆了,有一部分android程序要使用root权限可能的用法类似于(这个也是Superuser中的一部分代码):


复制代码 代码如下:

Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes("mount -oremount,rw /dev/block/mtdblock3 /system\n");
os.writeBytes("busybox cp /data/data/com.koushikdutta.superuser/su /system/bin/su\n");
os.writeBytes("busybox chown 0:0 /system/bin/su\n");
os.writeBytes("chmod 4755 /system/bin/su\n");
os.writeBytes("exit\n");
os.flush();

而在上面提到的Superuser和android程序中的su源码中都有这部分代码:


复制代码 代码如下:

if(setgid(gid) || setuid(uid)) {
fprintf(stderr,"su: permission denied\n");
return 1;
}

看上去这里就是进行权限切换的地方了。面普通用户要能使用su,su的权限要是这样:

-rwsr-xr-x. 1 root root 34904 11月 3 2010 /bin/su

这个和电脑版的su上是一样的。

从出上面的分析可以认为破解android的root权限的实质是:在系统中加入一个任何用户都可能用于登陆的su命令。当然这首先要取得root权限才能做

到。在z4root这个android下的破解android的root权限的程序中有一个rageagainstthecage,可能就是设法得到root权限的程序。

第二篇文章:

如果你进行过程序开发,在root过的手机上面获得root权限的代码如下:


复制代码 代码如下:

Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
......
os.writeBytes("exit\n");
os.flush();

从上面代码我们可以看到首先要运行su程序,其实root的秘密都在su程序中,《android root权限破解分析》中讲到Android系统默认的su程序只能root和shell可以用运行su,这个是安全的。如果把这个限制拿掉,就是root破解了!

下面我们仔细分析一下程序是怎样获得root权限的,如果对Linux的su命令熟悉的朋友可能知道su程序都设置SUID位,我们查看一下我的手机(已经root破解)上的su权限设置,

我们发现su的所有者和所有组都是root,是其实是busybox的软链接,我们查看busybox的属性发现,其设置了SUID和SGID,并且所有者和所有组都是root。SUID和SGID的作用是什么呢?如果你不太清楚,请参考《Linux进程的实际用户ID和有效用户ID》,这样运行busybox的普通用户,busybox运行过程中获得的是root的有效用户。su程序则是把自己启动一个新的程序,并把自己权限提升至root(我们前面提到su其实就是busybox,运行期它的权限是root,当然也有权限来提升自己的权限)。

再强调一下不光root手机上su需要设置SUID,所有的Linux系统上的su程序都需要设置SUID位。请参考一下UC服务器的su的权限情况:

我们发现su也设置了SUID位,这样普通用户也可以运行su程序,su程序会验证root密码,如果正确su程序可以把用户权限提高的root(因为其设置SUID位,运行期是root权限,这样其有权限提升自己的权限)。

这样我们就可以看出其实Android系统的破解的根本原理就是替换掉系统中的su程序,因为系统中的默认su程序需要验证实际用户权限(只有root和 shell用户才有权运行系统默认的su程序,其他用户运行都会返回错误)。而破解后的su将不检查实际用户权限,这样普通的用户也将可以运行su程序, 也可以通过su程序将自己的权限提升。

到这里大家对root破解不感到神秘了吧。root破解没有利用什么Linux内核漏洞(Linux内核不可能有这么大的漏洞存在),可以理解成root 破解就是在你系统中植入“木马su”,说它是“木马”一点儿都不为过,假如恶意程序在系统中运行也可以通过su来提升自己的权限的这样的结果将会是灾难性 的。所以一般情况下root过手机都会有一个SuperUser应用程序来让用户管理允许谁获得root权限,也算是给系统加了一层保险吧!

通过上文《Android系统root破解原理分析》 的介绍大家应该明白了root破解过程的终极目标是替换掉系统中的su程序。但是要想替换掉系统中su程序本身就是需要root权限的,怎样在root破 解过程中获得root权限,成为我们研究的重点了。下面我们先清点一下我们需要破解系统情况,假设需要破解的Android系统具备如下条件:


复制代码 代码如下:

1、可以通过adb连接到设备,一般意味着驱动程序已经安装。
2、但是adb获得用户权限是shell用户,而不是root。

要想理解root破解过程我们首先需要了解一下adb工具,SDK中包含adb工具,设备端有adbd服务程序后台 运行,为开发机的adb程序提供服务,adbd的权限,决定了adb的权限。具体用户可查看/system/core/adb下的源码,查看 Android.mk你将会发现adb和adbd其实是一份代码,然后通过宏来编译。

查看adb.c的adb_main函数你将会发现adbd中有如下代码:


复制代码 代码如下:

int adb_main(int is_daemon)
{
    ......
    property_get("ro.secure", value, "");
    if (strcmp(value, "1") == 0) {
        // don't run as root if ro.secure is set...
        secure = 1;
        ......
    }

if (secure) {
        ......

从中我们可以看到adbd会检测系统的ro.secure属性,如果该属性为1则将会把自己的用户权限降级成shell用户。一般设备出厂的时候在/default.prop文件中都会有:


复制代码 代码如下:

ro.secure=1

这样将会使adbd启动的时候自动降级成shell用户。

然后我们再介绍一下adbd在什么时候启动的呢?答案是在init.rc中配置的系统服务,由init进程启动。我们查看init.rc中有如下内容:


复制代码 代码如下:

# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
   disabled

对Android属性系统少有了解的朋友将会知道,在init.rc中配置的系统服务启动的时候都是root权限(因为init进行是root权限,其子程序也是root)。由此我们可以知道在adbd程序在执行:


复制代码 代码如下:

/* then switch user and group to "shell" */
setgid(AID_SHELL);
setuid(AID_SHELL);

代码之前都是root权限,只有执行这两句之后才变成shell权限的。

这样我们就可以引出root破解过程中获得root权限的方法了,那就是让以上面setgid和setuid函数执行失败,也就是降级失败,那就继续在root权限下面运行了。

这其实利用了一个RageAgainstTheCage漏洞,具体分析请参考《Android adb setuid提权漏洞的分析》和《RageAgainstTheCage》。这里面做一个简单说明:


复制代码 代码如下:

1、出厂设置的ro.secure属性为1,则adbd也将运行在shell用户权限下;

2、adb工具创建的进程ratc也运行在shell用户权限下;

3、ratc一直创建子进程(ratc创建的子程序也 将会运行在shell用户权限下),紧接着子程序退出,形成僵尸进程,占用shell用户的进程资源,直到到达shell用户的进程数为 RLIMIT_NPROC的时候(包括adbd、ratc及其子程序),这是ratc将会创建子进程失败。这时候杀掉adbd,adbd进程因为是 Android系统服务,将会被Android系统自动重启,这时候ratc也在竞争产生子程序。在adbd程序执行上面setgid和setuid之 前,ratc已经创建了一个新的子进程,那么shell用户的进程限额已经达到,则adbd进程执行setgid和setuid将会失败。根据代码我们发 现失败之后adbd将会继续执行。这样adbd进程将会运行在root权限下面了。

3、这是重新用adb连接设备,则adb将会运行在root权限下面了。

通过上面的介绍我们发现利用RageAgainstTheCage漏洞,可以使adbd获得root权限,也就是adb获得了root权限。拿到root权限剩下的问题就好办了,复制破解之后的su程序到系统中(见上文《Android系统root破解原理分析》的介绍),都是没有什么技术含量的事情了。

其实堵住adbd的这个漏洞其实也挺简单的:


复制代码 代码如下:

/* then switch user and group to "shell" */
if (setgid(AID_SHELL) != 0) {
    exit(1);
}

if (setuid(AID_SHELL) != 0) {
    exit(1);
}

如果发现setgid和setuid函数执行失败,则adbd进程异常退出,就把这个漏洞给堵上了。为什么这么多设 备都没有堵上这个漏洞呢?我觉得是设备厂商的策略(不排除傻X的厂商存在哦),虽然知道怎么封堵漏洞但是就是留着个后门给大家,让第三方给自己定制 rom,提高自己系统的易用性。

至此我们把root的过程和root之后系统情况都进行了介绍,相信你也不会对root破解再神秘了吧!

时间: 2013-10-23

Android 访问文件权限的四种模式介绍

Linux文件的访问权限 * 在Android中,每一个应用是一个独立的用户 * drwxrwxrwx * 第1位:d表示文件夹,-表示文件 * 第2-4位:rwx,表示这个文件的拥有者(创建这个文件的应用)用户对该文件的权限 * r:读 * w:写 * x:执行 * 第5-7位:rwx,表示跟文件拥有者用户同组的用户对该文件的权限 * 第8-10位:rwx,表示其他用户组的用户对该文件的权限 openFileOutput的四种模式 * MODE_PRIVATE:-rw-rw---- * MOD

android 权限大全 分享

访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permission.ACCESS_COARSE_LOCATION,通过WiFi或移动基站的方式获取用户错略的经纬度信息,定位精度大概误差在30~1500米获取精确位置 android.permission.ACCESS_FINE_LOCATION,通过GPS芯片接收卫星的定位信息,定位精度达10米以内访问定位额

Android需要提升权限的操作方法

权限提升方法:一种方法:1.在AndroidManifest.xml中的manifest节点中添加 android:sharedUserId="android.uid.system".2.添加后程序在虚拟机上是不可以直接用的.但可以用eclipse编译成apk.3.(这一步经验证不执行即可)编译成apk后用压缩工具打开apk,把META-INF目录中的CERT.SF.CERT.RSA 两个文件删除.4.使用android自带的签名工具signapk.jar 以及源码中的platform

Android权限控制之自定义权限

天哪,这篇文章终于说道如何自定义权限了,左盼右盼,其实这个自定义权限相当easy.为了方便叙述,我这边会用到两个app作为例子示范. Permission App: used to define a new permission 这个作为定义权限的App,我称之为Permission App. Client App: used to access the specified activity of Permission App 这个作为访问上述自定义权限的App,我称之为Client App 先

Android 6.0权限申请详解及权限资料整理

在android 6.0开始,部分的权限需要我们动态申请,也就是说当我们的打开app的时候系统不会主动像您申请app所需要的部分权限,需要客户在使用app的时候主动的去申请. 一.权限的申请两步骤: 1.权限申请: /** * @param permissions需要申请的权限 * @param requestCode申请回调code */ public static void requestPermissions(final @NonNull Activity activity,final @

Android使用记录访问权限详解

使用记录访问权限 什么是使用记录访问权限呢?这是在Android5.0(Api level 21)新添加的,通过该权限我们可以查看设备上其它应用使用情况的统计信息等. 如何使用该权限呢? 首先在manifest中添加: <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" /> 由于该权限默认只授

Android获取ROOT权限的实例代码

获取Android的ROOT权限其实很简单,只要在Runtime下执行命令"su"就可以了. 复制代码 代码如下: // 获取ROOT权限public void get_root(){ if (is_root()){        Toast.makeText(mCtx, "已经具有ROOT权限!", Toast.LENGTH_LONG).show();    }    else{        try{            progress_dialog = P

基于android中权限的集合汇总

程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 完整列表如下: 1. android.permission.ACCESS_CHECKIN_PROPERTIES    允许读写访问"properties"表在 checkin数据库中,改值可以修改上传( Allows read/write access to the "properties" table in the checkin database, to change

基于Android中获取资源的id和url方法总结

一.获取android工程里面的各种资源的id; 1.1 string型 比如下面: << string name="OK">> 客户端请求成功 << / string>> //string资源中 名称为OK的 id 获取方式 int strId = getResources().getIdentifier("OK", "string", getPackageName()); 1.2 color型

基于jQuery中ajax的相关方法汇总(必看篇)

前提条件 话说是jquery中的ajax方法,那么前提条件当然是引入jquery啦. <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js" type="text/javascript"></script> 具体方法 ①load() 使用load()方法通过Ajax请求加载服务器中的数据,并把返回的数据放置到指定的元素中,它的调用格式为: load(url,[data],[call

基于Android中手势交互的实现方法

闲来无事,琢磨琢磨Android中的手势交互,发现网上在手势方面的文章并不是很多,而且很多的参考价值并不大.于是出此博文,与大家共勉.鉴于我写此博文时对手势交互的研究也不是特深,如果有不正确的地方,还请各位博友批评指正. 首先,在Android系统中,每一次手势交互都会依照以下顺序执行. 1. 接触接触屏一刹那,触发一个MotionEvent事件. 2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象. 3. 通过GestureDetec

基于Android中Webview使用自定义的javascript进行回调的问题详解

先说为什么需要讨论这个问题. 现在很多的手机应用,都可能会直接嵌入一个web页面.这样做的好处:一个是功能更新方便,维护起来容易,只需要维护服务器的页面即可,不需要更新客户端:另一个是功能通用,不仅android可以用,ios也可以用,symbian也可以直接用. 那为什么现在很多手机应用并不做成web方式的呢?原因很多.一个是现阶段web方式展现能力相对较弱,如果对于应用的美观程度要求比较高,就无法使用web方式:一个是web方式速度相对较慢,用户体验会受一些影响:一个是现阶段流量还是相对宝贵

基于Android中实现定时器的3种解决方法

在Android开发中,定时器一般有以下3种实现方法:一.采用Handler与线程的sleep(long)方法二.采用Handler的postDelayed(Runnable, long)方法三.采用Handler与timer及TimerTask结合的方法下面逐一介绍:一.采用Handle与线程的sleep(long)方法Handler主要用来处理接受到的消息.这只是最主要的方法,当然Handler里还有其他的方法供实现,有兴趣的可以去查API,这里不过多解释.1. 定义一个Handler类,用

基于android中读取assets目录下a.txt文件并进行解析的深入分析

android读取assets文件下的内容,一般都是使用getAsset.open()方法,并将文件的路径作为参数传入,而当我们解析一个目录下的文件时需要对其进行解析时,比如:a.txt文件的内容为:nameandroid,liuclass1,2,3,4这些文件有时就像是数据库文件的格式一样,我们就需要对其进行解析.我们知道获取assets文件后返回的是一个inputstream而不是一个file类型,所以我们需要对inputstream进行解析.主要分为两个阶段:第一个阶段为:去换行符,第二个

Android中Notification的用法汇总

我们在用手机的时候,如果来了短信,而我们没有点击查看的话,是不是在手机的最上边的状态栏里有一个短信的小图标提示啊?你是不是也想实现这种功能呢?今天的Notification就是解决这个问题的. 我们也知道Android系统也是在不断升级的,有关Notification的用法也就有很多种,有的方法已经被android抛弃了,现在我实现了三种不同的方法,并适应不同的android版本.现在我就把代码公布出来,我喜欢把解释写在代码中,在这里我就不多说了,先看效果图: 再看代码,主要的代码如下: pac

基于Android中dp和px之间进行转换的实现代码

在xml布局文件中,我们既可以设置px,也可以设置dp(或者dip).一般情况下,我们都会选择使用dp,这样可以保证不同屏幕分辨率的机器上布局一致.但是在代码中,如何处理呢?很多控件的方法中都只提供了设置px的方法,例如setPadding,并没有提供设置dp的方法.这个时候,如果需要设置dp的话,就要将dp转换成px了. 以下是一个应用类,方便进行px和dp之间的转换. 复制代码 代码如下: import android.content.Context; public class Densit

基于android中的各种颜色在drawable.xml中的值详解

< drawable name="white">#FFFFFF< /drawable>< !--白色 --> < drawable name="black">#000000< /drawable>< !--黑色 --> < drawable name="ivory">#FFFFF0< /drawable>< !--象牙色 --> <