TShopping

 找回密碼
 註冊
搜索
查看: 478|回復: 1

[教學] Android 獲取ROOT權限原理解析

[複製鏈接]
發表於 2013-11-24 23:57:51 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk Push to Twitter 

一、 概述

本文介紹了android中獲取root權限的方法以及原理,讓大家對android玩家中常說的“越獄”有一個更深層次的認識。


二、 Root的介紹

1.        Root的目的

可以讓我們擁有掌控手機系統的權限,比如刪除一些system/app下面的無用軟件,更換開關機鈴聲和動畫,攔截狀態欄彈出的廣告等。

2.        Root的原理介紹

谷歌的android系統管理員用戶就叫做root,該帳戶擁有整個系統至高無上的權利,它可以訪問和修改你手機幾乎所有的文件,只有root才具備最高級別的管理權限。我們root手機的過程也就是獲得手機最高使用權限的過程。同時為了防止不良軟件也取得root用戶的權限,當我們在root的過程中,還會給系統裝一個程序,用來作為運行提示,由用戶來決定,是否給予最高權限。這個程序的名字叫做Superuser.apk。當某些程序執行su指令想取得系統最高權限的時候,Superuser就會自動啟動,攔截該動作並作出詢問,當用戶認為該程序可以安全使用的時候,那麼我們就選擇允許,否則,可以禁止該程序繼續取得最高權限。Root的過程其實就是把su文件放到/system/bin/ Superuser.apk放到system/app下面,還需要設置/system/bin/su可以讓任意用戶可運行,有set uid和set gid的權限。即要在android機器上運行命令:adb shell chmod 4755 /system/bin/su。而通常,廠商是不會允許我們隨便這麼去做的,我們就需要利用操作系統的各種漏洞,來完成這個過程。

特別說明:我們燒機中的Eng版本並沒有Root權限

3.        Root的方法

從Root的原理我們了解到,root過程分三步:



    1. a.        adb push su /system/bin

    2. b.        adb push SuperUser.apk /system/app

    3. c.       adb shell chmod 4755 /system/bin/su
    複製代碼


若係統是eng版的,做到以上三步,那麼我們Root就大功告成,但實際是不行的。為什麼呢?原因有三:

1、user版的/system路徑是只讀權限,不能簡單寫入

2、chmod需要Root權才能運行(死循環了)

3、有些系統在啟動時會自動將su的4755權限設成755,甚至直接刪除su

那麼針對這種情況,我們怎麼辦呢?非常簡單:燒一個eng版本的boot.img就行了

可以用展訊的燒錄工具,或者用fastboot模式從sd卡燒一個boot.img文件即可

至此,我們Root就成功了,可以用RE(Root Explorer)在根目錄創建和刪除文件。


三、 深入理解Root機制

其流程是:

  1. 1.       Su 被用戶調用

  2. 2.       Su 創建了一個socket監聽

  3. 3.       Su 向Superuser發送了一個廣播,說是有一個程序要請求root

  4. 4.       Su 等待socket 數據接收。有超時處理。

  5. 5.       Superuser 界面收到廣播後,彈出一個對話框,詢問用戶

  6. 6.       Superuser 向傳來的數據中的socket寫回用戶應答結果。

  7. 7.       Su 根據socket得到的結果處理應該不應該繼續執行

  8. 8.       完成提權管理
複製代碼


superuser.apk這個程序是root成功後,專門用來管理root權限使用的,防止被惡意程序濫用。

源碼地址:http://superuser.googlecode.com/svn/trunk

我們有兩點疑問:

1. superuser是怎麼知道誰想用root權限?

2. superuser是如何把用戶的選擇告訴su程序的?

即superuser和su程序是如何通訊的,他們倆位於不通的時空,一個在java虛擬中,一個在linux的真實進程中。

superuser共有兩個activity: SuperuserActivity和SuperuserRequestActivity ,其中SuperuserActivity主要是用來管理白名單的,就是記住哪個程序已經被允許使用root權限了,省的每次用時都問用戶。

SuperuserRequestActivity 就是用來詢問用戶目前有個程序想使用root權限,是否允許,是否一直允許,即放入白名單。

這個白名單比較關鍵,是一個sqlite數據庫文件,位置:

/data/data/com.koushikdutta.superuser/databases/superuser.sqlite

