技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 1781|回复: 0
收起左侧

root android模拟器的最通用方式

[复制链接]

272

主题

446

帖子

4795

积分

用户组: 真·技术宅

UID
2
精华
61
威望
148 点
宅币
3617 个
贡献
131 次
宅之契约
0 份
在线时间
617 小时
注册时间
2014-1-25
发表于 2016-5-19 14:46:44 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
这里介绍的是绝对可行的root方式,对于android模拟器,无论x86 x64 ,无论4.0 5.0 6.0都适用
真机的话5.0和6.0,root成功率比较低,因此不适合在上面做root方面的测试,这时只能考虑虚拟机,因为虚拟机adb有root权限,利用adb root权限便可以提升su权限
网上盛传的方法是http://androidsu.com/superuser https://www.0xaa55.com/forum.php ... tid=1648&extra=
需要superuser.apk,我分析了该网站的su,发现除了传统su的流程(setuid setgid)外,还加入了和superuser.apk通信的这一步
superuser.apk用于单个app权限设置。
遗憾的是该作者并没完成mips架构,和5.0以上的su适配

默认的su,是只允许root权限和shell权限来执行的,因此一般的app并不能使用,因此这也是我们修改的重点,同时还要给su加上必要的环境变量
我这种方式,去除了权限判断部分,因此减少了某些情况下由于这部分带来的root权限未成功获取的bug

这里提供一种方式,可以支持全平台
先构造文件夹:
/jni
/jni/su.cpp
/jni/Android.mk
/jni/Application.mk


  1. //su.cpp
  2. /*
  3. * Copyright (C) 2008 The Android Open Source Project
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. *     http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */

  17. #include <errno.h>
  18. #include <getopt.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <pwd.h>

  24. #define AID_ROOT             0  /* traditional unix root user */
  25. #define AID_SYSTEM        1000  /* system server */
  26. #define AID_SHELL         2000  /* adb and debug shell user */
  27. #define AID_NOBODY        9999
  28. #define AID_APP          10000  /* first app user */
  29. #define AID_USER        100000  /* offset for uid ranges for each user */


  30. void pwtoid(const char* tok, uid_t* uid, gid_t* gid) {
  31.     struct passwd* pw = getpwnam(tok);
  32.     if (pw)
  33.     {
  34.         if (uid) *uid = pw->pw_uid;
  35.         if (gid) *gid = pw->pw_gid;
  36.     }
  37.     else
  38.     {
  39.         char* end;
  40.         errno = 0;
  41.         uid_t tmpid = strtoul(tok, &end, 10);
  42.         if (errno != 0 || end == tok)
  43.                 printf("invalid uid/gid '%s'", tok);
  44.         if (uid) *uid = tmpid;
  45.         if (gid) *gid = tmpid;
  46.     }
  47. }

  48. void extract_uidgids(const char* uidgids, uid_t* uid, gid_t* gid, gid_t* gids, int* gids_count) {
  49.     char *clobberablegids;
  50.     char *nexttok;
  51.     char *tok;
  52.     int gids_found;

  53.     if (!uidgids || !*uidgids)
  54.     {
  55.         *gid = *uid = 0;
  56.         *gids_count = 0;
  57.         return;
  58.     }

  59.     clobberablegids = strdup(uidgids);
  60.     strcpy(clobberablegids, uidgids);
  61.     nexttok = clobberablegids;
  62.     tok = strsep(&nexttok, ",");
  63.     pwtoid(tok, uid, gid);
  64.     tok = strsep(&nexttok, ",");
  65.     if (!tok)
  66.     {
  67.         /* gid is already set above */
  68.         *gids_count = 0;
  69.         free(clobberablegids);
  70.         return;
  71.     }
  72.     pwtoid(tok, NULL, gid);
  73.     gids_found = 0;
  74.     while ((gids_found < *gids_count) && (tok = strsep(&nexttok, ",")))
  75.     {
  76.         pwtoid(tok, NULL, gids);
  77.         gids_found++;
  78.         gids++;
  79.     }
  80.     if (nexttok && gids_found == *gids_count)
  81.     {
  82.         fprintf(stderr, "too many group ids\n");
  83.     }
  84.     *gids_count = gids_found;
  85.     free(clobberablegids);
  86. }

  87. int main(int argc, char** argv)
  88. {
  89.     uid_t current_uid = getuid();

  90.     // Handle -h and --help.
  91.     ++argv;
  92.     if (*argv && (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0))
  93.     {
  94.         fprintf(stderr,
  95.                 "usage: su [UID[,GID[,GID2]...]] [COMMAND [ARG...]]\n"
  96.                 "\n"
  97.                 "Switch to WHO (default 'root') and run the given command (default sh).\n"
  98.                 "\n"
  99.                 "where WHO is a comma-separated list of user, group,\n"
  100.                 "and supplementary groups in that order.\n"
  101.                 "\n");
  102.         return 0;
  103.     }

  104.     uid_t uid = 0;
  105.     gid_t gid = 0;

  106.     if (*argv)
  107.     {
  108.         gid_t gids[10];
  109.         int gids_count = sizeof(gids)/sizeof(gids[0]);
  110.         extract_uidgids(*argv, &uid, &gid, gids, &gids_count);
  111.         if (gids_count) {
  112.             if (setgroups(gids_count, gids))
  113.             {
  114.                 printf("setgroups failed");
  115.             }
  116.         }
  117.         ++argv;
  118.     }

  119.     if (setgid(gid))
  120.             printf("setgid failed");
  121.     if (setuid(uid))
  122.             printf("setuid failed");

  123.     //设置环境变量
  124.     setenv("PATH", "/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", 1);
  125.     setenv("LD_LIBRARY_PATH", "/vendor/lib:/system/lib", 1);
  126.     setenv("ANDROID_BOOTLOGO", "1", 1);
  127.     setenv("ANDROID_ROOT", "/system", 1);
  128.     setenv("ANDROID_DATA", "/data", 1);
  129.     setenv("ANDROID_ASSETS", "/system/app", 1);
  130.     setenv("EXTERNAL_STORAGE", "/sdcard", 1);
  131.     setenv("ASEC_MOUNTPOINT", "/mnt/asec", 1);
  132.     setenv("LOOP_MOUNTPOINT", "/mnt/obb", 1);
  133.     char* exec_args[argc + 1];
  134.     size_t i = 0;
  135.     for (; *argv != NULL; ++i)
  136.     {
  137.       exec_args[i] = *argv++;
  138.     }

  139.     if (i == 0) exec_args[i++] = "/system/bin/sh";
  140.     exec_args[i] = NULL;

  141.     execvp(exec_args[0], exec_args);
  142.     printf("failed to exec %s", exec_args[0]);
  143. }

  144. //Android.mk
  145. LOCAL_SRC_FILES := su.cpp
  146. LOCAL_MODULE := su
  147. LOCAL_MODULE_FILENAME := su
  148. LOCAL_LDFLAGS += -fPIE -pie
  149. LOCAL_CFLAGS += -fPIE
  150. include $(BUILD_EXECUTABLE)

  151. //Application.mk   根据自己的需求调整
  152. APP_ABI := armeabi
  153. APP_PLATFORM := android-15

