300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 如何使Android应用程序获得root权限

如何使Android应用程序获得root权限

时间:2020-05-03 00:17:15

相关推荐

如何使Android应用程序获得root权限

写这篇文章前,首先要感谢Simon_fu,他的两篇关于root权限的文章对于我的工作起到了非常大的帮助,这篇文章可以说是对他的文章的一个补充。Simon_fu的文章可以参考如下两个网页:

Android程序的安全系统

Android应用程序获得root权限

一般来说,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权限的文章网上已有很多,这里就不再细说,可以参考如下两篇文章:

/liujian885/archive//03/22/5404834.aspx

/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应用程序获得root权限

发布于: 一月 18作者:Simon_fu目录:Android,技术评论:52 条评论

我在博文《Android程序的安全系统》中提到两种让root权限的办法。最近在网上发现很多朋友转载那篇文章,但是对那篇文章中提到的第一种方法怎样实现,不是很明白。本文将会以一个例子实现来演示怎样让一个Android应用程序获得root权限。

问题

我遇到的问题是我想在Java应用程序中动态mount一个NFS的系统,但是执行mount命令必须要要root权限才可以。一般情况下,在Android的Java层是不能获得root权限的。

思路

我在博文《Android程序的安全系统》中提到两种思路:

1、实现一个init实现一个Service,来帮助Android应用程序执行root权限的命令。

2、实现一个虚拟设备,这个设备帮助Android应用程序执行root权限的命令。

本文将会选择第一种来解决Android应用程序mount NFS文件系统的问题。

Init.rc Service

在Android系统init.rc中定义很多Service,具体定义格式可以参考《Android Platform Developer’s Guide》中的“Android Init Language”。Init.rc中定义的Service将会被Init进程创建,这样将可以获得root权限。

现在问题是Android应用程序怎样启动让init进程知道我们想运行那个进程呢?答案是设置系统属性“ctl.start”,把“ctl.start”设置为你要运行的Service,假设为“xxx”,Android系统将会帮你运行“ctl.start”系统属性中指定的Service。那么运行结果init进程将会将会写入命名为“init.svc.+Service名称”的属性中,也就是“init.svc.xxx”属性,应用程序可以参考查阅这个值来确定Service执行的情况。想更深入了解Android property系统可以参考博文《(翻译)Android属性系统》。

Android property权限

难道Android属性“ctl.start”是所有进程都可以设置的吗?那世界不就乱套了,谁都可以可以执行init.rc中Service了,查看property_service.c中的源码,设置Android系统属性的函数为handle_property_set_fd:

1: void handle_property_set_fd(int fd)

2: {

3:......

4:switch(msg.cmd) {

5:case PROP_MSG_SETPROP:

6: msg.name[PROP_NAME_MAX-1] = 0;

7: msg.value[PROP_VALUE_MAX-1] = 0;

8:

9: if(memcmp(msg.name,"ctl.",4) == 0) {

10: if (check_control_perms(msg.value, cr.uid, cr.gid)) {

11: handle_control_message((char*) msg.name + 4, (char*) msg.value);

12: } else {

13: ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n",

14:msg.name + 4, msg.value, cr.uid, cr.pid);

15: }

16: }

17: ......

18:}

19: }

从源码中我们发现如果设置“ctl.”开头的Android系统property,将会调用check_control_perms函数来检查调用者的权限,其定义如下:

1: static int check_control_perms(const char *name, int uid, int gid) {

2:int i;

3:if (uid == AID_SYSTEM || uid == AID_ROOT)

4: return 1;

5:

6:/* Search the ACL */

7:for (i = 0; control_perms[i].service; i++) {

8: if (strcmp(control_perms[i].service, name) == 0) {

9: if ((uid && control_perms[i].uid == uid) ||

10: (gid && control_perms[i].gid == gid)) {

11: return 1;

12: }

13: }

14:}

15:return 0;

16: }

我们发现root权限和system权限的应用程序将会授权修改“ctl.”开头的Android系统属性。否则将会检查control_perms全局变量中的定义权限和Service。

如果想更深入的了解Android Init进程和Android Property的权限控制,请参考《Android Permission》。

实例

通过上面的介绍我们基本已经有思路了,下面以上面提出的mount nfs文件系统为例说明:

