欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 系统 -- android apk 的root 权限和USB adb 权限的区别

程序员文章站 2023-09-29 16:27:54
android apk 的root 权限和usb adb 权限的区别 usb adb 权限是指,当adb 连接手机时,手机中的守护进程adbd 的权限为root 权限,从而它的子进程也具有root...

android apk 的root 权限和usb adb 权限的区别

usb adb 权限是指,当adb 连接手机时,手机中的守护进程adbd 的权限为root 权限,从而它的子进程也具有root 权限,通常如果adb shell 看到是:

android 4.0 以后版本:

c:\>adb shell

root@android:/#

android 2.3 版本:

c:\>adb shell

#

即表明adb 的连接是root 权限的,相反如果看到是$ 即表明是shell 权限android 的apk 本身都是不具备root 权限的,如果想启用root 权限,那么就必须借助具有root 权限的进程或者具有s bit 的文件,目前比较通用的手法是,手机root 后,内置了su到system/bin, 然后普通app 即可借助su 命令来达到root 权限切换。

网络上已经有同仁修改su 命令,并通过一个apk 来控制su 命令的权限控制。

supersu:https://forum.xda-developers.com/showthread.phpt=1538053(更新速度很快,推荐使用)综上所叙,如果adb 已经有root 权限,那么让apk 行使root 权限就很简单了。比如在jb 版本或者以前的版本上:

adb remount

adb push su /system/bin

adb push superuser.apk /system/app

adb shell chmod 0644 /system/app/superuser.apk

adb shell chmod 6755 /system/bin/su

adb reboot

kk 以后的版本:

* adb 的root 权限是在system/core/adb/adb.c 中控制。主要根据ro.secure 以及 ro.debuggable 等system property 来控制。

默认即档ro.secure 为0 时,即开启root 权限,为1时再根据ro.debuggable 等选项来确认是否可以用开启root 权限。为此如果要永久性开启adb 的root 权限,有两种修改的方式:

1. 修改system property ro.secure, 让ro.secure=0。

2. 修改adb.c 中开启root 权限的判断逻辑。

*在l 版本上adb 会受到selinux 的影响, 所以需要调整selinux policy 设置.

下面详细说明这两种修改方式:

第一种方法. 修改system property ro.secure, 让ro.secure=0。

(1)修改alps/build/core/main.mk

ifneq (,$(user_variant))

# target is secure in user builds.

additional_default_properties += ro.secure=1

将additional_default_properties += ro.secure=1 改成 additional_default_properties += ro.secure=0 即可。

(2)在android jb 版本(4.1) 以后,google 从编译上直接去除了adbd 的user 版本root 权限, 为此您要修改system/core/adb/android.mk 中的编译选项allow_adbd_root, 如果没有打开这个选项,那么adb.c 中将不会根据ro.secure 去选择root 还是shell 权限,直接返回shell 权限。因此您必须需要android.mk 中的第126行:

ifneq (,$(filter userdebug eng,$(target_build_variant)))

===> ifneq (,$(filter userdebug user eng,$(target_build_variant)))

(3)在android l (5.0) 以后, google 默认开启selinux enforce mode, 需要在user build 上将su label 默认build 进sepolicy.

放开selinux 的限制. 更新alps/external/sepolicy/android.mk 116 行, 将su label 默认编译进入sepolicy.

sepolicy_policy.conf := $(intermediates)/policy.conf

$(sepolicy_policy.conf): private_mls_sens := $(mls_sens)

$(sepolicy_policy.conf): private_mls_cats := $(mls_cats)

$(sepolicy_policy.conf) : $(call build_policy, $(sepolicy_build_files))

@mkdir -p $(dir $@)

$(hide) m4 -d mls_num_sens=$(private_mls_sens) -d mls_num_cats=$(private_mls_cats) \

-d target_build_variant=$(target_build_variant)\

-d force_permissive_to_unconfined=$(force_permissive_to_unconfined) \