复制代码


在jni目录下执行ndk-build即可,生成的su文件替换成/system/bin/mysu
模拟器中:
adb remount                                //使/system可写
adb push \??su /system/bin/mysu
adb shell chmod 6777 /system/bin/mysu      //使普通进程可以执行su并获取root权限

我们用简单的代码测试:

  1.     public static boolean canRunRootCommands() {
  2.         boolean retval = false;
  3.         Process suProcess;

  4.         try {
  5.             suProcess = Runtime.getRuntime().exec("mysu");

  6.             DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
  7.             DataInputStream osRes = new DataInputStream(suProcess.getInputStream());

  8.             if (null != os && null != osRes) {
  9.                 // Getting the id of the current user to check if this is root
  10.                 os.writeBytes("id\n");
  11.                 os.flush();

  12.                 String currUid = osRes.readLine();
  13.                 boolean exitSu = false;
  14.                 if (null == currUid) {
  15.                     retval = false;
  16.                     exitSu = false;
  17.                     Log.d("ROOT", "Can't get root access or denied by user");
  18.                 } else if (true == currUid.contains("uid=0")) {
  19.                     retval = true;
  20.                     exitSu = true;
  21.                     Log.d("ROOT", "Root access granted");
  22.                 } else {
  23.                     retval = false;
  24.                     exitSu = true;
  25.                     Log.d("ROOT", "Root access rejected: " + currUid);
  26.                 }

  27.                 if (exitSu) {
  28.                     os.writeBytes("exit\n");
  29.                     os.flush();
  30.                 }
  31.             }
  32.         } catch (Exception e) {
  33.             // Can't get root !
  34.             // Probably broken pipe exception on trying to write to output
  35.             // stream after su failed, meaning that the device is not rooted

  36.             retval = false;
  37.             Log.d("ROOT",
  38.                     "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage());
  39.         }

  40.         return retval;
  41.     }

复制代码

可以发现是成功的

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号|网站地图

GMT+8, 2019-6-18 07:42 , Processed in 0.095780 second(s), 37 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表