1、首先定义一个执行mount的脚本,我把它位于/system/etc/mount_nfs.sh,定义如下:

1: #!/system/bin/sh

2:

3: /system/bin/busybox mount -o rw,nolock -t nfs 192.168.1.6:/nfs_srv /data/mnt

不要忘了把它加上可执行权限。

2、在init.rc中加入一个Service定义,定义如下:

1: service mount_nfs /system/etc/mount_nfs.sh

2:oneshot

3:disabled

3、让自己的应用程序获得system权限,博文《Android程序的安全系统》中提到了怎样获得system权限,获得system用户权限,需要以下步骤:

(1). 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。

(2). 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行

(3). 使用mm命令来编译,生成的apk就有修改系统时间的权限了。

4、在自己应用程序中设置System系统属性“ctl.start”为“mount_nfs”,这样Android系统将会帮我们运行mount_nfs系统属性了。这里需要强调的是不能够调用System.getProperty,这个函数只是修改JVM中的系统属性。而不能修改Android的系统属性。可以调用android.os.SystemProperties(Android 2.1 Eclair系统可以调用这个API),如果你的Android版本不能调用这个类,只能通过JNI,调用C/C++层的API property_get和property_set函数了。如果想详细了解请参考《(翻译)Android属性系统》。代码如下:

1: SystemProperties.set("ctl.start", "mount_nfs");

5、最后在自己应用程序中,读取“init.svc.mount_nfs”Android系统Property,检查执行结果。代码如下:

1: while(true)

2: {

3:mount_rt = SystemProperties.get("init.svc.mount_nfs", "");

4:if(mount_rt != null && mount_rt.equals("stopped"))

5:{

6: return true;

7:}

8:

9:try

10:{

11: Thread.sleep(1000);

12:}catch(Exception ex){

13: Log.e(TAG, "Exception: " + ex.getMessage());

14:}

15: }

init进程维护一个service的队列,所以我们需要轮训来查询service的执行结果。

通过上面的这些步骤,Android应用程序就能够调用init.rc中定义的Service了。这样你的Android应用程序也就获得了root权限。

总结

通过上文可以看出,在Android获得root权限还是需要一些前提的,比如:

1、必须是Android系统开发人员,否则你无法修改init.rc等文件。 2、你的应用程序必须要获得system权限。

这样可以防止root权限被应用程序无限制的使用,最终危及Android系统安全。

希望本文对你能有所帮助,如果有错误之处敬请指正。

标签:android,framework

你可以通过RSS 2.0 来跟踪本文的所有评论。 你可以对本文发表评论,或者对本文进行评分,或者从你的网站引用 本文。

相关文章

(转)Android核心分析Android系统的Binder机制之四——系统Service(翻译)Android属性系统Android系统的Binder机制之三——服务代理对象(2)Android系统的Binder机制之二——服务代理对象(1)Android系统的Binder机制之一——Service ManagerAndroid系统集成第三方pre-build库和程序Android系统Wifi移植(转)高焕堂关于Android数字电视的文章合集——家庭云(转)高焕堂——Android框架底层结构知多少?Android JNI编程提高篇之二Android JNI编程提高篇之一Android JNI开发入门之二Android JNI开发入门之一Android系统语言出厂设置为简体中文

COMMENTS

52 条评论

bevis

-01-20 14:51:20

谢谢simon,每次定期的来你这里看看,总会学到很多知识。前几天就刚好遇到你说的这个问题,今天来这里看了一下,问题看来可以解决了,呵呵,谢谢!

[回复]

Simon_fu回复:

一月 20th, at 15:52

欢迎你多来关注Simon,也欢迎你对Simon的文章多提宝贵意见!大家共同进步!

[回复]

flye03

-01-21 16:12:07

后来我更改service 为

service mtest /system/bin/logwrapper /system/etc/a.sh

后程序就能正确运行了,不知道是什么原因。总体上是通过了,感谢simon的分享。

[回复]

tang

-02-24 13:44:13

Simon,你真棒

[回复]

Simon_fu回复:

二月 24th, at 16:30

欢迎大家多指正!

共同进步~!

[回复]

gqdy365

-02-24 18:11:04

