1.Android Root原理(转)

原地址:http://blog.csdn.net/hsluoyc/article/details/50560782
防止原地址不能使用,我就ctrl + v

第1章 Root的基本原理

Android的内核就是Linux,所以Android获取root其实和Linux获取root权限是一回事儿。

你想在Linux下获取root权限的时候就是执行sudo或者su,接下来系统会提示你输入root用户的密码,密码正确就获得root权限了。Android本身就不想让你获得Root权限,大部分手机出厂的时候根本就没有su这个程序。所以你想获得Android的root权限,第一步就是要把编译好的su文件拷贝到Android手机的/system/bin或者/system/xbin/目录下。我们先假设你可以把su放在xbin下,接下来你可以在Android手机的adb shell或者串口下输入su了。

Linux下su以后输入密码就可以root了,但Android里的su和Linux里的su是不一样的,Android里的su不是靠验证密码的,而是看你原来的权限是什么。意思就是如果你是root,那你可以通过su切换到别的用户,比如说shell,wifi,audio什么的。但如果你是root之外的其他用户,就不能切换回root了,会提示你permission denied。(具体su是怎么做到这一点的,我准备过几天有时间的时候写在下面,单独说明)

也就说用root运行su才有用,但我这个时候还没有root怎么办呢?这就涉及到另外个问题。

一般我们在Linux的console下输入ls -l 会列出所有文件的权限。

比如:-rwxr-xr-x,用过Linux的人都知道r代表该文件可读,w代表可写,x代表可执行,-就代表没有该权限。第一个rwx代表文件所有者的权限,第二个rwx代表和所有者同组人的权限,第三个rwx代表其他用户对该文件的权限。但下面这个文件就比较特殊。

rws,它的执行权限标志位是一个s,s代表当任何一个用户执行该文件的时候都拥有文件所有者的权限,这文件的所有者是root,简单点说就是不管谁执行这个文件,他执行的时候都是以root身份执行的。

也就说即使我不是root也有可能以root身份来执行程序,那么我就把一个所有者是root的su程序权限标志位置成-rwsr-xr-x,那么不管谁执行它,都是root身份执行,su就可以顺利执行成功了,执行成功之后我就是root身份了。

问题都清楚了,就是你需要把一个所有者是root的su拷贝到Android手机上,并且把su的权限标志位置成-rwsr-xr-x。能把这个事情搞定你就成功root了一个手机。

大概意思就是两行代码

cp /data/tmp/su /system/bin/ #copy su 到/system/分区
chown root:root su #su的所有者置成root
chmod 4775 /system/bin/su #把su置成-rwsr-xr-x

然而,执行上面的每一行代码都需要root权限才能成功。

意思就是说,你只有有root权限的情况下才能执行上面两行代码,而这两行代码就是为了让你获得root权限的,这是一个逻辑闭环,那么如何打破这个逻辑闭环呢?

一个办法就是找一个本身已经有root权限的进程来启动我上面的两行代码,那我这两行代码一启动就是root权限,就可以顺利执行了。但是已经有root权限的进程都是出厂时候就装到手机上的,代码写死了,你没法控制它执行你自己的代码啊。这个时候就需要你找漏洞了,比如用来破解Android2.3 root权限的zergRush漏洞就是利用一个拥有root权限的进程栈溢出漏洞。

第2章 Root的由来

什么是Root?

Root本身是指Linux系统的root帐户,该帐户拥有整个系统至高无上的权利,系统中的所有对象它都可以操作,对于Android手机用户来说的Root是指拥有Root权限,一般情况下,手机厂商出于安全考虑会关闭手机的Root权限,手机系统是运行在普通用户权限下的,用户是无法操作系统中的文件与数据的。

Root与刷机本身是有很多关联的,而且随着刷机工具的便利与刷机原理的变化,两者的关系更加是模糊不清了。不同厂商针对获取Root权限设置了不同的要塞。

首先从刷机说起,如HTC手机在刷机前需要保证S-OFF,S-OFF代表什么呢?S代表SecurityLock安全锁,保护锁的意思,S-OFF就是关掉锁保护。然后是Motorola的手机,这个厂商对于不同型号的手机设置是不同的,很多Motorola型号的手机将BootLoader是锁住的,因此,在刷机前需要先解锁BootLoader。还有中兴手机,这厂商更是变态,一次次的版本升级只是为了锁住用户不让用户升级,也就导致了同一型号的手机由于版本不同有的型号带Recovery,有的又不带。三星的手机现在可以说是最好卖的,一方面是出色的硬件配置与外观,另一方面是有众多的Rom包可以刷。三星的好几款手机是Google源码的测试样机,而且三星手机在出厂时对用户的限制相比其它品牌是较少的,这也是广大Android开发者对它青睐有加的原因。

早先的Android手机要想获取Root权限可以有以下几种方式:

1)使用本地提权漏洞利用工具来直接Root,这是最原始最纯洁的方式。随着厂商对Rom的升级,这些内核的漏洞随时都可能被修补,因此,这种Root方法在时间与空间上都有着很大的局限性。

