前言
一直很好奇Android Root的原理,恰好最近碰到了一個(gè)跟Android默認(rèn)帶Root權(quán)限的問(wèn)題,這里順便記錄一下Android系統(tǒng)root的原理。
原理
Android是基于Llinux內(nèi)核的開(kāi)源操作系統(tǒng),與Ubuntu系統(tǒng)類似,所以在Android里獲取root權(quán)限其實(shí)和在Linux系統(tǒng)下獲取root權(quán)限是一回事。在Linux系統(tǒng)下獲取root權(quán)限的方法是在命令行執(zhí)行sudo或者su,接下來(lái)輸入提權(quán)密碼就可以獲取root權(quán)限了。Android系統(tǒng)其實(shí)也是這樣,例如應(yīng)用層程序開(kāi)發(fā),在root過(guò)的手機(jī)上運(yùn)行root權(quán)限的代碼如下所示:
1
2
3
4
5
|
Process process = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); ...... os.writeBytes("HelloWorld!\n"); os.flush(); |
我們可以看到,Android應(yīng)用程序獲取root權(quán)限也是需要執(zhí)行su命令,因此Android能夠root的密碼都在su程序上。但是,Android本身是不想讓你獲取root權(quán)限的,因此大部分手機(jī)出廠都是user版本,默認(rèn)是不帶su這個(gè)二進(jìn)制程序的。所以你想獲取Android的root權(quán)限,第一步就是要把編譯好的su文件拷貝到Android手機(jī)的/system/bin或/system/xbin目錄下(為什么要拷貝到/system目錄下,是因?yàn)檫@個(gè)分區(qū)是沒(méi)有nosuid限制的,同時(shí)/system/bin和/system/xbin又都是系統(tǒng)環(huán)境變量PATH里的路徑,可以直接執(zhí)行su)。我們先假設(shè)你可以把編譯好的su程序放在xbin或者bin目錄下,接下來(lái)你可以在Android手機(jī)的adb shell或者串口下輸入su提權(quán)了。
Linux命令行下輸入su之后,是需要輸入root密碼才能夠提權(quán)的,但是Android里的su和Linux里的su是不一樣的,Android里的su是不靠驗(yàn)證密碼的,而且需要驗(yàn)證你之前的權(quán)限是什么。意思是,如果你是root用戶,那你可以通過(guò)su切換到別的用戶,比如shell、wifi、audio等。但是如果你是root之外的其他用戶,就不能切換到root了,會(huì)提示你permission denied。也就是說(shuō),用root運(yùn)行su才有用,但是這個(gè)時(shí)候我沒(méi)還有root權(quán)限怎么辦?這就是接下來(lái)要討論的問(wèn)題。
我們?cè)赨buntu下查看/usr/bin/passwd文件的權(quán)限,如下圖所示:
這個(gè)文件的權(quán)限比較特殊,Linux用戶一般都知道文件分為r、w、x權(quán)限,那這個(gè)s是神馬意思呢?這里回答一下,s代表當(dāng)任何一個(gè)用戶執(zhí)行該文件的時(shí)候都擁有文件所有者的權(quán)限,這文件所有者是root。簡(jiǎn)單來(lái)說(shuō),就是不管誰(shuí)執(zhí)行這個(gè)文件,他執(zhí)行的時(shí)候都是以root身份來(lái)執(zhí)行的。
看到這里,大家是不是都有思路了,也就是說(shuō),即使我不是root用戶也可能以root用戶的身份來(lái)執(zhí)行程序,那么我把一個(gè)所有者是root的su程序權(quán)限標(biāo)志位設(shè)置為-rwsr-xr-x,那么不管是誰(shuí)執(zhí)行它,都是以root身份執(zhí)行。這就牛逼了,su果斷可以執(zhí)行成功,那你也就可以順利的獲取root權(quán)限了。
破解
原理都清楚了,那root的過(guò)程其實(shí)就是分兩步:
1. 把一個(gè)所有者是root的su拷貝到Android手機(jī)上。
2. 把su的權(quán)限標(biāo)志位設(shè)置成-rwsr-xr-x。
寫(xiě)成代碼大概如下所示:
1
2
3
|
cp /sdcard/su /system/xbin/ chown root:root /system/xbin/su chmod 4755 /system/xbin/su |
代碼看起來(lái)很簡(jiǎn)單,但是想真正的運(yùn)行成功,以上代碼每一句都需要root權(quán)限執(zhí)行。我擦,一下回到解放前,跟先有雞還是先有蛋的問(wèn)題類似,代碼運(yùn)行需要root權(quán)限,而代碼本身的目的就是獲取root權(quán)限,成了一個(gè)封閉的死循環(huán)了。但是所幸Android系統(tǒng)有Bug,因此就給了你打破這個(gè)死循環(huán)的機(jī)會(huì)。
打破的方法就是找一個(gè)本身已經(jīng)有root權(quán)限的進(jìn)程來(lái)運(yùn)行這個(gè)3行的shell腳本,這樣腳本就可以順利執(zhí)行了。但是已經(jīng)有root權(quán)限的進(jìn)程都是出廠時(shí)候就裝到手機(jī)上的,代碼寫(xiě)死了,你沒(méi)法控制它執(zhí)行自己的代碼啊,這個(gè)時(shí)候就需要查找漏洞了。例如Android2.3 root權(quán)限的zergRush漏洞就是利用一個(gè)擁有root權(quán)限的進(jìn)程棧溢出漏洞。具體利用漏洞的方法大家就可以自行g(shù)oogle了。
防止root
通過(guò)上述分析,我們可以簡(jiǎn)單的理解,解決Android系統(tǒng)能夠su提權(quán)的方法就是把su文件干掉就可以了。