我有个问题想请教一下楼主,我在做fm模块时遇到了一个权限问题,驱动层生成的文件节点在dev目录下面,上层打开它时说没有权限,我通过串口修改权限后是可以打开的,我网上查了一下,有人说是在init.rc里面做初始化修改,可以指点一下吗?

[回复]

Simon_fu回复:

二月 24th, at 21:04

确实可以在init.rc中做,init.rc提供了chown和chmod命令,你可以参考system/core/init/readme.txt文件,里面对init.rc的命令进行了详细的描述,网上也有人已经翻译成了中文。

[回复]

gqdy365回复:

二月 25th, at 08:58

谢谢你,支持你的博客!

[回复]

billyc

-03-10 03:06:19

Thank you for this great article. The only one article talk about get app root access in an unrooted Android device.

Great Job! and thank you again.

[回复]

匿名

-03-14 11:08:10

总结

通过上文可以看出,在Android获得root权限还是需要一些前提的,比如:

1、必须是Android系统开发人员,否则你无法修改init.rc等文件。 2、你的应用程序必须要获得system权限。

这样可以防止root权限被应用程序无限制的使用,最终危及Android系统安全。

不等于没说么,如何是Android系统开发人员的话,难道他就没有root权限么? 没有Root权限,他还叫系统开发人员么?

最核心的问题是,大家都想知道,一般的应用程序如何能够请求到root权限,我目前system权限已经有了,就是没有root权限,因为我不是系统开发人员。

[回复]

Simon_fu回复:

三月 14th, at 20:22

你不能修改init.rc呢?

如果能修改就可以了~!

Android系统设计目标就是不把root暴露给应用程序的,需要root权限的操作都已经封装成Service了,当然我的实现也是这样的。

如果你已经获得了system权限,那么你可以调用系统中定义的各种service,由各种service来执行需要root权限的操作。如果你要的操作没有对应的service,那么这就是你的系统提供商不想暴露给你。你唯一能做的就是破解它,来获得root权限了。

Android系统开发人员有root权限,但是他们要把需要root权限的操作暴露给上层的应用程序也是需要考虑的一个方面。也是Android系统安全的一个考虑的方面。

[回复]

匿名

-03-20 12:36:49

simon您好!

您提到“实现一个虚拟设备,这个设备帮助Android应用程序执行root权限的命令”

我现在已经写了一个相应驱动,但不知道android app如何跟底层的linux驱动通信,一直找不到头绪,能指导下我吗?

万分感谢

[回复]

Simon_fu回复:

三月 20th, at 14:25

实现一个字符设备驱动,然后app打开这个设备驱动文件,然后向里面写入需要执行的命令,由驱动程序代理执行相应的命令。

[回复]

匿名回复:

三月 21st, at 13:18

谢谢您!

祝博主天天开心!

[回复]

匿名

-04-07 17:09:36

simon您好!

看了您的博客,收益很大,想问问您两个问题

1,您说的使用虚拟字符驱动的方法,在方法里怎样调用eth0让它开启,设置ip等呀,可以提供些函数嘛?

2,使用服务的方法,怎样把参数传进去呀?运用一个脚本是ok的。

希望指导下,万分感谢

[回复]

Simon_fu回复:

四月 7th, at 17:54

首先,实现字符设备的方法,我是这样做的,就和打开普通文件一样打开虚拟字符设备,然后把需要执行的命令一次性写入该设备文件,设备驱动就开始代理执行这些命令;你可以向做驱动的同事请教这个问题。

其次:服务的方法,脚本应该也是可以处理参数的,当然你也可以通过C/C++编写一个程序来完成服务也是一样的。你可以查阅一下脚本的实现,另外init服务也是可以加参数的,请参考Android init readme.

[回复]

匿名回复:

四月 8th, at 08:34

很谢谢您的及时回复

驱动也是我自己写的,现在问题就在于设备怎样去执行那些命令,驱动中没有system函数的调用,ifc_up也用不了,如何把ifconfig这个文件加入的话好像就麻烦了点,您说的“设备驱动就开始代理执行这些命令”是怎样代理的,能指点下嘛,非常感谢

[回复]

Simon_fu回复:

四月 8th, at 09:20