上文說過,root的本質就是往/system/bin/下放一個su文件,不檢查調用者權限的su文件。普通程序可以調用該su來運行root權限的命令。superuser.apk中就自帶了一個這樣的su程序。一開始superuser會檢測/system/bin/su是否存在:

  1. File su = new File("/system/bin/su");

  2. // 檢測su文件是否存在,如果不存在則直接返回

  3. if (!su.exists())  {

  4. Toast toast = Toast.makeText(this, "Unable to find /system/bin/su.", Toast.LENGTH_LONG);

  5. toast.show();

  6. return;

  7. }

  8. //如果大小一樣,則認為su文件正確,直接返回了事。

  9. if (su.length() == suStream.available())

  10. {

  11.   suStream.close();

  12.   return;   //

  13. }



  14. // 如果檢測到/system/bin/su文件存在,但是不對頭,則把自帶的su先寫到"/data/data/com.koushikdutta.superuser/su"

  15. //再寫到/system/bin/su。

  16. byte[] bytes = new byte[suStream.available()];

  17. DataInputStream dis = new DataInputStream(suStream);

  18. dis.readFully(bytes);

  19. FileOutputStream suOutStream = new FileOutputStream("/data/data/com.koushikdutta.superuser/su");

  20.    suOutStream.write(bytes);

  21.    suOutStream.close();

  22.    

  23.    Process process = Runtime.getRuntime().exec("su");

  24.    DataOutputStream os = new DataOutputStream(process.getOutputStream());

  25.    os.writeBytes("mount -oremount,rw /dev/block/mtdblock3 /system\n");

  26.    os.writeBytes("busybox cp /data/data/com.koushikdutta.superuser/su /system/bin/su\n");

  27.    os.writeBytes("busybox chown 0:0 /system/bin/su\n");

  28.    os.writeBytes("chmod 4755 /system/bin/su\n");

  29.    os.writeBytes("exit\n");

  30.    os.flush();
複製代碼


有進程使用root權限,superuser是怎麼知道的呢,關鍵是句:

  1. sprintf(sysCmd, "am start -a android.intent.action.MAIN

  2.                                     -n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRequestActivity

  3.                                  --ei uid %d --ei pid %d > /dev/null", g_puid, ppid);

  4.   if (system(sysCmd))

  5.    return executionFailure("am.");
複製代碼


   原理是am命令,am的用法:

  1. usage: am [subcommand] [options]
  2.     start an Activity: am start [-D] [-W] <INTENT>
  3.         -D: enable debugging
  4.         -W: wait for launch to complete
  5.     start a Service: am startservice <INTENT>
  6.     send a broadcast Intent: am broadcast <INTENT>
  7.     start an Instrumentation: am instrument [flags] <COMPONENT>
  8.         -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
  9.         -e <NAME> <VALUE>: set argument <NAME> to <VALUE>
  10.         -p <FILE>: write profiling data to <FILE>
  11.         -w: wait for instrumentation to finish before returning
  12.     start profiling: am profile <PROCESS> start <FILE>
  13.     stop profiling: am profile <PROCESS> stop
  14.     <INTENT> specifications include these flags:
  15.         [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
  16.         [-c <CATEGORY> [-c <CATEGORY>] ...]
  17.         [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
  18.         [--esn <EXTRA_KEY> ...]
  19.         [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
  20.         [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
  21.         [-n <COMPONENT>] [-f <FLAGS>]
  22.         [--grant-read-uri-permission] [--grant-write-uri-permission]
  23.         [--debug-log-resolution]
  24.         [--activity-brought-to-front] [--activity-clear-top]
  25.         [--activity-clear-when-task-reset] [--activity-exclude-from-recents]
  26.         [--activity-launched-from-history] [--activity-multiple-task]
  27.         [--activity-no-animation] [--activity-no-history]
  28.         [--activity-no-user-action] [--activity-previous-is-top]
  29.         [--activity-reorder-to-front] [--activity-reset-task-if-needed]
  30.         [--activity-single-top]
  31.         [--receiver-registered-only] [--receiver-replace-pending]
  32.         [<URI>]<span style="font-family: Calibri; font-size: 14px;"> </span>
複製代碼

還有個疑點,就是su怎麼知道用戶是允許root權限還是反對呢?原來是上面提到的白名單起來作用,superuser把用戶的選擇放入:

/data/data/com.koushikdutta.superuser/databases/superuser.sqlite   數據庫中,然後su進程再去讀該數據庫來判斷是否允許。

  1. static int checkWhitelist()
  2. {
  3. sqlite3 *db;
  4. int rc = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL);
  5. if (!rc)
  6. {
  7.   char *errorMessage;
  8.   char query[1024];
  9.   sprintf(query, "select * from whitelist where _id=%d limit 1;", g_puid);
  10.   struct whitelistCallInfo callInfo;
  11.   callInfo.count = 0;
  12.   callInfo.db = db;
  13.   rc = sqlite3_exec(db, query, whitelistCallback, &callInfo, &errorMessage);
  14.   if (rc != SQLITE_OK)
  15.   {
  16.    sqlite3_close(db);
  17.    return 0;
  18.   }
  19.   sqlite3_close(db);
  20.   return callInfo.count;
  21. }
  22. sqlite3_close(db);
  23. return 0;
  24. }
複製代碼



四、 資源文件的獲取

從上文的源碼地址獲取源代碼,替換系統的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即可直接運行。


五、 總結

在閱讀完本文後,可以站在專業的角度了解root的真正原理,以及有用戶有需求時我們可以幫助其快速的解決問題。



 

臉書網友討論

評分

參與人數 1T幣 +5 熱心 +2 收起 理由
呵呵 + 5 + 2

查看全部評分

發表於 2013-11-25 21:16:39 | 顯示全部樓層
我喜歡!感謝大大的分享

版主招募中

您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2016-12-8 00:39 , Processed in 0.058555 second(s), 23 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表