概述:通过阅读本文可以深刻理解Android系统中获得Root权限的方法和原理。本文会详细介绍Root的目的,原理和代码层次的具体实现方法。
Android Root介绍:
1. Root目的
手机获得Root权限以后,用户就可以完全拥有手机系统的最高权限,在Linux系统中相当于Root账号,在Windows系统中相当于Administrator账号。因为Android系统是基于Linux的,所以叫Root权限。
有了Root权限以后,用户可以*删除一些系统自带的无用软件,更换开关机铃声,去除状态栏弹出的广告和常用软件中嵌入的第三方广告平台展示广告的干扰,让你的手机随心所欲,不再受干扰,总之一句话Root可以让你真正享有手机主人的感觉。
2. Root原理介绍
给手机Root的原理大概分为三个步骤:步骤一,把su文件拷贝到/system/bin/目录下面。步骤二,把Superuser.apk放到/system/app/目录下面。步骤三,设置/system/bin/su让任意用户都可以运行并且拥有set_uid和set_gid的权限。
当然,这些操作厂商是不会轻易允许我们这样做的,这样我们就需要去利用Android操作系统的各种漏洞去实现这些操作,利用这些漏洞完成以上三步操作的过程就是Root的过程。
Su – Switch User切换用户。
3. Root方法介绍
从Root的原理我们了解到,想要Root需要三个步骤:
- adb push su /system/bin — xbin下是放一些小工具来方便使用的
- adb push SuperUser.apk /system/app
- adb shell chmod 4755 /system/bin/su(关于chmod XXX可以到这里了解一下http://hi.baidu.com/angivo/item/345af44260142b09e9350416)
如果系统是英文版,那么经过以上三个步骤,Root就大功告成了,通过安装Root Explorer软件就可以在根目录下创建删除文件了。但是国内的手机的系统都是经过厂商改造过的中文版,通过以上三个步骤是不行的,原因有以下三点:
- 中文版的/system路径是只读权限,我们是不能完成写入或者copy操作的
- chmod命令是需要拥有Root权限后才可以使用的,我们的在操作的时候是没有Root权限的,所以这个命令在我们Root过程中是无法使用的
- 某些厂商定制的系统在系统重新启动的时候会自动将su的权限从4755改成755或者直接删除了su,正是因为这个原因我们经常会碰到,明明我们是已经Root过的手机,但是手机重启后就没有Root权限了。这种只是临时获得的Root权限。
针对以上三点,我们怎么能够确保获得永久的Root权限呢?一种方案是自己去烧制一个英文版boot.img,刷一个英文版的系统然后再Root就OK了。另外一种方案就是去实时监控system/bin目录下已有的su文件是否存在,如果不存在就立即copy一个过去。
4. 深入理解Root机制
Root调用流程如下:
- su被用户调用
- su创建一个socket监听,搭建一个通道来完成通讯
- su通过广播的方式通知superuser目前有一个应用要使用Root
- su等待socket数据通讯完成,通常会有超时处理
- superuser在收到广播以后会在界面弹出一个对话框,与用户交互,询问用户是否给予Root权限
- superuser将用户的选择结果再通过socket回传给su
- su根据socket得到的结果在做相应的处理判断应不应该继续给Root权限
- 完成本次授权处理
Superuser.apk这个应用是Root成功后,专门用来管理Root权限使用的,防止恶意应用滥用。可以去这个地方下载官方的superuser源码和su文件:http://superuser.googlecode.com/svn/trunk/ 自己就可以在Eclipse上打开superuser代码,完成编译和安装。
Superuser和su之间的通讯原理:
Superuser使用运行在Java虚拟机中,而su是运行在Linux的真是进程中,他们两个之间通讯superuser这个应用来完成大部分工作,superuser一共有两个Activity:一个是SuperuserActivity另外一个是SuperuserRequestActivity,其中SuperuserActivity是用来管理白名单的,用来记住那些应用程序已经被允许使用Root权限了,这样白名单中的应用再次提权时,就不需要麻烦用户选择了。而superuserRequestActivity是用来负责弹出对话框询问用户当前某个应用请求使用Root权限,让用户来完成选择授予还是不授予。如果用户选择永久授予Root权限,那会通过SuperuserActivity会将本次提权的应用写入白名单中。白名单其实就是一个sqlite的数据库,来保存用户选择永久授予Root权限的应用名单。白名单在数据库中位置为:
/data/data/com.koushikdutta.superuser/databases/superuser.sqlite
上文已经说过,Root的本质就是往 /system/bin/ 目录下放一个su文件,并且给su文件4755的权限,任何用户都有调用su的权限,这样普通程序可以调用该su来运行Root权限的命令。superuser.apk中就自带了一个这样的su程序。一开始superuser会检测/system/bin/su是否存在:
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文件正确,直接返回了事。
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();
有进程使用root权限,superuser是怎么知道的呢,关键是句:
sprintf(sysCmd, "am start -a android.intent.action.MAIN -n com.koushikdutta.superuser/com.koushikdutta.superuser.SuperuserRe questActivity --ei uid %d --ei pid %d > /dev/null", g_puid, ppid);
if (system(sysCmd))
return executionFailure("am.");
Superuser操作白名单代码:
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;
}
5. 资源文件的获取
从上文的源码地址获取源代码,替换系统的system/extras/su/下面的su.c 和Android.mk文件,使用编译命令./mk td28 u adr system/extras/su/ 编译成功后会生成out/target/product/hsdroid/system/xbin/su 文件,而Superuser.apk就是普通的apk文件,都在源码地址里面可以下载,下载后倒入到eclipse即可直接运行。