Android應用程式獲得root許可權
寫這篇文章前,首先要感謝 Simon_fu ,他的兩篇關於 root 許可權的文章對於我的工作起到了非常大的幫助,這篇文章可以說是對他的文章的一個補充。 Simon_fu 的文章可以參考如下兩個網頁:
一般來說, Android 下的應用程式可以“直接”得到的最大的許可權為 system ,但是如果我們需要在程式中執行某些需要 root 許可權的命令,如 ifconfig 等,就需要 root 許可權了。按照 Simon 的文章中提到的,應用程式有以下兩種辦法臨時獲得 root 許可權:
1) 實現一個init 實現一個 Service ,來幫助 Android 應用程式執行 root 許可權的命令。
2) 實現一個虛擬裝置,這個裝置幫助Android 應用程式執行root 許可權的命令。
第二種辦法我這裡沒有嘗試,暫時也不會。這裡講講我在實現第一種辦法的過程和遇到的一些問題。
1. 將我們要執行的命令寫成指令碼,或者可執行程式。
下面是我的指令碼 ifconfig_test.sh :
# ! /system/bin/sh
ifconfig
注意: 指令碼的第一行必須為 # ! /system/bin/sh ,否則無法執行,通過 dmesg 可以檢視到資訊內容為 cannot execve ./ifconfig_test.sh: Exec format error
也可以採用 C/C++ 編寫需要執行的命令或者程式,並在編譯 image 的時候編譯成可執行程式。
2. 在 init.rc 中註冊 service
Android 中的 service 需要在 init.rc 中註冊, Init.rc 中定義的 Service 將會被 init 程式建立,這樣將可以獲得 root 許可權。當得到相應的通知(通過屬性設定)後, init 程式會啟動該 service 。
本文中註冊的內容如下:
service ifconfig_test /system/etc/ifconfig_test.sh
oneshot
disabled
其中, oneshot 表示程式退出後不再重新啟動, disabled 表示不在系統啟動時啟動。
注意: 這裡 service name 不能超過 16 個字元。我之前的 service name 由於定義的比較長, 18 個字元,設定屬性通知 service 啟動後檢視 dmesg 可以看到提示: init: no such service 。檢視 /system/core/init/parser.c 的原始碼,在 parse_service->valid_name 函式中可以看到如下內容: if (strlen(name) > 16) { return 0; } ,證明 service 的名字的確不能超過 16 個字元。
3. 將 Android 應用程式提升為 system 許可權
既然應用程式可以通過啟動 service 獲得 root 許可權,那麼豈不是很不安全。 Android 考慮到了這點,規定只有 system 許可權的應用程式才能設定屬性,通知 service 啟動。關於提升 system 許可權的文章網上已有很多,這裡就不再細說,可以參考如下兩篇文章:
http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx
http://labs.chinamobile.com/mblog/532767_73183
4. 在應用程式中新增屬性設定程式碼
前面已經提到,對於 Android 來說,應用程式通知 init 啟動 service 是通過設定系統屬性來完成的,具體為設定 System 系統屬性 “ctl.start” 為 “ifconfig_test” ,這樣 Android 系統將會幫我們執行 ifconfig_test 這個 service 了。
對該系統屬性的設定有三種方法,分別對應三種不同的應用程式:
1) Java 程式碼
Android 在 Java 庫中提供 System.getProperty 和 System.setProperty 方法, Java 程式可以通過他們來設定和獲得屬性。程式碼如下:
SystemProperties.set("ctl.start", "ifconfig_test");
上面的程式碼是通知 Android 執行 ifconfig_test service ,如果需要查詢當前 service 執行的狀態,如是否執行完畢,可以通過如下程式碼查詢:
ret = SystemProperties.get("init.svc. ifconfig_test ", "");
if(ret != null && ret.equals("stopped"))
{
return true;
}
2) JNI 程式碼
當編寫 NDK 的程式時,可以使用 property_get 和 property_set 這兩個 API 來獲得和設定屬性。使用這兩個 API 必須要包含標頭檔案cutils/properties.h 和連結 libcutil 庫。
3) Shell 指令碼
Android 提供了命令列 setprop 和 getprop 來設定和獲取屬性,他們可以在指令碼中被使用。
由於我的程式是在 JNI 中呼叫指令碼,指令碼中又執行 ifconfig ,因此我將設定屬性的部分放在了指令碼中完成,程式碼如下:
setprop ctl.start ifconfig_test
#wait for the service until it stops
ret=1
while [ $ret -ne 0 ]
do
getprop | grep "$ENABLE_MAPPER_SRV" | grep stopped
ret=$?
done
通過上面 4 個步驟, Android 應用程式就獲得了 root 許可權,更具體的說,是在執行我們需要執行的命令時臨時獲得了 root 許可權。
近段時間關注Android系統的reboot部分,在應用程式呼叫reboot函式可以實現重啟。順著流程看看reboot如何運作。
在Watchdog.java檔案裡,有一例:
void rebootSystem(String reason) {
Slog.i(TAG, "Rebooting system because: " + reason);
//註冊PowerManager服務
PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
//呼叫reboot()方法
pms.reboot(reason);
}
下面順著往下走,
Step1:
在PowerManagerService.java檔案
public void reboot(String reason)
{
// REBOOT許可權
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
…
final String finalReason = reason;
Runnable runnable = new Runnable() {
public void run() {
synchronized (this) {
//這裡執行reboot
ShutdownThread.reboot(mContext, finalReason, false);
}
}
};
…..
}
Step2:
在ShutdownThread.java檔案:
public final class ShutdownThread extends Thread {
…
//這裡是reboot函式
public static void reboot(final Context context, String reason, boolean confirm) {
mReboot = true;// mReboot為true
….
}
public void run() {
…
rebootOrShutdown(mReboot, mRebootReason);//其實這裡執行是reboot
}
public static void rebootOrShutdown(boolean reboot, String reason) {
// reboot為真,執行Power.reboot()方法
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
try {
Power.reboot(reason);
} catch (Exception e) {
Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
}
} else if (SHUTDOWN_VIBRATE_MS > 0) {
…
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
Power.shutdown();//執行Power類的shutdown方法
}
}
Step3:
在Power.java檔案:
public class Power{
…
public static void reboot(String reason) throws IOException
{
rebootNative(reason);//呼叫JNI的reboo方法
}
//宣告rebootNative
private static native void rebootNative(String reason) throws IOException ;
…
}
Step4:
在android_os_Power.cpp檔案:
// #define HAVE_ANDROID_OS 1
static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
sync();
#ifdef HAVE_ANDROID_OS
// 字元reason為空的話,執行自動重起
if (reason == NULL) {
reboot(RB_AUTOBOOT);
} else {
//有原因的重啟
const char *chars = env->GetStringUTFChars(reason, NULL);
//呼叫__reboot()
__reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_RESTART2, (char*) chars);
env->ReleaseStringUTFChars(reason, chars); // In case it fails.
}
jniThrowIOException(env, errno);
#endif
}
Step5:
關於reboot()方法的來頭,在bionic\libc\unistd\reboot.c檔案裡:
int reboot (int mode)
{
//傳NULL到__reboot函式
return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );
}
總的來說,歸結一點是__reboot()函式。
Step6:
看看__reboot()的來由,在bionic\libc\arch-arm\syscalls\__reboot.S檔案裡:
// # define __NR_SYSCALL_BASE 0x900000
//#define __NR_reboot (__NR_SYSCALL_BASE + 88)
.text
.type __reboot, #function
.globl __reboot
.align 4
.fnstart
__reboot:
.save {r4, r7}
stmfd sp!, {r4, r7}
ldr r7, =__NR_reboot
swi #0
ldmfd sp!, {r4, r7}
movs r0, r0
bxpl lr
b __set_syscall_errno
.fnend
這是__reboot函式用匯編實現,用C語言來呼叫。關機部分可以這樣來分析
相關文章
- Mac 在命令列中獲得Root許可權Mac命令列
- Android手機獲取Root許可權Android
- .NET 程式許可權控制、獲得管理員許可權程式碼
- Android系統許可權和root許可權Android
- Linux因15年前的核心漏洞被獲得 Root 許可權Linux
- 【Android】Phoenix OS(鳳凰系統)啟用root許可權Android
- Android破取某漫畫app獲得VIP許可權AndroidAPP
- Chrome OS:Linux應用程式將獲得訪問ndroid資料夾的許可權ChromeLinux
- Mac osx下獲取root使用者許可權Mac
- 值得注意的 Android 應用程式許可權–資訊圖Android
- MAC 開啟root許可權Mac
- win10獲得電腦管理員許可權怎麼操作 win10怎樣獲得管理員許可權Win10
- Atitit godaddy 檔案許可權 root許可權設定Go
- 取消 root 級管理員的 root 許可權
- 許可權系統:許可權應用服務設計
- win10如何獲得trustedinstaller許可權_win10獲取trustedinstaller許可權方法Win10Rust
- android - 解決“應用自定義許可權重名”Android
- 自定義Android應用的訪問許可權Android訪問許可權
- 短視訊系統原始碼,讓程式獲得通知欄許可權原始碼
- win10怎麼獲得管理員許可權_win10獲取管理員許可權的步驟Win10
- 許可權系統:許可權應用服務設計Tu
- w10如何獲得管理員許可權_win10怎麼取得管理員許可權Win10
- 類的許可權與應用
- android之使用signapk打包成系統應用,獲取系統許可權AndroidAPK
- Mac OS X 下獲取root使用者許可權圖解Mac圖解
- Microsoft Graph for Office 365 - Azure AD應用程式許可權ROS
- win10取得管理員許可權怎麼獲取 win10計算機管理員許可權獲得方法Win10計算機
- vim儲存只讀檔案時獲得sudo許可權
- 通過可寫檔案獲取 Linux root 許可權的 5 種方法Linux
- iOS 10設定應用許可權iOS
- 【Android】22.0 許可權處理(四)——應用程式版本控制:Git的使用AndroidGit
- android許可權大全Android
- Android permission許可權Android
- Python經典棧緩衝區溢位獲取root許可權Python
- NetGear路由器可以通過命令注入獲取ROOT許可權路由器
- Mac 開啟和關閉root許可權Mac
- android動態許可權到自定義許可權框架Android框架
- win10管理員許可權如何獲取 win10怎樣讓當前使用者獲得管理員許可權Win10