请参考一下这个帖子:

/linux/clf/linuxK/archive/00/00/57/83/578302.html

另外,虚拟设备方案不是Android平台下面常规方案,主要涉及到安全性;只有万不得已的时候再用。优先选用init服务的方案会比较好。

[回复]

匿名回复:

四月 8th, at 11:12

谢谢您如此热心。

现在就是在考虑init服务写的那个socket如何能从用户手中获得参数,而不是在init中配置参数。

非常感谢您的回答,祝您工作顺利,身体健康

[回复]

byfrancis

-04-13 10:23:08

Simon您好,看了你的博文感觉受益匪浅,按照我的理解,文中的方法好像没有不能让用户“一键获取root的权限”,或者是让应用程序自动获取root权限。我知道网上有个应用程序Z4root,可以让用户一键获取root权限,但我不知道是怎么实现的。如果是我对您的方法没有理解,或者是您有一键获取root权限的方法,能指点一下吗?不胜感激!

[回复]

Simon_fu回复:

四月 13th, at 10:34

这个就是传说中root破解,我没有研究过这种破解方式,没有发言权。不好意思!

[回复]

byfrancis回复:

四月 13th, at 22:29

非常感谢,期待您后续的android博文

[回复]

chaos

-04-15 08:03:01

simon牛,问你一个比较傻的问题啊

像RE之类的文件甚至能有重新把根目录挂载为RW的权限

这种权限也是通过这种方法实现的吗

还是说已经root的手机应用程序即可以通过

process = Runtime.getRuntime().exec(“su”);

这种语句来获取root权限??

[回复]

Simon_fu回复:

四月 15th, at 08:54

我在网上看到很多人都是这样获得root权限的,但是这必须要是rooted过的手机,否则没戏!所以这种方法不通用。rooted手机本身也是利用了系统漏洞,如果那一天把漏洞堵上,也就没戏了!

[回复]

chaos回复:

四月 20th, at 10:56

谢谢simon牛

我看了下android 那些terminal模拟器的代码,自己编译了,发现他们在没有root权限的机器上是没有办法执行su的,也看了下superuser的代码,它的思路是修改机器上的su程序,替换成自己编译的su程序,大致明白了通过process = Runtime.getRuntime().exec(“su”);怎么获取root权限的。

ps:

有一个小问题,我看了你上文提到的请参考《Android Permission》。里面我尝试着对init.rc文件进行修改,但是每次修改后重启机器init.rc文件都恢复成为修改前的状态了,请问你有修改过该文件吗?

[回复]

Simon_fu回复:

四月 20th, at 14:10

因为你的根分区是是只读的,试试adb remount行不行?

[回复]

chaos回复:

四月 20th, at 18:37

对 我是root权限 mount -o rw,remount -t rootfs /

[回复]

匿名回复:

四月 22nd, at 00:59

init.rc 不是在ramdisk裡面嗎?ramdisk運行在內存裡面,

每次重開機當然會恢復之前的狀態。

[回复]

chaos回复:

四月 24th, at 01:31

谢谢了 那init.rc未启动时具体在rom的什么文件里面呢?

是不是在启动之后再映射到内存内吗

如果要修改是不是得修改rom然后重新刷机才可以成功??

[回复]

Simon_fu回复:

四月 24th, at 21:14

呵呵!我只是研究了这个技术,刷机这种事儿我可没干过!

这个帮不了你啊!

你可以到刷机网站上面请教这个问题。

[回复]

chaos回复:

四月 24th, at 19:16

那在为映射到内存之前init.rc对应哪个文件呢?

是否修改init.rc必须先修改rom

然后重新刷机才能生效??

[回复]

pcsuite

-04-16 12:15:53

楼主,你好,我看了你很多篇文章,写的都很好,而且对我的帮助也很大,在此表示感谢。

[回复]

dxz

-04-22 18:18:20

你好,我要是想用我的应用在system目录下创建一个文件,用你说的那方法好像不可行吧。能不能给个思路。谢谢

[回复]

Simon_fu回复:

四月 22nd, at 22:46

你遇到什么问题了吗?

我觉得是可以做到的!因为已经有root权限了,在系统中创建文件没有理由不成功的。

