一、 概述 本文介紹了android中獲取root權(quán)限的方法以及原理,讓大家對android 玩家中常說的“越獄”有一個(gè)更深層次的認(rèn)識。
二、 Root 的介紹 1. Root 的目的 可以讓我們擁有掌控手機(jī)系統(tǒng)的權(quán)限,比如刪除一些system/app下面的無用軟件,更換開關(guān)機(jī)鈴聲和動(dòng)畫,攔截狀態(tài)欄彈出的廣告等。 2. Root的原理介紹 谷歌的android系統(tǒng)管理員用戶就叫做root,該帳戶擁有整個(gè)系統(tǒng)至高無上的權(quán)利,它可以訪問和修改你手機(jī)幾乎所有的文件,只有root才具備最高級別的管理權(quán)限。我們r(jià)oot手機(jī)的過程也就是獲得手機(jī)最高使用權(quán)限的過程。同時(shí)為了防止不良軟件也取得root用戶的權(quán)限,當(dāng)我們在root的過程中,還會給系統(tǒng)裝一個(gè)程序,用來作為運(yùn)行提示,由用戶來決定,是否給予最高權(quán)限。這個(gè)程序的名字叫做Superuser.apk。當(dāng)某些程序執(zhí)行su指令想取得系統(tǒng)最高權(quán)限的時(shí)候,Superuser就會自動(dòng)啟動(dòng),攔截該動(dòng)作并作出詢問,當(dāng)用戶認(rèn)為該程序可以安全使用的時(shí)候,那么我們就選擇允許,否則,可以禁止該程序繼續(xù)取得最高權(quán)限。Root的過程其實(shí)就是把su文件放到/system/bin/ Superuser.apk 放到system/app下面,還需要設(shè)置/system/bin/su可以讓任意用戶可運(yùn)行,有set uid和set gid的權(quán)限。即要在android機(jī)器上運(yùn)行命令:adb shell chmod 4755 /system/bin/su。而通常,廠商是不會允許我們隨便這么去做的,我們就需要利用操作系統(tǒng)的各種漏洞,來完成這個(gè)過程。 特別說明:我們燒機(jī)中的Eng版本并沒有Root權(quán)限 3. Root的方法 從Root的原理我們了解到,root 過程分三步: a. adb push su /system/bin b. adb push SuperUser.apk /system/app c. adb shell chmod 4755 /system/bin/su 若系統(tǒng)是eng版的,做到以上三步,那么我們Root就大功告成,但實(shí)際是不行的。為什么呢?原因有三: 1、user版的/system路徑是只讀權(quán)限,不能簡單寫入 2、 chmod需要Root權(quán)才能運(yùn)行(死循環(huán)了) 3、有些系統(tǒng)在啟動(dòng)時(shí)會自動(dòng)將su的4755權(quán)限設(shè)成755,甚至直接刪除su 那么針對這種情況,我們怎么辦呢?非常簡單:燒一個(gè)eng版本的boot.img就行了 可以用展訊的燒錄工具,或者用fastboot模式從sd卡燒一個(gè)boot.img文件即可 至此,我們Root就成功了,可以用R.E(Root Explorer)在根目錄創(chuàng)建和刪除文件。
三、 深入理解Root機(jī)制 其流程是: 1. Su 被用戶調(diào)用 2. Su 創(chuàng)建了一個(gè)socket監(jiān)聽 3. Su 向Superuser發(fā)送了一個(gè)廣播,說是有一個(gè)程序要請求root 4. Su 等待socket 數(shù)據(jù)接收。有超時(shí)處理。 5. Superuser 界面收到廣播后,彈出一個(gè)對話框,詢問用戶 6. Superuser 向傳來的數(shù)據(jù)中的socket寫回用戶應(yīng)答結(jié)果。 7. Su 根據(jù)socket得到的結(jié)果處理應(yīng)該不應(yīng)該繼續(xù)執(zhí)行 8. 完成提權(quán)管理
superuser.apk這個(gè)程序是root成功后,專門用來管理root權(quán)限使用的,防止被惡意程序?yàn)E用。 源碼地址: http://superuser./svn/trunk 我們有兩點(diǎn)疑問: 1. superuser是怎么知道誰想用root權(quán)限? 2. superuser是如何把用戶的選擇告訴su程序的? 即superuser和su程序是如何通訊的,他們倆位于不通的時(shí)空,一個(gè)在java虛擬中,一個(gè)在linux的真實(shí)進(jìn)程中。 superuser共有兩個(gè)activity: SuperuserActivity 和 SuperuserRequestActivity ,其中SuperuserActivity 主要是用來管理白名單的,就是記住哪個(gè)程序已經(jīng)被允許使用root權(quán)限了,省的每次用時(shí)都問用戶。 SuperuserRequestActivity 就是用來詢問用戶目前有個(gè)程序想使用root權(quán)限,是否允許,是否一直允許,即放入白名單。 這個(gè)白名單比較關(guān)鍵,是一個(gè)sqlite數(shù)據(jù)庫文件,位置: /data/data/com.koushikdutta.superuser/databases/superuser.sqlite 上文說過,root的本質(zhì)就是往 /system/bin/ 下放一個(gè)su文件,不檢查調(diào)用者權(quán)限的su文件。普通程序可以調(diào)用該su來運(yùn)行root權(quán)限的命令。superuser.apk中就自帶了一個(gè)這樣的su程序。一開始superuser會檢測/system/bin/su是否存在: File su = new File("/system/bin/su"); // 檢測su文件是否存在,如果不存在則直接返回 if (!su.exists()) { Toast toast = Toast.makeText(this, "Unable to find /system/bin/su.", Toast.LENGTH_LONG); toast.show(); return; } //如果大小一樣,則認(rèn)為su文件正確,直接返回了事。 if (su.length() == suStream.available()) { suStream.close(); return; // }
// 如果檢測到/system/bin/su 文件存在,但是不對頭,則把自帶的su先寫到"/data/data/com.koushikdutta.superuser/su" //再寫到/system/bin/su。 byte[] bytes = new byte[suStream.available()]; DataInputStream dis = new DataInputStream(suStream); dis.readFully(bytes); FileOutputStream suOutStream = new FileOutputStream("/data/data/com.koushikdutta.superuser/su"); suOutStream.write(bytes); suOutStream.close();
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(); 有進(jìn)程使用root權(quán)限,superuser是怎么知道的呢,關(guān)鍵是句: sprintf(sysCmd, "am start -a android.intent.action.MAIN -n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRequestActivity --ei uid %d --ei pid %d > /dev/null", g_puid, ppid); if (system(sysCmd)) return executionFailure("am."); 原理是am命令,am的用法: usage: am [subcommand] [options] start an Activity: am start [-D] [-W] <INTENT> -D: enable debugging -W: wait for launch to complete start a Service: am startservice <INTENT> send a broadcast Intent: am broadcast <INTENT> start an Instrumentation: am instrument [flags] <COMPONENT> -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT) -e <NAME> <VALUE>: set argument <NAME> to <VALUE> -p <FILE>: write profiling data to <FILE> -w: wait for instrumentation to finish before returning start profiling: am profile <PROCESS> start <FILE> stop profiling: am profile <PROCESS> stop
<INTENT> specifications include these flags: [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>] [-c <CATEGORY> [-c <CATEGORY>] ...] [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...] [--esn <EXTRA_KEY> ...] [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...] [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...] [-n <COMPONENT>] [-f <FLAGS>] [--grant-read-uri-permission] [--grant-write-uri-permission] [--debug-log-resolution] [--activity-brought-to-front] [--activity-clear-top] [--activity-clear-when-task-reset] [--activity-exclude-from-recents] [--activity-launched-from-history] [--activity-multiple-task] [--activity-no-animation] [--activity-no-history] [--activity-no-user-action] [--activity-previous-is-top] [--activity-reorder-to-front] [--activity-reset-task-if-needed] [--activity-single-top] [--receiver-registered-only] [--receiver-replace-pending] [<URI>]
還有個(gè)疑點(diǎn),就是su怎么知道用戶是允許root權(quán)限還是反對呢?原來是上面提到的白名單起來作用,superuser把用戶的選擇放入: /data/data/com.koushikdutta.superuser/databases/superuser.sqlite 數(shù)據(jù)庫中,然后su進(jìn)程再去讀該數(shù)據(jù)庫來判斷是否允許。 static int checkWhitelist() { sqlite3 *db; int rc = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL); if (!rc) { char *errorMessage; char query[1024]; sprintf(query, "select * from whitelist where _id=%d limit 1;", g_puid); struct whitelistCallInfo callInfo; callInfo.count = 0; callInfo.db = db; rc = sqlite3_exec(db, query, whitelistCallback, &callInfo, &errorMessage); if (rc != SQLITE_OK) { sqlite3_close(db); return 0; } sqlite3_close(db); return callInfo.count; } sqlite3_close(db); return 0; }
四、 資源文件的獲取 從上文的源碼地址獲取源代碼,替換系統(tǒng)的system/extras/su/下面的su.c 和Android.mk文件,使用編譯命令./mk td28 u adr system/extras/su/ 編譯成功后會生成out/target/product/hsdroid/system/xbin/su 文件,而Superuser.apk就是普通的apk文件,都在源碼地址里面可以下載,下載后倒入到eclipse即可直接運(yùn)行。
五、 總結(jié) 在閱讀完本文后,可以站在專業(yè)的角度了解root的真正原理,以及有用戶有需求時(shí)我們可以幫助其快速的解決問題。 |
|