TShopping

 找回密碼
 註冊
搜索
查看: 410|回復: 0

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

[複製鏈接]
發表於 2013-12-7 00:42:56 | 顯示全部樓層 |閱讀模式
 
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 過程分三步:
a.        adb push su /system/bin
b.        adb push SuperUser.apk /system/app
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就成功了,可以用R.E(Root Explorer)在根目錄創建和刪除文件。

三、 深入理解Root機製成
其流程是:
1.       Su 被用戶調用
2.       Su 創建了一個socket監聽
3.       Su 向Superuser發送了一個廣播,說是有一個程序要請求root
4.       Su 等待socket 數據接收。有超時處理。
5.       Superuser 界面收到廣播後,彈出一個對話框,詢問用戶
6.       Superuser 向傳來的數據中的socket寫回用戶應答結果。
7.       Su 根據socket得到的結果處理應該不應該繼續執行
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>]
複製代碼


還有個疑點,就是su怎麼知道用戶是允許root權限還是反對呢?原來是上面提到的白名單起來作用,superuser把用戶的選擇放入:
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite    數據庫中,然後su進程再去讀該數據庫來判斷是否允許。
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;
}

四、 資源文件的獲取
從上文的源碼地址獲取源代碼,替換系統的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的真正原理,以及有用戶有需求時我們可以幫助其快速的解決問題。


 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



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

GMT+8, 2016-12-11 10:27 , Processed in 0.056531 second(s), 22 queries .

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

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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