system分区是只读的,你可能需要remount一下吧。

[回复]

dxz回复:

四月 23rd, at 08:46

您好,我是初学者,您说的那个服务该怎么写呢 ?我还是没明白那服务是怎么回事?为什么掉声明一个服务就可以应用就可以获取root权限呢 ?还是应用只能调用声明的那个服务里的方法?

[回复]

chaos

-04-24 01:34:49

simon牛

最近我打算详细阅读以下android框架的源代码

ActivityManagerService.java

对ActivityManagerService的大致流程有所了解了

但是对于细节很难看懂

能不能介绍一下你阅读android源码的技巧吗

或者在国外有没有对android相关源码剖析的文章或blog吗?

尤其是对ActivityManagerService.java部分的??

非常感谢

[回复]

Simon_fu回复:

四月 24th, at 21:16

说实话,上万行的代码我也不看!

只是说自己需要的时候,顺藤摸瓜摸到这里而已!

另外既然是service,熟悉了Android service对你理解它也很有帮助。

[回复]

chaos

-04-24 19:20:04

simon牛,请教一个问题

请问一下能不能指点一下阅读android框架源代码的技巧啊

比如我最近在阅读ActivityManagerService.java 光这一个模块就一万多行的代码

大体知道是一个什么它流程 但细节深究实在是很乱啊 看不出头绪

或者外国有没有相关剖析android源代码的blog或文章吗??

[回复]

aplikacje na telefon

-04-30 08:58:52

The most comprehensive and very well thought out write up I have found on this subject on the net. Keep on writing, I will keep on coming by to read your new content. This is my fourth time coming by your blog.

[回复]

soros

-05-25 10:04:59

谢谢楼主共享,不知道楼主是否研究过Runtime.exec() 方法执行shell 指令呢? 这样是不是也能够获取到root 执行权限呢? 我正在使用这种方法,但是却不能够正常执行shell 脚本。

[回复]

Simon_fu回复:

五月 28th, at 18:11

可以肯定的告诉你,绝对不可能拥有root权限。因为只有在java层才能调用Runtime.exec(),这样的进程不可能是root权限的进程,最高是system权限。

[回复]

abc

-05-28 13:57:52

理解错,谢谢,问题已经解决了

[回复]

abc

-06-03 09:55:44

解决了,是线程并发问题。

[回复]

匿名

-07-10 16:35:53

simon_fu;你好,我想请问一下,我要通过jni方式去操作/dev目录下的设备文件,我看您的博文说只要获得system权限就可以操作设备了,但是我获得了system权限还是不能访问设备文件,请问访问设备文件ap必须要具备root权限吗?

[回复]

Simon_fu回复:

九月 14th, at 14:07

这个就要看你的设备驱动要求的权限了!

有的设备驱动必须要root才可以!

需要驱动哦你工程师商议!

[回复]

lufengdie

-08-01 15:01:21

“首先定义一个执行mount的脚本,我把它位于/system/etc/mount_nfs.sh”

这一步不能操作啊。

请教楼主、

[回复]

Simon_fu回复:

九月 14th, at 13:58

说明你没有设备的root权限,或者你没有remount system分区。

[回复]

匿名

-08-19 22:34:30

你好simon,我最近遇到一个问题,我的apk要执行一些需要root权限的命令.看了你介绍的这种方法(第一种),可是这种方法怎么取得命令执行的输出呢?

[回复]

Simon_fu回复:

九月 14th, at 13:55

把命令行重定向到文件,然后执行结束之后,读取文件内容。

[回复]

vincent.yan

-08-23 19:40:10

simon牛,看了你的几篇文章,收益匪浅

但是我现在遇到类似问题,希望能给予指导。

首先我要实现的是一个android应用,但是我想要获取到root权限。(不是Android系统开发人员),这个情况该怎么做?是否用第二种方法可以实现

或者你有什么好方法让应用在非root权限下,去抓屏呢?

[回复]

Simon_fu回复:

九月 14th, at 13:54

抓屏?

我觉得应该是要用到framebuffer吧!

没有root权限我觉得难!

不好意思!

[回复]

Simon_fu

-09-14 13:59:41

研究一下init的帮助文档,里面解释了init service参数传递问题。

[回复]

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。