`
ihyperwin
  • 浏览: 434534 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

android root权限破解分析

阅读更多
破解android的root权限的本质是:在系统中加入一个任何用户都可能用于登陆的su命令。或者说替换掉系统中的su程序,因为系统中的默认su程序需要验证实际用户权限,只有root和 shell用户才有权运行系统默认的su程序,其他用户运行都会返回错误。而破解后的su将不检查实际用户权限,这样普通的用户也将可以运行su程序,也可以通过su程序将自己的权限提升。

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


Android的应用程序入口肯定是Java程序。应用程序的启动者是由系统临时根据Androidmanifest.xml中定义的权限而创建的临时用户。而不像linux那样是使用登陆者的身份启动,从而使得进程具有登陆者的所有权限。这也是Android的安全机制之一。
新的权限机制也带来新的问题,Android给应用程序的权限是按功能来分,java虽然可以访问文件系统。但由于应用程序本身是临时用户启动,这个临时用户权限十分有限。因此诞生了<越狱/root机器>这样的产物。

其实root机器不是真正能让你的应用程序具有root权限。它原理就跟linux下的像sudo这样的命令。在系统的bin目录下放个su程序并且属主是root并有suid权限。则通过su执行的命令都具有Android root权限。

当然使用临时用户权限想把su拷贝的/system/bin目录并改属性并不是一件容易的事情。这里用到2个工具跟2个命令。
工具就是busybox。不熟悉的同学可以去网上google下。这个太有名了我就不多说了。把busybox拷贝到你有权限访问的目录然后给他赋予4755权限,你就可以用它做很多事了。
当然busybox不能提升权限,真正提升权限的是ratc这个程序,这个程序中一键root包里面可以找到,作用是rooting在adb的shell。
网上介绍Ratc的文章不多,它是rage against the cage 的缩写。是真正的提升权限的破解程序。虽然我没看过源代码,但估计是利用adb源代码部分内容来实现的,
原理估计跟模拟器使用adb shell登陆可以获得root shell差不多。(因为它运行需要adb连接才会成功)。

使用busybox前先运行ratc,这样运行busybox的UID将是0,也就是root。
首先把system目录改成可读性的:busybox mount -o remount,rw /system,
当然你还不能改下面的文件,因为system下文件的所有者都不是你。但你可以偷梁换柱把system下的目录给换掉。
使用命令Busybox mount -t tmpfs none /system/xbin,呵呵这下xbin目录你随便写了。
将su跟busybox弄过去cp /data/data/xxx/su /system/xbin。然后赋权限chmod 4755 /system/xbin/su。
然后使目录生效busybox --install -s /system/xbin,别忘善后busybox mount -o remount,ro /system去掉system可写。
这样只是临时的,只能用su跟busybox能执行一些原来系统没有权限执行的命令而已。当系统重启后/system/xbin又变为原来的文件。
真正要改系统的话需要自己写内核代码(相当于windows的驱动程序)。内核文件拥有所有权限。使用busybox命令insmod /data/data/xxx/xxx.ko装载内核文件,你想干嘛就可以干嘛了。
当然我们不是搞破解的没必要去改别人的机器,我们只是想让自己应用程序具有root权限而已。所以临时的su就可以了。
我们用c++写一个可执行文件。使用socket可以跟java的程序通讯。然后将需要使用root权限才能执行的代码放在c++程序里,然后java程序中创建新的su进程,
将c++程序带全路径作为参数1。启动后就可以通过socket调用c++函数去执行你想干的事了。最后程序执行完了别忘了善后busybox umount /system/xbin。
最后说说要注意的事情,如果机器已经拥有Android root权限的话就不需要做这些事情了,但root过的机器都有装有个权限管理的程序。会弹出对话框。但这个程序管理能力有限,如果不想让他弹出的话。也许可以通过改su文件名来解决。有兴趣的同学不妨试试。


--------------------------------------------------------------------------------------------------------------------------------------------------------


破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/system/bin/或/system/xbin/目录下放置一个可执行文件“su”,这是一个二进制文件,仅仅在系统中置入这个“su”文件是不会给手机的软件或硬件造成任何故障。

下面的代码是android系统原版的su中的部分代码,可以看出只允许getuid()为AID_ROOT和AID_SHELL的进程可以使用su进行登陆。
也就是说,Android系统默认的su程序只能root和shell可以用运行su,这个是安全的。如果把这个限制拿掉,就是root破解了,获取了root权限

/* 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;
}

  在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;
}

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




--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

root破解过程的终极目标是替换掉系统中的su程序。但是要想替换掉系统中su程序本身就是需要root权限的,怎样在root破 解过程中获得root权限,成为我们研究的重点了。
下面我们先清点一下我们需要破解系统情况,假设需要破解的Android系统具备如下条件:

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

要想理解root破解过程我们首先需要了解一下adb工具,SDK中包含adb(android debug briage)工具,设备端有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) {

           ......

           setgid(AID_SHELL);

           setuid(AID_SHELL);

           ......

       }

   }

从中我们可以看到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

  在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漏洞。这里面做一个简单说明:

    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程序到系统中,都是没有什么技术含量的事情了。

其实堵住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进程异常退出,就把这个漏洞给堵上了。
为什么这么多设备都没有堵上这个漏洞呢?我觉得是设备厂商的策略,虽然知道怎么封堵漏洞但是就是留着个后门给大家,让第三方给自己定制 rom,提高自己系统的易用性。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

去年的Android adb setuid提权漏洞被用于各类root刷机,漏洞发现人Sebastian Krahmer公布的利用工具RageAgainstTheCage(rageagainstthecage-arm5.bin)被用于z4root等提权工具、Trojan.Android.Rootcager等恶意代码之中。下面我们来分析这一漏洞的产生原因。

The Android Exploid Crew小组在后来发布了一份PoC代码:rageagainstthecage.c。从这份代码开始着手。
在main(:72)函数中,首先获取了RLIMIT_NPROC的值(:83),这个值是Linux内核中定义的每个用户可以运行的最大进程数。
然后,调用find_adb()函数(:94)来搜索Android系统中adb进程的PID,具体而言,该函数读取每个进程对应的文件的/proc/<pid>/cmdline,根据其是否等于”/sbin/adb”来判断是否adb进程。
接下来,fork了一个新的进程(:109),父进程退出,而子进程继续。接下来,在113行创建一个管道。

rageagainstthecage.c
代碼:

if (fork() > 0)
    exit(0);

setsid();
pipe(pepe);

重头戏发生在下面的122到138行,代码如下:

rageagainstthecage.c

代碼:if (fork() == 0) {
    close(pepe[0]);
    for (;;) {
        if ((p = fork()) == 0) {
            exit(0);
        } else if (p < 0) {
            if (new_pids) {
                printf("\n[+] Forked %d childs.\n", pids);
                new_pids = 0;
                write(pepe[1], &c, 1);
                close(pepe[1]);
            }
        } else {
            ++pids;
        }
    }
}
新建一个进程后,在子进程之中,exploit代码不断地fork()(:125),而新的子进程不断退出,从而产生大量的僵尸进程(占据shell用户的进程数)。
最终,进程数达到上限,fork()返回小于0,于是打印当前已经创建多少子进程,并向管道输入一个字符(:131)。
在这里,管道的作用是和(:122)fork出来的父进程同步,该进程在141行read这一管道,因而阻塞直至僵尸进程已经达到上限(:131)。
进一步的,exploit杀掉adb进程,并在系统检测到这一现象并重启一个adb之前,再一次fork(),将前一个adb留下的进程空位占据。
最后,在152行,exploit调用wait_for_root_adb(),等待系统重启一个adb,这个新建的adb就会具有root权限。


为什么在shell用户的进程数达到上限RLIMIT_NPROC以后,新建的adb会具有root权限?我们来看adb的源码。
在<android_src>/system/core/adb/adb.c的第918行,我们可以看到如下代码:

android_src/system/core/adb/adb.c
代碼:/* then switch user and group to "shell" */
if (setgid(AID_SHELL) != 0) {
    exit(1);
}
if (setuid(AID_SHELL) != 0) {
    exit(1);
}
这已经是漏洞修补以后的代码。在漏洞最初被发现时,代码如下:

android_src/system/core/adb/adb.c
代碼:/* then switch user and group to "shell" */
setgid(AID_SHELL);
setuid(AID_SHELL);
简而言之,原来没有检查setuid()函数的返回值。事实上,在此之前,adb.c中的代码都是以root权限运行,以完成部分初始化工作。
在这一行,通过调用setuid()将用户从root切换回shell,但setuid()在shell用户进程数达到上限RLIMIT_NPROC时,会失败,因此adb.c继续以root身份运行,而没有报错。

我们来看setuid()的man手册(man 2 setuid),其中有如下说明:
man 2 setuid
代碼:RETURN VALUE
       On  success,  zero is returned.  On error, -1 is returned, and errno is
       set appropriately.

ERRORS
       EAGAIN The uid does not match the current uid and  uid  brings  process
              over its RLIMIT_NPROC resource limit.
可以看到,setuid是可能发生错误的,并且在uid的进程数超过RLIMIT_NPROC极限时,发生EAGAIN错误。


在android的源码中,setuid()定义于<android_src>/bionic/libc/unistd/setuid.c,实际上引用了一个外部符号__setuid,
这个符号在<android_src>/bionic/libc/arch_xxx/syscalls/__setuid.S中定义,最终是一个%eax=$__NR_setuid32,%ebx=uid的int 0×80中断。

因为只是要分析原理,我们不再鏖战于Android,转而看向Linux内核。
在最新的kernel2.6中,setuid()位于kernel/sys.c的682行,其中,在697行,一切正常的情况下,它会调用set_user()来完成用户切换。

set_user()实现于同一文件的587行,其中一部分代码如下:
kernel/sys.c
代碼:if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
        new_user != INIT_USER) {
    free_uid(new_user);
    return -EAGAIN;
}
含义很明显,当目标用户的进程数达到上限,那系统就不能再将一个进程分配给它,因而返回-EAGEIN。然后再setuid()中,直接跳过后面的代码,而返回错误。

至此,整个漏洞的原理已经分析完毕。整理如下:

1、在Android的shell用户下,制造大量的僵尸进程,直至达到shell用户的进程数上限RLIMIT_NPROC;

2、kill当前系统中的adb进程,并再次占据其进程位置以保持达到上限;

3、系统会在一段时间后重启一个adb进程,该进程最初是root用户,在完成少许初始化工作后,调用setuid()切换至shell用户;

4、此时shell用户的进程数已经达到上限,所以setuid()失败,返回-1,并且用户更换没有完成,adb还是root权限;

5、adb没有检查setuid()的返回值,继续后续的工作,因此产生了一个具有root权限的adb进程,可以被用于与用户的下一步交互。

实际上,setuid在目标用户进程数达到RLIMIT_NPROC极限时返回错误,这一问题可能产生的安全隐患最早可以追溯到2000年。而在2006年,出现了真正利用这一编码问题的漏洞(CVE-2006-2607)。

因此,这并不是一个全新的漏洞。我们可以得出几点结论:

1、函数返回值一直是忽略的对象,因为getuid()永远不会失败,程序员可能会认为setuid()也不会失败——至少没有遇到过,因此忽略了对返回值的检查。检查一个系统函数是否调用失败是一个常识,但又是很麻烦的事,如果为了省事而忽略,问题就可能产生了。

2、Android下的安全问题,很多并非全新的,而且个人判断将来还会有大量漏洞、恶意代码产生于传统思路,而作用于新的平台。面对这一新的平台,我们是否能抢先于攻击者做好防范准备,是一个需要我们思考和实践的问题。











分享到:
评论

相关推荐

    android root权限包

    Android root权限包,如描述中提到的"android root权限包 su zip",通常是一个包含了获取root权限所需工具和脚本的压缩文件,用于解锁Android设备的全部潜力。 首先,我们来详细了解一下root权限是什么。在Android...

    android 请求root权限

    在Android系统中,根权限(root权限)是一个高级权限,允许用户访问系统级别的文件和功能,这在默认情况下是被禁止的。对于开发者或者高级用户来说,获取root权限能够实现更多的自定义和优化操作,例如修改系统文件...

    Android应用程序请求root权限代码

    本文将详细介绍如何在Android应用中实现弹窗请求root权限的功能,并对提供的代码进行深入分析。 #### 二、代码解读 ```java /** * 获取Root权限设备(ROOT权限) * getPackageCodePath() * @param pkgCodePath ...

    android获取root权限

    其次,获取 root 权限可以让用户安装一些需要root权限的应用程序,例如一些游戏和工具等等。 那么,谁需要获取 root 权限呢?第一类人群是黑客或喜欢对系统进行hacking的人,因为他们需要更多的控制权和自由度。第...

    android 获取root权限工具

    在Android系统中,root权限是最高级别的访问权限,允许用户对设备有全面的控制,包括修改系统文件、安装自定义固件、删除预装应用等。对于开发者来说,获取root权限能够更深入地调试和优化应用程序,而对于普通用户...

    安卓手机Root权限破解.doc

    许多机友新购来的Android机器没有破解过Root权限,无法使用一些需要高权限的软件,以及进行一些高权限的操作,其实破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/system/bin/或/system/xbin/...

    root权限破解

    root权限破解 可以快速破解android系统的root权限

    android root 权限测试app

    在Android系统中,"root权限"是指获得手机操作系统最底层的访问权限,允许用户执行对系统文件和设置的更改,通常这些更改在普通用户模式下是不允许的。这个"android root 权限测试app"可能是为了帮助开发者或者高级...

    手机root权限破解

    许多机友新购来的Android机器没有破解过Root权限,无法使用一些需要高权限的软件,以及进行一些高权限的操作,其实破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/system/bin/或/system/xbin/...

    安卓系统Root权限破解

    根据作者的介绍,v1.9.1能够获取任意Android版本的ROOT权限(Android 2.3.4除外)。 请一定要确认你的电脑中已经安装了USB驱动了! 还有需要拔出外置SD卡! 如果红字部分你都做到了还不能够成功ROOT的话,请尝试...

    Android9.0 开放root权限

    主要是针对P版开发adb root和app root权限,资源基于MTK方案。

    android 10获得root权限补丁

    android 10获得root权限补丁,在rk3288上测试有效。

    android apk获取root权限方法总结

    Android APK 获取 Root 权限方法总结 Android APK 获取 Root 权限是一个复杂的技术难题,许多开发者和用户都遇到过这个问题。那么,如何使 Android APK 获取 Root 权限呢?今天,我们将总结一些常见的方法来获取 ...

    Android root下修改设备分辨率

    在Android系统中,修改设备分辨率通常涉及到对系统底层设置的更改,这通常需要获取设备的Root权限。Root权限是Android系统中的超级用户权限,允许用户访问和修改系统核心文件,包括与显示分辨率相关的配置。然而,...

    Android中的软件的自动更新(包括静默更新,需Root权限)

    本篇文章将深入探讨Android软件的自动更新机制,特别是涉及静默更新以及需要Root权限的情况。 首先,自动更新是一种自动下载和安装应用新版本的过程,无需用户手动操作。Android Market(现为Google Play Store)...

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

    android root权限破解分析 许多机友新购来的Android机器没有破解过Root权限,无法使用一些需要高权限的软件,以及进行一些高权限的操作,其实破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/...

    SuperOneClick android Root 权限绿色工具

    **Android Root权限详解** 在Android操作系统中,Root权限是指获得系统最高级别的管理权限,类似于Windows系统中的管理员权限。这种权限允许用户访问并修改系统级别的文件和设置,包括但不限于系统核心、服务以及...

    全志A33核心板-获取Root权限

    在Android系统中,root权限是最高级别的管理员权限,允许用户对系统进行深度定制和优化。本文将详细介绍如何为全志A33核心板获取Root权限,并探讨其在安卓系统中的应用与风险。 首先,获取Root权限的基本步骤通常...

    赋予ANDROID-root权限

    ### 赋予ANDROID模拟器Root权限详解 在Android开发过程中,有时我们需要对模拟器进行更深层次的操作,比如安装特定的应用、修改系统设置等。这时就需要获取模拟器的root权限。本文将详细介绍如何通过ADB(Android ...

Global site tag (gtag.js) - Google Analytics