2)由于手机厂商对硬件的封闭,加上内核补丁修补很完全,这个时候获取Root权限就更难了,这个时候刷机与Root就联合起来了,由于不能从系统内部通过Exploits来获取Root权限,只能通过修改Rom包来达到Root的目的,这也是目前很多第三方Rom包自带了Root的原因,然而手机厂商也不是吃干饭的,手机厂商在OTA升级时使用Recovery对包签名进行验证来防止用户刷入修改过的包。对于这种变态的厂商,只能通过FastBoot来线刷了,这里内容就不再展开了。

3)当然,还有一部分厂商,为了吸引更多用户购买他们的手机,还是在手机中偷偷的留了后门的,比如不锁BootLoader,让用户刷第三方的Recovery,又或是干脆留个以前的漏洞不补,让用户自己来Exploits等等

第3章 RageAgainstTheCage漏洞分析

假设需要破解的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) {
          ......
          setgid(AID\_SHELL);
          setuid(AID\_SHELL);
          ......
      }
  }

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

1: 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权限下面了。
4)这时重新用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进程异常退出,就把这个漏洞给堵上了。为什么这么多设备都没有堵上这个漏洞呢?我觉得是设备厂商的策略(不排除傻X的厂商存在哦),虽然知道怎么封堵漏洞但是就是留着个后门给大家,让第三方给自己定制rom,提高自己系统的易用性。

第4章 Superuser与su如何协作

su与SuperUser.apk是如何协作的
在Root后手机会植入su与superuser.apk两个文件,前者会被放入手机的/system/bin目录下,后者被放到/system/app目录下,它们组合在一起,为系统提供了su权限的管理。这两个工具目前由xda论坛上的ChainsDD在维护(顺便说一下,国内xxRoot工具也有自已的su与SuperUser.apk文件,修改取自并修改于ChainsDD的代码,并且版权被切)。 su程序与Linux平台上的su本身无太大差别,只是由于系统的特殊性去掉了部分内容,并加上了一些控制代码。su程序保留的命令行参数不多,"-c"与"-s"可能是最常用的,整个程序核心功能由两个方向性的函数allow()与deny()组成,在经过计算获取到了命令行参数与命令后,会执行以下代码:

if(su_from.uid == AID\_ROOT || su_from.uid == AID_SHELL)
       allow(shell, orig_umask);
   if (stat(REQUESTOR_DATA_PATH, &st) < 0) {
       PLOGE("stat");
       deny();
    }
    ……
   setgroups(0, NULL);
   setegid(st.st_gid);
   seteuid(st.st_uid);

AID_ROOT与AID_SHELL分别是root与shell权限,程序直接放行,stat()函数会检查手机是否安装有SuperUser.apk,没有程序会拒绝执行。条件满足就会以Superuser的权限往下执行:

db =database_init();
if (!db) {
    LOGE("sudb - Could not open database,prompt user");
    dballow = DB_INTERACTIVE;
} else {
    LOGE("sudb - Database opened");
    dballow = database_check(db, &su_from,&su_to);
    sqlite3_close(db);
    db = NULL;
    LOGE("sudb - Database closed");
}
switch (dballow){
        case DB_DENY: deny();
        case DB_ALLOW: allow(shell,orig_umask);
        case DB_INTERACTIVE: break;
        default: deny();
    }

database_init()与database_check()负责从SuperUser.apk程序databases目录下的permissions.sqlite数据库中读取权限设置,这也是为什么SuperUser.apk有能力控制su的原因!(人家主动找上门的)等dballow弄到手,该放行该拒绝就看着办了,如果没搜索到记录就代表是第一次,需要往下建立socket来send_intent,send_intent()采用底层构造Intent方式来发送广播,这个广播会被SuperUser.apk接收,等返回后会给你返回个字符串”ALLOW”或”DENY”,这时候su程序该咋地就咋地了:

if(send_intent(&su_from, &su_to, socket_path, -1, 0) < 0) {
    deny();
}

if(socket_receive_result(socket_serv_fd, buf, sizeof(buf)) < 0) {
    deny();
}
……
 if (!strcmp(result, "DENY")) {
    deny();
} else if(!strcmp(result, "ALLOW")) {
    allow(shell, orig_umask);
} else {
    LOGE("unknown response from SuperuserRequestor: %s", result);
    deny();
}

下面是SuperUser.apk的工作了,上面的广播会被SuperUser.apk的SuRequestReceiver广播接收者收到,广播接收者首先读取prompt设置,如果用户要的是自动处理,那就根据这个值来对Root权限请求自动拒绝或自动放行,如果不自动处理,就到数据库中搜索权限规则,并根据结果发回处理,另外SuperUser除了对普通的程序进程su权限控制外,还提供了NFC、SecretCode、PinCode的监控,SuperUser同时注册了安装与卸载Apk的广播接收者,在安装与卸载时会对权限数据库中的条目进行更新或删除操作,限于篇幅,SuperUser的详细实现在此就不再展开了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 玩儿过Linux的应该都明白Root代表了什么,获取Root权限你就能控制系统的一切,甚至还可以执行rm -rf ...
    freeman521阅读 5,094评论 1 10
  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 98,523评论 9 468
  • 如果让我去孤岛呆一个月,只能带一种食物,我选择玉米。如果有什么能让我早晨六点就起床去早市,那也很有可能是因为...
    西楼风雨阅读 441评论 0 0
  • 下雨了。 从上午的时候就天色阴暗,明明知道今天免不了一场雨,就期待着,不要是太大的雨,好似以前晚上出去上自习,一出...
    2小阅读 236评论 0 0