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位,我們查看一下My Phone(已經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破解再神秘了吧!