Android 的提權 (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
熟悉Android的同學都知道,執行上面的每一行代碼都需要root許可權才能成功。
意思就是說,你只有有root許可權的情況下才能執行上面兩行代碼,而這兩行代碼就是為了讓你獲得root許可權的,這是一個邏輯閉環,那麼如何打破這個邏輯閉環呢?
一個辦法就是找一個本身已經有root許可權的進程來啟動我上面的兩行代碼,那我這兩行代碼一啟動就是root許可權,就可以順利執行了。但是已經有root許可權的進程都是出廠時候就裝到手機上的,代碼寫死了,你沒法控制它執行你自己的代碼啊。這個時候就需要你找漏洞了,比如用來破解Android2.3 root許可權的zergRush漏洞就是利用一個擁有root許可權的進程棧溢出漏洞。
/*
* 棧溢出說白了就是這個進程讀到了自有內存之外的地址空間,這段內存空間沒分配給它,誰都能寫
* 這段內存,那我就可以把自己的兩行代碼預先寫到這裡,運行zergRush代碼,然後等那個倒霉的進
* 程執行我就行了。
*/
棧溢出這段也解釋錯了,關於棧溢出的解釋大家可以看答案下面@張炬 的評論。上面有下劃線的部分可以忽略。

如果各位有一定基礎,能看懂我上面講的,就基本知道原理其實並不難,難點在於找到漏洞。
zergRush的代碼在這兒:
revolutionary/zergRush · GitHub
有興趣的可以看看,網上也有很多分析文章。

另外iphone的越獄其實和Android的root是一回事兒,都是越權操作。所以越獄的方式也都差不多,也是找IOS自帶程序的漏洞,只不過IOS安全性強一點,所以也比較難找。如果你發現你的iphone的某個自帶程序經過一些特定操作會出現系統崩潰重啟的現象,並且是可以復現的,那就很有可能可以用來越獄了。
好像是IOS6出來的時候,由於比較難搞,某個越獄團隊就號召大家來找茬,發現的漏洞可以報告給他們用來越獄。說明IOS越獄越來越難。直接體現就是現在越獄需要的時間越來越長。
不過如果你發現漏洞也可以報告給蘋果,蘋果會根據漏洞嚴重程度給予一定獎勵。我記得看新聞說南非一個傢伙靠給蘋果找漏洞賺25萬美元。發家致富的好路子啊,哈哈。

================================================
謝謝各位支持
關於為什麼su一定要放到/system/bin/或者/system/xbin/
一個同事告訴我,這個問題我的解釋是錯的,su不能放在data分區原因是因為data分區在mount時就指定了不能給可執行程序加s位。你在adb shell里執行mount就可以看到,或者看我下面的截圖。

下面有下劃線的部分是我自己的解釋,各位可以忽略。
/*
* 首先,你當然可以把su這個程序copy到/data/分區,但你adb push進去的時候,su有這個程序的所
* 有者肯定不是root,一般是shell什麼的(記不清了,應該是和adbd這個進程的所有者一樣),這個時
* 候即使你把它許可權置為-rwsr-xr-x,哪你運行它的時候也是shell身份運行的,su會提示你輸入密碼
* 的。
* 第二我們root手機的目的是為了運行需要root許可權的APP,比如goagent或者什麼的。這些APP里代
* 碼需要獲得root的時候是這麼寫的:
* Process p = Runtime.getRuntime().exec("su");
* 也就是它們在代碼里調用了一下su這個程序,哪可以寫成下面這個樣子嗎?
* Process p = Runtime.getRuntime().exec("./data/tmp/su");
* 我沒寫過APP,不太清楚,估計是不行的。換句話說你必須把su放到環境變數PATH所有的目錄
* 里,APP才能調用到它。如果你不想放到bin或者xbin下,你就必須給PATH增加一個目錄。PATH是
* root許可權才能修改的,你如果能修改PATH,說明你已經有root許可權了,修改PATH就沒必要了,還
* 不如直接放到bin下面。
*/

關於sudo
android的工程里沒有sudo這個東西。sudo是為了給普通用戶臨時分配root許可權的,Android里建立了很多用戶,比如wifi,shell等等,這些用戶可以訪問那個文件,不可以訪問那個文件,代碼里已經寫死了,許可權也分配的很分明。它們在運行的過程中不需要臨時獲得root許可權。所以Android不需要sudo這個程序。

回復@吳利文
1. Android的su確實是不驗證密碼的,是我想當然了。答案已經修改了。
2. chmod 1755也是我錯了,應該是4755,答案已經改了。
3. 你的答案我看了,你沒發覺你跟我說的是一回事嗎?我覺得你應該是沒仔細看我的答案吧。
4. 你敘述的 so call"一般的root流程",只是一種方法,而這個問題是問原理。實際上不管你用什麼漏洞獲得了root,下面需要做的一樣的,都是copy su到xbin, chown最後chmod。你的「一般的root流程」和別人不管用什麼方法的二般流程有什麼區別嗎?不都是為了剛上面這些事嗎?

/* ChangeLog
* 08/13/2013
* 修改棧溢出的解釋錯誤
* 修改為什麼su一定要放到/system/bin/或者/system/xbin/的解釋錯誤
* 08/16/2013
* 修改chmod錯誤
* 修改運行su需要密碼的錯誤
* 回復somebody
*/


首先明白幾點
1. su是一個elf可執行文件,superUser是用來和su配合的root授權管理軟體。

2. 要執行su(其他程序獲取root許可權默認執行su)必須將su放在系統環境變數里,bin和xbin目錄,其他地方你需要加全路徑

3. bin和xbin目錄在system分區,默認只讀,所以要寫入su必須重新掛在該分區為可寫

知道這些再說如何root

1. 通過漏洞將自己進程提權到root許可權,具體做法要去了解漏洞利用原理

2. 進程獲取root許可權後重新掛載system分區可讀寫

3. 然後將su拷貝到bin目錄或者xbin目錄,由於su的所有者提權進程已經是root進程,所以su也具有root屬性。然後設置su文件755屬性,即所有者可讀可寫可執行,所在組和其他用戶可讀可執行,同時為了讓一般用戶在執行某些程序的時候,能夠暫時具有該程序擁有者的許可權,所以需要設置s標誌位,即其他評論提到的chmod 4755 su,superuser拷貝system目錄並安裝,放在system目錄下作為系統應用,防用戶刪除

4. 這樣其他程序調用su以後,先要經過superuser同意,用戶點同意後,由於su擁有者為root所以其進程也擁有root許可權,相應的它執行的命令也都是有root許可權, 詳細的做法可去github搜su源碼閱讀,最後執行的一句`execv(ctx-&>to.shell, ctx-&>to.argv + argc);`通過驗證後將su進程直接替換成需要執行的命令

基本過程就是這樣,重點在漏洞利用上,要考慮selinux等一些安全機制繞過,前邊幾個回答的都是漏洞利用提取以後的事情,這些操作大同小異,都是腳本來執行,可參考前邊提到的root精靈腳本。


滾了幾屏,算是看完了,這些都過時了;Android 4.2以後需要通過native service拉起su daemon之類的服務進程才能正常使用root相關功能;Android 5.x以後更需要搞定SELINUX才能正常使用root相關功能,所以新版本的授權管理一般都帶有類似seinject的功能來注入安全策略,依靠替換系統服務如zygote等native service。


作為補充,發一下之前從網上扒來的SU中的部分代碼,以此解釋Android是通過原有的許可權來判斷你有沒資格執行su :

/* 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
", myuid);
return 1;
}


Android 的提權 (root) 原理是什麼? @Kevin 更多提到ROOT管理背後的原理,這就是Android和Linux中的SID的用途,這是所有類UNIX通用的申請處理高許可權方式。

其實在我的理解中應該是兩個:
1,提權
2,ROOT

對於 1,提權 是利用系統的漏洞,獲得原本獲取不了的許可權,提升本應用的許可權。
已知的漏洞:
1.a:之前提到的利用adbd的漏洞,在2.X時代有效。這個利用的過程還是比較複雜,時間也比較長;
1.b:三星CPU的漏洞,比如在Galaxy繫上可以利用這個漏洞來ROOT,這個漏洞就比較好利用了,之接在APK代碼里就可以利用。在我的Galaxy Note上用過。
提權不一定是對於主系統(Android系統),還有些是針對輔助系統(BOOTLOADER和RECOVERY)。
1.c:三星系的手機可以利用一個BOOTLOADER的漏洞(我不太清楚是不是漏洞,但是三星本身沒有官方解鎖工具這一說的,難道是官方提供的?),可以任意的刷包,這樣我們就可以利用這個途徑來修改SYSTEM分區了,都有許可權修改SYSTEM分區了,往上放個文件還不是分分鐘的事。官方解鎖的就是提供方式,允許用戶刷入自定義的文件。
1.d:OPhone系統的老版本(2.0、2.5)中(不知道還有沒有人用這個系統)的RECOVERY存在一個關於路徑的處理的漏洞。它有一個自己定義的upk升級包,只能處理/system/carrier下的文件,但在路徑處理上估計是文本比較,你可以通過/system/carrier/../app這種方式來繞過它的管理系統,來修改/system/app下的文件。
一般情況下主系統的漏洞對用戶的危害最大,因為它使一個普通許可權的應用可以訪問到本沒有許可權訪問的資源。對於三星CPU漏洞,如果一個應用利用它提高自己的許可權,直接訪問簡訊的資料庫文件,而不是通過Android提供的Provider,系統就沒有使用沙盒檢查的機會,而且用戶也不知道它們做了什麼,你從它的許可權申請列表上也看不到它會讀取簡訊。
對於輔助系統的漏洞,一個普通的應用就沒有辦法了,因為平時輔助系統是不啟動的。但也並不是沒有利用的可能。

對於 2,ROOT 在我理解就是安裝ROOT管理工具,對於Linux的發行版本來說,本身提供了ROOT管理工具su還有sudo。但是對於Android來說本身沒有提供ROOT管理工具,所以我們需要利用提權的這個過程在系統中插入ROOT管理工具,以方便我們使用更高的許可權。因為畢竟提權這個過程一般來說不是很容易實現的。比如我們提到的BOOTLOADER或RECOVERY的漏洞,是沒有辦法在主系統中使用的,所以需要安裝ROOT管理工具以在主系統中使用。
ROOT之後因為可以修改系統,所以我們也有機會修復已知的漏洞,比如上面提到的三星CPU的漏洞。

以下由於本身半桶水水平,可能不正確,請輕拍:
對於ROOT本身來說不會降低系統安全性,除非ROOT管理器本身又有漏洞。所以通過官方解鎖的方式,使用安全的RECOVERY和安全的ROOT管理器,與官方的安全性一致。

但是兩個黑色的「安全」提醒著我們,市面上魚龍混雜的ROOT工具並不是都安全的,所以使用時一定選用大家認可的,安全的方式。例如說我們平時用的SuperU.apk和與其相配的su應用,在應用層申請ROOT許可權時,都會提示用戶許可。但是針對一些黑色的ROOT的管理工具,它如果留下後門,對於一些特定的請求不提示直接同意,而且不記錄日誌的話,這樣就像在自己的設備中下了一個定時炸彈一樣。


@Kevin 的答案有問題,看來他並不知道root的原理
先引用他的兩段話:

大概意思就是兩行代碼
cp /data/tmp/su /system/bin/ #copy su 到/system/分區
chmod 1775 /system/bin/su #把su置成-rwsr-xr-x
那怎麼搞定這個事情呢?Android的system分區本身不可寫,只有是root的許可權才能改動它,執行不了啊。

獲得root的時候是這麼寫的:

Process p = Runtime.getRuntime().exec("su");

也就是它們在代碼里調用了一下su這個程序,哪可以寫成下面這個樣子嗎?

Process p = Runtime.getRuntime().exec("./data/tmp/su");

先看第一段,理解沒有錯誤的話他是想說,只要system有了寫入的許可權,就可以執行這兩行代碼,進而獲取root許可權。既然Android的system分區不可寫,那乾脆不寫system,等獲取root許可權再寫入system就行了,第一條命令需要system可寫入,命令一隻是拷貝,其本身沒有實質性意義。第二條命令把su設置成-rwsr-x-rx也其實只完成了一半——

su還需要所有者(Owner)是root才能正確的給其他程序賦予root許可權。linux系統中,當前用戶執行的程序,該程序進程的 有效用戶ID(Effective UID)就是當前用戶,但擁有s(set uid)許可權的程序,其進程的有效用戶ID是這個程序的所有者。換句話說,有set uid許可權的程序,運行之後,就相當於所有者運行了這個程序,如果所有者是root,那這個進程也擁有root許可權。能夠正常授權的su,其所有者必須是root,否則不能正常授權。沒有root許可權的情況下,我們可以通過chmod來設置s許可權,但是不能使用chown來修改su的所有者為root(提示Unable to chown su: Operation not permitted)。

所以通過zergRush破解許可權的原因是,只有破解到了root許可權,才能設置su的所有者是root,才能有可正常使用的su。

再看第二段,就算把代碼改成Process p = Runtime.getRuntime().exec("./data/tmp/su");也不能獲得root許可權。正如我前面所說的,必須先修改su的所有者為root才能獲取root許可權,所以在破解到root許可權之前,無論做什麼都不能獲得一個有效的su。

現在root流程一般是zergRush破解root許可權,然後用root許可權啟動adbd,電腦端用adb登陸之後直接就擁有了root許可權,然後設置su許可權和所有者,重掛載system使system可寫入,然後拷貝su到/system/xbin/並安裝SuperSu,重啟手機。這個過程還可以變成 安裝SuperSu,破解root許可權,設置su的許可權和所有者,重啟手機,執行su,重掛載system,拷貝su自身到/system/xbin。看到了嗎,獲取root許可權跟system不可寫沒有關係,重掛載system並拷貝su到xbin只是為了讓應用程序更容易調用su罷了

PS: chmod 1775 /system/bin/su #把su置成-rwsr-xr-x
這個chmod的許可權應該是4755才對吧?1755對應的許可權是-rwxr-xr-t,連s都沒有

PPS:還有一點,Kevin說輸入su要密碼,安卓連/etc/passwd都沒有,哪來的密碼


最近也在搗鼓這個問題,想弄明白如何獲取最初的root許可權。很多命令比如mount,chown都需root許可權才能執行的。這些命令能夠執行成功,說明已經獲取到了臨時的root許可權了。

拷貝一段root精靈的執行腳本:

#!/system/bin/sh

export PATH=$PATH:/sbin:/system/bin:/system/sbin:/system/xbin:/data/local/tmp
//此句不需要root許可權,只是當前shell的path值會改變。

mount -o suid,remount /dev /dev || busybox mount -o suid,remount /dev /dev
//此句執行成功的話,是需要root許可權的,那麼root許可權從何來呢??
cat /system/bin/sh &> /dev/sh
chown 0.0 /dev/sh
chmod 06755 /dev/sh

#permanent root
mount -o remount,rw /system
if [ -d "/system/xbin/"]
then
dd if=/data/local/tmp/busybox of=/system/xbin/busybox
chown root.root /system/xbin/busybox
chmod 04755 /system/xbin/busybox
/system/xbin/busybox --install -s /system/xbin
/system/xbin/busybox --install -s /system/bin
rm /system/xbin/su
rm /system/bin/su
dd if=/data/local/tmp/su of=/system/xbin/su
chown root:root /system/xbin/su
chmod 06755 /system/xbin/su
ln -s /system/xbin/su /system/bin/su

else
dd if=/data/local/tmp/busybox of=/system/bin/busybox
chown root.root /system/xbin/busybox
chmod 04755 /system/bin/busybox
/system/bin/busybox --install -s /system/bin
rm /system/bin/su
dd if=/data/local/tmp/su of=/system/bin/su
chown root:root /system/bin/su
chmod 06755 /system/bin/su

fi

dd if=/data/local/tmp/KingUser.apk of=/system/app/KingUser.apk
chmod 0644 /system/app/KingUser.apk
pm install -r /system/app/KingUser.apk
rm /data/local/tmp/su
rm /data/local/tmp/KingUser.apk
rm /data/local/tmp/busybox


所有答案已經過時,Android 4.3以後就不能用setuid的su了,更不用說4.4以後的SELinux了


根本的問題在於獲取root許可權,然後執行什麼都是次要的了。

至於答案中提到的su啊sudo啊,之類的都是獲取了root許可權後的事情,不是問題的根本。

獲取root許可權不是你按照常規的在命令行執行一些命令或者運行一個程序就可以得到的。因為這些都是在linux的既定規則內玩,怎末可能破壞其規則?

所以只有一條路:非正常路徑,比如:找到bug和漏洞,讓規則破壞,從而獲得提權。或者在系統之外進行操作,比如系統還沒啟動就操作其磁碟上的文件系統,讓某些你安排的程序發生規則外的特性。這時候由於系統還沒啟動,任你擺布(他睡著完全沒有知覺和抵抗以及運行規則的能力)所以你可以換掉系統(涮rom把自己改過的系統刷上去)不過如果硬體上不允許那麼此路不通。


所以無論安卓、ios還是pc系統的linux,windows等都是一樣的。必須找到漏洞或走非常規路線才能取得特權。


而取得特權對於系統安全是十分嚴重的事情,即如果普通用戶很容易獲取到特權,那將是嚴重性的安全災難。
你想想如果運行於企業伺服器集群上的linux如果某個版本發現提權漏洞,那被黑客黑掉拿到數據的風險後果非常嚴重。


簡單點說,就是Android系統裡面沒有su這個可執行的文件,提權就是利用Android系統漏洞把su裝入系統。


對於ARM平台的root已經毫無壓力了,但是對於X86平台,就算將su和suuserapk給拷貝進去並賦予正確的許可權,也還是無法進行root的。不知道這個大家有啥辦法?


在Android里通常是在程序中執行su去獲取root許可權,而就是在這個su中調用了setUid(0)和setGid(0),大概是,記不清了,通過這兩個函數把你進程的uid設為和root一樣(root的uid就是0),所以也就是說你自己隨便寫一個可執行文件,去調用這兩個函數就能提權。
而要成功調用這兩個函數,需要特殊許可權,一般我們可以見到chmod 0777 xxx這樣的形式,前面的那個0就是對應的setUid和setGid的許可權,可以用chmod 4777 xxx去改。

其實看透了之後原理很簡單,一些操作可以在adb shell中實現,試試就知道了~


Android5.1 /system/xbin/su許可權已經是rwsr-xr-x了,arg shell -&> su或者adb root都可以,但是為啥在apk里執行su,然後寫入命令,顯示的是:java.io.IOException: write failed: EPIPE (Broken pipe)


簡單來說,其實就是linux系統裡面的su命令,切換root用戶,等於window系統的超級管理員。
安卓基於linux,su命令的效果一樣。
root就是在你的安卓系統裡面添加一個su二進位文件,當app需要使用root許可權時(一般都是涉及系統文件),就通過執行su文件獲取一個root的許可權。
而我們需要一個管理app獲取root許可權的管理軟體,這個就是平時用到的超級用戶等app。只有安裝了這個管理軟體之後,我們才可以限制app的root許可權,不然的話,如果系統本身不識別你安裝的su文件,app就可以直接使用root許可權。


一句話解釋:添加擁有最高許可權的su binary文件用於進行最高許可權操作。


DDMS有個工具 Dump View Hierarchy需要用到ROOT許可權
然後我找了root包,刷入後,
敲入命令adb shell
shell@android:$
輸入su後變為root@generic:#

另建了模擬器,敲入adb shell
直接顯示root@generic

想問下,第一種需要輸入su才變為root用戶
第二種直接是root用戶

這兩種用戶區別在哪裡?


推薦閱讀:

如何分析 iOS、Android 和 Windows Phone 的 UI 設計?
如何評價索尼 Xperia Z3 手機?
大家都知道安卓的經典解鎖是3×3的格子!而最少需要4個點才能當做一個密碼,那麼,理論上3×3的鎖,一共有多少種解鎖密碼?
小米的出現,對中國手機行業產生了哪些影響,還會怎樣影響?
如何說服女朋友換安卓手機?

TAG:RootAndroid | Android |