android無需root執(zhí)行shell(adb)方案

android內(nèi)執(zhí)行shell的幾種解決方案

熟悉adb shell的小伙伴可能知道,很多android設(shè)備的信息,是可以通過shell獲取到的,例如常見的電池信息、內(nèi)存占用、cpu占用等等,但遇到不能插線、沒有網(wǎng)絡(luò)的情況,這些方式就無法使用了,這里不對具體的shell命令做科普,主要談及如何在android應(yīng)用內(nèi)執(zhí)行shell,使其具備更好的適應(yīng)性。

root權(quán)限下直接執(zhí)行

在android應(yīng)用工程內(nèi),可以通過java的runtime直接執(zhí)行shell指令,尤其是低版本的android,在具備root權(quán)限的情況下,更是可以先進(jìn)行su的切換,從而使得shell指令使用su角色執(zhí)行,具體代碼如下:

Process ps = Runtime.getRuntime().exec("su"); //1、執(zhí)行su切換到root權(quán)限
DataOutputStream dos = new DataOutputStream(ps.getOutputStream());
dos.writeBytes(cmd + "\n"); // 2、向進(jìn)程內(nèi)寫入shell指令,cmd為要執(zhí)行的shell命令字符串
dos.flush();

有些不要su權(quán)限的shell,則可以不進(jìn)行第一步的su切換,直接執(zhí)行shell指令即可。

遺憾的是,這種執(zhí)行shell的方式,在高版本的Android上,無法使用su權(quán)限,高版本的android,可以嘗試將su換成/system/bin/sh:

Process ps = Runtime.getRuntime().exec("/system/bin/sh"); //1、執(zhí)行su切換到root權(quán)限
DataOutputStream dos = new DataOutputStream(ps.getOutputStream());
dos.writeBytes(cmd + "\n"); // 2、向進(jìn)程內(nèi)寫入shell指令,cmd為要執(zhí)行的shell命令字符串
dos.flush();

更加通用的方式,是無需root執(zhí)行shell。

非root提權(quán)執(zhí)行

android的權(quán)限用戶分為xxxxx,而一般獲取信息類的shell指令,至少需要uid2000的權(quán)限;普通的第三方應(yīng)用執(zhí)行的shell,對應(yīng)的權(quán)限是該應(yīng)用進(jìn)程的用戶權(quán)限,也就是普通的用戶權(quán)限,因此,想要執(zhí)行高權(quán)限shell的話,就需要進(jìn)行提權(quán)操作。

提權(quán)執(zhí)行shell的方式有很多種,但總體而言,離不開“中轉(zhuǎn)”這個思想。

首先,我們可以明確的是,非root環(huán)境,普通應(yīng)用內(nèi)執(zhí)行shell,是不可能具備高級用戶權(quán)限的,因此就只有另辟蹊徑,既然應(yīng)用內(nèi)無法提權(quán),那么我們就把執(zhí)行shell這個操作,不交給應(yīng)用來執(zhí)行,通過設(shè)立一個中轉(zhuǎn)站,應(yīng)用只負(fù)責(zé)給這個中轉(zhuǎn)站傳遞要執(zhí)行的shell指令,中轉(zhuǎn)站負(fù)責(zé)執(zhí)行這個shell指令,并把執(zhí)行結(jié)果回傳給應(yīng)用,這樣就實(shí)現(xiàn)了應(yīng)用執(zhí)行shell指令的提權(quán)。

這里收集了一些“中轉(zhuǎn)站”的思路,提供給大家借鑒:

  • AdbLib實(shí)現(xiàn)設(shè)備內(nèi)adb通訊
    這種提權(quán)執(zhí)行的思路主要是,通過在設(shè)備內(nèi)實(shí)現(xiàn)一個adb server,代替pc和adbd通信,再把執(zhí)行后的結(jié)果通過socket通信回傳給應(yīng)用,實(shí)現(xiàn)了提權(quán)執(zhí)行的功能。
    AdbLib是開源的一套ADB的通信服務(wù),通過pc端先執(zhí)行adb 端口轉(zhuǎn)發(fā),把a(bǔ)db通信端口轉(zhuǎn)發(fā)到adblib的通信端口5555上,實(shí)現(xiàn)了設(shè)備內(nèi)的adb server,這種方式也是阿里移動測試工具solopi的提權(quán)方式。

  • app_process提權(quán)執(zhí)行
    app_process是 Android 上的一個原生程序,是 APP 進(jìn)程的主入口點(diǎn),可以讓虛擬機(jī)從 main() 方法開始執(zhí)行一個 Java 程序的東西,最關(guān)鍵是,在adb shell內(nèi)通過app_process執(zhí)行的java程序,其進(jìn)程權(quán)限也是uid2000,因此可以執(zhí)行一些高權(quán)限的shell。
    app_process的執(zhí)行方式示例如下:

    # 使用 dex
    CLASSPATH=/data/local/tmp/test.dex app_process /system/bin moe.haruue.Test
    app_process -Djava.class.path=/data/local/tmp/test.dex /system/bin moe.haruue.Test
    
    # 使用 apk
    CLASSPATH=/data/app/moe.haruue.test-1/base.apk app_process /system/bin moe.haruue.Test
    app_process -Djava.class.path=/data/app/moe.haruue.test-1/base.apk /system/bin moe.haruue.Test
    

    因此,我們可以在apk應(yīng)用內(nèi),實(shí)現(xiàn)一個java類用于執(zhí)行shell,再實(shí)現(xiàn)一個socket服務(wù)和應(yīng)用進(jìn)行通信,交換執(zhí)行指令和執(zhí)行結(jié)果。
    這里有一個開源的項(xiàng)目app_process-shell-use,即是用這種方式完成的提權(quán)執(zhí)行。

  • dalvikvm提權(quán)執(zhí)行
    dalvikvm可以創(chuàng)建一個虛擬機(jī)并執(zhí)行參數(shù)中指定的Java類,在adb shell內(nèi)通過dalvikvm啟動一個java程序的話,其進(jìn)程權(quán)限同樣是uid2000,執(zhí)行方式示例如下:

    dalvikvm -cp /data/app/foo.jar Foo 
    

    因此,和app_process一樣的思路,我們同樣可以通過java程序完成shell的執(zhí)行并通過socket進(jìn)行通信;值得一提的是,這種方式即是訊飛的iTest的提權(quán)執(zhí)行方式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。