-s $^ > $@

$(hide) sed '/dontaudit/d' $@ >$@.dontaudit

将-d target_build_variant=$(target_build_variant) 改成 -d target_build_variant=eng

如果是n 版本, selinux policy 已经搬移到 alps/system/sepolicy.

即第一种方法在android l(5.0) 以后你需要改(1),(2),(3).

第二种方法. 修改adb.c 中开启root 权限的判断逻辑。这里针对4.1 以后版本 和4.1以前版本有所区别。

(1).如果是jb 4.1 以后版本,直接修改函数should_drop_privileges()函数, 清空这个函数,直接返回 0 即可。返回0 即开启root 权限。

(2).如果是jb 4.1 以前版本,直接修改函数adb_main 函数,在

/* don't listen on a port (default 5037) if running in secure mode */

/* don't run as root if we are running in secure mode */

if (secure) {

struct __user_cap_header_struct header;

struct __user_cap_data_struct cap;

if (prctl(pr_set_keepcaps, 1, 0, 0, 0) != 0) {

exit(1);

}

在这段代码前加一行:

secure = 0; //mtk71029 add for root forever.

/* don't listen on a port (default 5037) if running in secure mode */

/* don't run as root if we are running in secure mode */

if (secure) {

struct __user_cap_header_struct header;

struct __user_cap_data_struct cap;

if (prctl(pr_set_keepcaps, 1, 0, 0, 0) != 0) {

exit(1);

}

(3)在android l (5.0) 以后, google 默认开启selinux enforce mode, 需要在user build 上将su label 默认build 进sepolicy.

放开selinux 的限制. 更新alps/external/sepolicy/android.mk 116 行, 将su label 默认编译进入sepolicy.

sepolicy_policy.conf := $(intermediates)/policy.conf

$(sepolicy_policy.conf): private_mls_sens := $(mls_sens)

$(sepolicy_policy.conf): private_mls_cats := $(mls_cats)

$(sepolicy_policy.conf) : $(call build_policy, $(sepolicy_build_files))

@mkdir -p $(dir $@)

$(hide) m4 -d mls_num_sens=$(private_mls_sens) -d mls_num_cats=$(private_mls_cats) \

-d target_build_variant=$(target_build_variant)\

-d force_permissive_to_unconfined=$(force_permissive_to_unconfined) \

-s $^ > $@

$(hide) sed '/dontaudit/d' $@ >$@.dontaudit

将-d target_build_variant=$(target_build_variant) 改成 -d target_build_variant=eng

如果是n 版本, selinux policy 已经搬移到 alps/system/sepolicy.

即第二种方法在android l(5.0) 以后你需要改(1),(3).

[测试与确认]

当修改完成后,只需要重新build bootimage ,然后download 即可,然后到setting 中开启debug 选项,adb 连接后,会显示 #, 即root 成功。

(1). adbd 的root 权限

我们通常在debug user 版本问题时, 或者进行user 版本的monkey test 时都会这个工作,以便debug. 可以参考faq.如果你想user 版本adb root 权限默认关闭, 而在想开启时, 可以通过工程模式中的设置项开启, 那么请user2root 功能 (l 版本不再支持此功能)。

此功能默认关闭, 如果开启, 需要在projectconfig.mk 中设置: mtk_user_root_switch = yes

同样注意此项功能通常只用于debug 或者 cmcc 送测, 在正式出货版本, 强烈要求关闭, 否则有安全风险.

(2). app 的root 权限

app 的root 权限通常是通过执行su 命令来获取。注意的是kk 上, 因为多种限制, 普通的su 难以直接拿到root 权限, 需要做针对性的改动.

通常我们会内置具有控制端的第三方su, 下面以内置supersu, 以及使用google default su 为例进行说明。(3). 如何内置第三方supersu

该方式可以绕过zygote 和 adbd 对root capabilities boundset 的限制. mtk 目前仅测试kk 以及以前的版本,l 版本后因为supersu 还在持续更新中, 请客户查看它官网的说明.

3.1. 下载supersu

supersu:https://forum.xda-developers.com/showthread.phpt=1538053

3.2. 内置superuser.apk 到 system/app

将su 复制并改名成: daemonsu

内置su 到 system/xbin

内置daemonsu 到 system/xbin

内置chattr 到 system/xbin

内置chattr.pie 到 /system/xbin3.3. 内置install-recovery.sh 到system/etc

并且按照faq: faq09021 如何修改内置文件的权限, 用户,属性https://online.mediatek.com/pages/faq.xlist=sw&faqid=faq09021

更新alps/system/core/inlcude/private/android_filesystem_config.h

在android_files 数组的最开始新增.

{ 00755, aid_root, aid_root, 0, "system/etc/install-recovery.sh" },

(4). 如何内置google default su

4.1 放开google default su 只准shell/root 用户使用的限制.

system/extras/su/su.c 中删除下面3行代码

if (myuid != aid_root && myuid != aid_shell) {

fprintf(stderr,"su: uid %d not allowed to su\n", myuid);

return 1;

}4.2 首先将此编译出的su 内置到system/bin, 然后修改su 的内置权限,启用sbit 位.

按照faq: faq09021 如何修改系统内置文件的权限, 用户,属性https://online.mediatek.com/pages/faq.aspxlist=sw&faqid=faq09021

更新alps/system/core/inlcude/private/android_filesystem_config.h

在android_files 数组中

增加

{ 06755, aid_root, aid_root, 0, "system/bin/su" },

注意这行要放在

{ 00755, aid_root, aid_shell, 0, "system/bin/*" },

之前4.3 如果是kk 版本(非kk2 mt6752/mt6732), 需要强行解除zygote 和 adbd 对root capabilities boundset 的限制

更新kernel/security/commoncap.c 中 cap_prctl_drop 函数为:

static long cap_prctl_drop(struct cred *new, unsigned long cap)

{

//mtk71029 add begin: let 'zygote' and 'adbd' drop root capabilities boundset ineffectively

if (!strncmp(current->comm, "zygote", 16)) {

return -einval;

}

if (!strncmp(current->comm, "adbd", 16)) {

return -einval;

}

// add end if (!capable(cap_setpcap))

return -eperm;

if (!cap_valid(cap))

return -einval; cap_lower(new->cap_bset, cap);

return 0;

}4.4 如果贵司一定要在k2(mt6752/mt6732)上开启, 请提交eservice, 申请定制的dvm, 放开相关的权限限制.4.5 如果贵司在l 版本操作, 请按下面的流程:

4.5.1 更新alps/frameworks/base/core/jni/com_android_internal_os_zygote.cpp

将 dropcapabilitiesboundingset(jnienv* env) 这个函数置空.

4.5.2 更新alps/frameworks/base/cmds/app_process/app_main.cpp 的main 函数,注释掉main函数开始的下面这段代码

if (prctl(pr_set_no_new_privs, 1, 0, 0, 0) < 0) {

// older kernels don't understand pr_set_no_new_privs and return

// einval. don't die on such kernels.

if (errno != einval) {

log_always_fatal("pr_set_no_new_privs failed: %s", strerror(errno));

return 12;

}

}

4.5.3 更新alps/system/core/adb/adb.c 将should_drop_privileges() 函数, 清空这个函数,直接返回 0 即可.

4.5.4 将selinux 调整到permissve mode, 参考faq11484:https://online.mediatek.inc/pages/faq.aspxlist=sw&faqid=faq11484

重新编译系统, 重新download 后, adb shell 进入后再输入su 看看是否命令行由$切换到#, 如果切换即成功。

(5). 在kk 版本后app 使用root 权限受到更加严格的限制。android kk 4.4 版本后,user 版本su 权限严重被限制。