android的 root权限
本文將從幾個方面,由淺至深地講述ROOT到底是什么東西?
一. ROOT權(quán)限簡單介紹
二.為什么需要ROOT
三. ADBD的ROOT權(quán)限
四.深入源代碼
ROOT權(quán)限簡介:
ROOT權(quán)限是Linux內(nèi)核中的最高權(quán)限,如果你的身份是ROOT,那么你就具有了ROOT權(quán)限。有了最高權(quán)限,你就可以為所欲為,換句話說,如果惡意程序獲取到了ROOT權(quán)限,那么就可以肆意地破壞你的手機(jī),獲取的隱私...所以廠商一般在生產(chǎn)手機(jī)的時候,不會提供給用戶ROOT權(quán)限,官方宣稱是為了保護(hù)用戶手機(jī)的安全,然后裝了一堆開機(jī)自動啟動,而用戶這輩子也用不到也卸載不了垃圾軟件(相信使用安卓的同學(xué)們都懂我的意思),而蘋果所說的越獄,也就是獲取ROOT權(quán)限。
為什么需要獲取ROOT權(quán)限?
蘋果用戶獲取ROOT權(quán)限,是為了可以免費(fèi)安裝各種軟件,以及為了獲取更加靈活的操作體驗,蘋果不會安裝一堆惡心的軟件;而安卓普通用戶獲取ROOT權(quán)限,最大的目的就是為了卸載這些惡心的自帶軟件,安卓極客用戶則是為了各種折騰安卓手機(jī),安卓開發(fā)人員是為了得到日志文件,分析BUG。
ADBD的ROOT權(quán)限:
ADBD是什么?相信大家都看過,IT男把手機(jī)連上電腦,然后不知怎么的彈出一個黑乎乎的窗口,上面有一排排白色的英文字母,然后帥氣的敲擊著鍵盤(一般敲擊 adb shell,然后進(jìn)入手機(jī)),啪啪幾下,可以幫你解決一些手機(jī)的問題。這個可以和手機(jī)交互的進(jìn)程就是ADBD。這就好比,你去朋友家玩,然后你朋友家比較高端,進(jìn)大門之前有個可視對講機(jī),那么你首先通過對講機(jī)呼叫朋友(敲擊adb shell),看看在不在家(手機(jī)是否相應(yīng)adb shell這個命令),如果朋友在家,那么就會通過對講機(jī)為你開門(成功進(jìn)入手機(jī)中),提供這個服務(wù)的可視對講機(jī)就相當(dāng)于ADBD。說白了,ADBD就是可以為你提供一種進(jìn)入手機(jī)內(nèi)部的服務(wù)通道。
那么為什么需要ADBD具有ROOT權(quán)限?這就涉及到另一個與ROOT息息相關(guān)的東西——su。
我們開機(jī)之后,使用手機(jī)的身份就是一個普通用戶(user),如果執(zhí)行su,那么就可以直接切換到ROOT身份。就像仙劍奇?zhèn)b傳三里面的景天,是個凡人,法力有限,但是大家都知道,他的前世是飛蓬將軍,法力高強(qiáng),天界無人能敵,只有魔界至尊重樓可以與他一較高下,當(dāng)他們來到天庭的時候,玉帝施法,讓景天直接切換成飛蓬將軍,于是他就有了飛蓬將軍的記憶和法力,與重樓又一次大戰(zhàn)。su就是這樣一個神奇的命令。
高通平臺上,su的相關(guān)代碼位于: LINUX/android/system/extras/su/su.c中
其實我們所說的越獄或者ROOT,就是把su安裝到手機(jī)里面 /system/bin目錄下,并把它的權(quán)限設(shè)置為4755,那么某些程序需要ROOT權(quán)限的時候,就可以通過su切換到ROOT身份,然后去執(zhí)行,因此一般被ROOT的手機(jī)都會安裝一個“超級用戶”這樣的應(yīng)用,就是用于管理哪些軟件可以切換到ROOT身份,哪些不可以,保證用戶安全,這個想法是很好很天真,對于正規(guī)的軟件,人家按照你的路子來,不正規(guī)的軟件,你一個小小的超級用戶的應(yīng)用,豈能擋我獲取ROOT,虐不死你。
那么為什么需要ADBD獲取ROOT權(quán)限呢?經(jīng)過上面的講解大家應(yīng)該能猜到,如果ADBD有ROOT權(quán)限,就可以通過adb 工具,為所欲為,而又不留下痕跡(不安裝su),可以刪除自帶垃圾軟件,獲取任意目錄的文件,安全性較高。筆者就是通過這種方式獲取一些系統(tǒng)級別文件。
深入代碼:
看了上面的文字,也許很多人會有這樣的想法,原來ROOT一個手機(jī)這么簡單?錯!一點也不簡單。
首先:/system分區(qū)是只讀的文件系統(tǒng),即你無法往system分區(qū)中寫入任何東西,其次就算你僥幸把su安裝到/system/bin下,你也沒法修改它的權(quán)限為4755,再者,即使你僥幸把su的權(quán)限設(shè)為4755,你也逃不過有些手機(jī)的反root機(jī)制(即檢測到有文件的權(quán)限為4755,就刪除)。
首先我們來看看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\n", myuid);return 1;} 這句話告訴我們,如果執(zhí)行su的不是ROOT或者SHELL用戶,那就直接退出,說明切換身份時候,你必須是這兩個用戶,還好我們用adb shell進(jìn)入,是SHELL用戶,好險啊。 if(argc < 2) {uid = gid = 0;} else {int gids_count = sizeof(gids)/sizeof(gids[0]);extract_uidgids(argv[1], &uid, &gid, gids, &gids_count);if(gids_count) {if(setgroups(gids_count, gids)) {fprintf(stderr, "su: failed to set groups\n");return 1;}}} 判斷執(zhí)行su的時候,有沒有其它參數(shù),我們只是執(zhí)行su,即argc < 2成立,su也可以切換成其它用戶(argc > 2,詳細(xì)看su命令的使用),這時候,uid 和 gid 都被設(shè)置為0 。即ROOT用戶的ID號和組號 if(setgid(gid) || setuid(uid)) {fprintf(stderr,"su: permission denied\n");return 1;} 來了來了,就是它,這就是我們最終的目的,把我變身成飛蓬將軍,如果一切順利,你就可以變身成功了(切換ROOT成功) /* Default exec shell. */execlp("/system/bin/sh", "sh", NULL); 每次su之后,就會變成root#,然后就可以通過控制臺繼續(xù)敲命令,但是不同的是,你已經(jīng)是ROOT了,權(quán)限已經(jīng)很大了。Android系統(tǒng)啟動的時候,ADBD是ROOT權(quán)限,只是后來被降級了,判斷是否降級的函數(shù)是should_drop_privileges()這個函數(shù):
static int should_drop_privileges() { #ifndef ALLOW_ADBD_ROOTreturn 1; #else /* ALLOW_ADBD_ROOT */ 首先判斷是否定義了ALLOW_ADBD_ROOT,如果系統(tǒng)都不允許你ROOT,就直接返回1,下面什么都不看了,就像找工作的時候,不管你多么厲害,如果你第一條要求都不符合,就直接把你pass了,說什么都沒用,夠狠的。 int secure = 0;char value[PROPERTY_VALUE_MAX];/* run adbd in secure mode if ro.secure is set and** we are not in the emulator*/property_get("ro.kernel.qemu", value, "");if (strcmp(value, "1") != 0) {property_get("ro.secure", value, "1");if (strcmp(value, "1") == 0) {// don't run as root if ro.secure is set...secure = 1; 下面就是獲取系統(tǒng)的屬性,判斷是否打開ROOT權(quán)限,可以看到如果ro.kernel.qumu 這個屬性被置為了,沒關(guān)系再給你一次機(jī)會,判斷ro.secure是否也是1,如果是,對不起你無法獲得root權(quán)限,我要把secure置為1了(secure為1意味著要降級,后面會講解),接著: // ... except we allow running as root in userdebug builds if the// service.adb.root property has been set by the "adb root" commandproperty_get("ro.debuggable", value, "");if (strcmp(value, "1") == 0) {property_get("service.adb.root", value, "");if (strcmp(value, "1") == 0) {secure = 0;}}}} 哈哈,又給了你一次機(jī)會,我再來判斷ro.debuggable是不是1,如果不是,對不起,我必須要降級,否則再給你一次機(jī)會,判斷service.adb.root這個屬性的值,如果也是1,那么就不降級,一般在編譯ROM版本的時候,會同事編譯兩個版本,一個是工程版本,是具有ROOT權(quán)限的ADBD,這樣方便開發(fā)者調(diào)試系統(tǒng),另一個就是我們用戶用的版本,叫user版本,這個是沒有ROOT權(quán)限的,可以看到,就是通過property_get一系列屬性來判斷是否降級。 return secure; #endif /* ALLOW_ADBD_ROOT */ } 最后,返回secure即可。可以看到最后決定是否降級的變量就是secure,所有如果有源代碼的話,只有最后將secure賦值為0,不管什么版本,最后都是ROOT權(quán)限。 if (should_drop_privileges()) {drop_capabilities_bounding_set_if_needed();gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET,AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,AID_NET_BW_STATS };if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {exit(1);/* then switch user and group to "shell" */if (setgid(AID_SHELL) != 0) {<span style="white-space:pre"> </span>//曾經(jīng)的漏洞,被封住了exit(1);}if (setuid(AID_SHELL) != 0) {<span style="white-space:pre"> </span>//曾經(jīng)的漏洞exit(1);}D("Local port disabled\n");} 從這段代碼可以看到,如果should_drop_privileges返回1,那么就可以降級了,降級函數(shù)為setgid(AID_SHELL)和setuid(AID_SHELL),曾經(jīng)有黑客利用一些方法,使得setgid和setuid執(zhí)行失敗,即降級失敗,以前的代碼中是沒有exit的,那么當(dāng)setuid和setgid執(zhí)行失敗之后,就不會降級。ROOT不是那么輕易的,現(xiàn)在有很多已知的漏洞,但是都被封鎖了,所有不是每個root工具都能root成功的,要看它采用的是什么方法來ROOT。
總結(jié)
以上是生活随笔為你收集整理的android的 root权限的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Stellarium(虚拟天文馆)
- 下一篇: 终端服务器超出了最大允许连接数解决办法