android开发中,手把手教你root Android系统
手把手教你root Android系统
因为从事的是智能家居相关行业,用的系统也是android系统,在某些场景下可能需要拿到系统的root权限。下面就手把手教大家去拿到app的root权限和adb的root权限,比如一般手机在出厂的时候,开关机动画都是固定的,但是如果有一个需求就是需要你动态的去切换开关机的动画的时候,可能就需要你拿到root权限,然后对system/media的开关机动画进行操作等,这些都是需要拿到root权限才能进行的
当然在android系统的root权限中也是有区别的,会在下面指出区别在哪:
您要确认您是想开启adbd 的root 权限,还是让app 也可以拿到root 权限。他们之间是有很大区别的,起功能导向也肯定不一样,举个例子:如果你的系统adb root了,并不代表你的apk可以对系统目录进行操作,同样也是apk如果拿到root权限,也不一定代表可以拿到所有对系统的操作权限;
注意严重声明: 任何在最终user版本上打开root权限的手法都会给用户带来安全风险, 请仔细评估您的需求是否真实需要.
MTK 强烈反对此类做法, 由此带来的安全风险,以及造成的损失, MTK 不承担任何的责任。
注意:MTK是强烈反对对user版本进行root的,因为会带来严重的安全行问题
什么是adb的权限:
USB adb 权限是指,当adb 连接手机时,手机中的守护进程adbd 的权限为root 权限,从而它的子
进程也具有root 权限,通常如果adb shell 看到是:
在上面可以看到:在输入adb shell之后,直接拿到的就是root的权限
什么是apk的root权限
一个apk想要拿到系统的root权限可没那么容易,知道linux的都知道,linux系统下如果想拿到系统的权限就必须要使用sudo命令,同样,在android系统中,如果你想你的apk可以拿到系统的权限,就必须要su,那么这个su就要在编译的时候编译到system/bin文件夹或者system/xbin下面,而且su文件使用权限也必须要对普通的用户进行开放
从上图可以看出,集成了su命令的系统,在进去shell的时候,其adb是没有root权限的,依旧是 ,但是在执行su,命令之后,其后面的 ,但是在执行su,命令之后,其后面的就已经转变成#,说明已经拿到root的权限了,但是本篇博客重点讲的就是如何去进行adb的root和apk的root
如何永久性开启adb的root的权限
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
即第一种方法在android L(5.0) 以后你需要改(1),(2),(3).
注:目前我们项目的系统是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
即第二种方法在android L(5.0) 以后你需要改(1),(3).
当修改完成后,只需要重新build bootimage ,然后download 即可,然后到setting 中开启debug选项,adb 连接后,会显示 #, 即root 成功。
如何去开启apk的root权限(su命令内置和克服SELINUX)
通过内置第三方SuperSU来进行apk的root(PS:作者由于项目时间比较忙,并没有尝试过这样的root方法)
该方式可以绕过zygote 和 adbd 对Root Capabilities BoundSet 的限制. MTK 目前仅测试KK 以及以前的版本, L 版
本后因为SuperSU 还在持续更新中, 请客户查看它官网的说明.
1:下载SuperSU
SuperSU: http://forum.xda-developers.com/showthread.php?t=1538053
2:内置Superuser.apk 到 system/app
将su 复制并改名成: daemonsu
内置su 到 system/xbin
内置daemonsu 到 system/xbin
内置chattr 到 system/xbin
内置chattr.pie 到 /system/xbin
3. 内置install-recovery.sh 到system/etc
更新alps/system/core/inlcude/private/android_filesystem_config.h
在android_files 数组的最开始新增.
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/install-recovery.sh" },
第二种方法就是内置Google default su命令
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;
}
2:首先将此编译出的su 内置到system/bin, 然后修改su 的内置权限,启用sbit 位.
1、修改 alps\system\extras\su\Android.mk
LOCAL_MODULE_TAGS := debug 改为 LOCAL_MODULE_TAGS := optional
注:将su设置在编译的时候不仅仅是在debug状态下才编译的 2、修改 alps\build\target\product\core.mk
增加PRODUCT_PACKAGES += \ su \
注:在编译的时候,编译su项目3、如果是KK(非KK2)版本。需要强行解除 zygote 和adbd 对Root Capabilities BoundSet 的限制。修改 alps\kernel\security\commoncap.c 增加static long cap_prctl_drop(struct cred *new, unsigned long cap) { //add start 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、然后修改su 的内置权限
更新alps/system/core/inlcude/private/android_filesystem_config.h
在android_files 数组中,将原来su的权限修改成:
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/su" },
注:这个时候编译出来的是可以获取root权限的,并且其编译成功后的目录是在system/xbin目录下的
3:如果贵司在L 版本操作, 请按下面的流程:(目前我操作的版本是L版本以后的)
更新alps/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
将 DropCapabilitiesBoundingSet(JNIEnv* env) 这个函数置空.
如:将函数体注释掉
static void DropCapabilitiesBoundingSet(JNIEnv* env) {
/* for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);if (rc == -1) {if (errno == EINVAL) {ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify ""your kernel is compiled with file capabilities support");} else {ALOGE("prctl(PR_CAPBSET_DROP) failed");RuntimeAbort(env);}}}*/
}
4:更新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;}
}
5:如果是L 版本, 需要手动关闭SELinux
更新bootable/bootloader/lk/platform/mt6xxx/rules.mk
# choose one of following value -> 1: disabled/ 2: permissive /3: enforcing
SELINUX_STATUS := 3
调整这个SELINUX_STATUS这个的值为 2
6:修改system/core/init/Android.mk 新增
ifeq ($(strip $(TARGET_BUILD_VARIANT)),user)
LOCAL_CFLAGS += -DALLOW_DISABLE_SELINUX=1
endif
笔者也是在网上参考了很多过来的人经验,再结合自己在实际修改权限的过程中遇到的某些问题做的一些总结,可能有时候我们做手机并不需要去更改的系统想相关的权限,而我们的用户可能对手机root也并不是那么敏感。但是作为一个开发者,并不意味着我们不会遇到某些场景下,需要打开root的这样的需求。当然,如果打开了root之后,最直接的结果可能就是会导致安全性会稍稍降低,但是也可以采用其他的方式来避免
参考的相关博客:
http://blog.csdn.net/muyang_ren/article/details/49507393
http://blog.csdn.net/kangear/article/details/51872653
当然这些内容其实在FAQ中其实都是有讲解和解决的,只是这个文档相对来说是比较大,就没有传上去了,在这里有需要的可以关注下 私信发一下
欢迎访问我的博客
android开发中,手把手教你root Android系统相关推荐
- Android 开发之手把手教你写 ButterKnife 框架(三)
系列文章目录导读: Android开发之手把手教你写ButterKnife框架(一) Android开发之手把手教你写ButterKnife框架(二) Android开发之手把手教你写ButterKn ...
- Android开发中遇到的问题(四)——Android中WARNING: Application does not specify an API level requirement!的解决方法
Android开发中遇到的问题(四)--Android中WARNING: Application does not specify an API level requirement!的解决方法 参考文 ...
- android开发中遇到的技术难题,android开发过程中遇到的问题以及解决办法
####编译的时候遇到的问题: "android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original th ...
- android开发模式,Android开发中无处不在的设计模式
Android开发中无处不在的设计模式――单例模式 Android开发中无处不在的设计模式――Builder模式 前面介绍了单例模式和Builder模式,有兴趣的见上面两个链接,这篇文章侧重介绍1下视 ...
- Android开发中无处不在的设计模式——动态代理模式
继续更新设计模式系列.写这个模式的主要原因是近期看到了动态代理的代码. 先来回想一下前5个模式: - Android开发中无处不在的设计模式--单例模式 - Android开发中无处不在的设计模式-- ...
- Android常用:手把手教你实现搜索框(含历史搜索记录)
http://blog.csdn.net/carson_ho/article/details/53366570 前言 像下图的搜索功能在Android开发中非常常见 今天我将手把手教大家如何实现具备历 ...
- 史上最全Android开发中100%会用到的开源框架整理(1/5)
其实这个开源框架整理很久了,只是一直放在有道云笔记里面,笔者还有很多写得文章都放在有道云笔记里面,有时间都好好整理一下放出来,本篇文章也会不定期更新,由于整理的开源框架分类都有200多个,所有这次只将 ...
- 在 Android 开发中使用 Kotlin 协程 (一) -- 初识 Kotlin 协程
前言 最近在研究 Kotlin 协程,发现功能真的超级强大,很有用,而且很好学,如果你正在或计划使用 Kotlin 开发 Android,那么 Kotlin 协程你一定不能错过! 协程是什么? 我们平 ...
- android addview指定位置,Android开发中,请问当在一个视图中addView另一个布局视图时为什么报错?...
Android开发中,我在一个视图中addView另一个布局视图(该视图通过inflate加载获得,其中root为null即没有附加parent视图),为什么还是会报错误: The specified ...
最新文章
- CSS盒模型及边距问题
- 宇宙中至少有两种方式能灭绝人类,第一种仅需两秒
- [转]23种经典设计模式的java实现_5_职责链模式
- KMP算法的动态规划解说
- python爬虫和数据分析电脑推荐_大数据分析必备的5款Python爬虫库
- Windows 下的 PHP 编译
- UI5 EventBus
- 设置本地Nexus存储库并从Maven部署WAR文件
- mysql的主主复制模型
- Unity3D中脚本的执行顺序和编译顺序
- SVN中,A项目如何共享B项目的内容
- 西电版《离散数学》勘误
- 解决微信小程序银行卡号输入转换格式
- 最小二乘法的线性拟合
- Express4.X版本修改默认模板jade为ejs并且试用html为视图模板后缀名
- 如何把win7电脑设置成网站服务器吗,如何为win7电脑设置服务器
- Ubuntu 怎么在 Libreoffice 中添加字体
- 解决 docker 磁盘空间不足问题
- 你真的适合学习JAVA开发吗?
- 统计学习导论(ISLR)(四):分类算法
热门文章
- ubuntu使用docker搭建licode
- 理解HBase面向列存储
- 好用到爆的python实战技巧
- 调色板,真彩色,DDB,DIB,BMP,RGB,YUV
- 类EMD的“信号分解方法”及MATLAB实现(第四篇)——VMD
- 暴风集团公布前三季度业绩预告,盈利同比增长惊人
- 微信小程序如何制作消息提示框---wx.showToast(Object object)
- php网络验证系统源码,kakaPHP 网络验证PHP服务端源码 - 下载 - 搜珍网
- 解决 invalid multibyte string 1
- uni-app 小项目开发 仿小米商城 后端提供数据3