前面我们说到的都是一些比较简单的Hack手段,如果要完全掌握你的设备要怎么办?这里就会有人说了,当然是ROOT了。对,今天我就来讲一讲怎么从一台安卓手机上获得ROOT权限。怕是有人要说了,ROOT谁不会啊,用一手一键ROOT工具,一秒钟就ROOT了好么!或者嫌这个比较low,我甚至还会用Recovery刷一个ROOT包获取root呢。这有什么好讲的!但是,AS A GEEKER 用这些东西还是很低端好么,要干我们就自己干,区区root还需要等别人适配么?Of course not!

0x000 什么是root权限?

其实root说白了,就是一个程序(因为可以在命令行里执行而且它并不是buildin指令,所以当然是一个程序),用来切换用户到超级用户权限。在超级用户权限下可以做很多普通用户做不了的事情。我们知道,在linux上做这件事的程序是su,所以在Android中我们沿用了这个名字,继续把做这件事的程序叫做su(其实Android程序获取root权限也是通过在runtime里执行su -c 来得到root权限的,系统怎么会给你这个api呢)。

0x001 su干了什么?

恩。我们知道超级用户权限是内核给出的权限特例,所以如果内核没有给你这个东西的入口,我们自然没法使用它。而我们看一般的安卓设备里并没有su这个程序,也就是说android设备是封闭了这个入口的。但是!我们还有另一个方法可以做到类似的事情,这个东西的名字叫setUID。这个setUID其实是Linux里的一个特殊的权限,它可以让你设置程序的UID。如果我们讲这个程序的UID设置为超级用户,那就可以做和超级用户一样的事情了。所以我们要做的,就是把su程序写入到/system/bin 目录然后给它设置4775权限(setUID+775) 当然 777也是可以的。

0x002 我们要怎么写su

程序里需要做的是只有一件,那就是setUID到root,然后解析传入的指令并执行。但一般来说,为了保证安全,我们会配套一个权限管理程序,这个程序与su之间通过socket链接,每次su接收到请求就向权限管理程序发送该程序包名,从而得到是否获得授权。所以总而言之就是鉴权+授权。那么写起来就很简单了,su完全可以写成,这么短


#define LOG "su"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__)

int main (){
LOGD(LOG, "su!");
setUID(0);
return 0;
}


当然这不包含执行命令和鉴权部分,其实加上也最多五十行,就是这么一个小程序。当然这个程序我们没法直接编译,我们这里用NDK工具里的ndk-build编译
编译脚本android.mk 以及 application.mk

###android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := su
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
include $(BUILD_EXECUTABLE)

###application.mk
APP_ABI := x86 armeabi-v7a
#这里指编译 x86和arm两种指令集的可执行程序 虽然我们用到的只有arm版的


得到一个名字为su的可执行文件

0x003 我们要怎么使用这个su

从前面的分析我们可以知道,它必须在系统的PATH目录下并且权限为4775以上才可以生效。但android默认的path目录只有 /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin 而这些目录的所有者都是root,也就是说我们陷入了一个死锁,需要root权限把这东西放进去获取root权限。但是这个死锁中有一个突破口,那就是recovery。我们也许经常听说recovery,但这个东西是什么,它其实是一个特殊的分区,用于恢复异常状态下的android设备,我们知道,recovery是可以三清的,那它必定要有root权限(因为/system/data等目录也是root用户所属)。所以我们可以在recovery里用recovery脚本将su移动到/system/bin/并赋予4775权限(也可以顺便把我们的apk移到system/app里 这样开机我们的apk就会出现在应用列表中了),这样我们就达成了目的。编辑刷机脚本update-script.(为了简洁 不用assert进行机型和环境的判断)


ui_print("Start write su!");
show_progress(0.500000, 0);
format("yaffs2", "MTD", "system");
mount("yaffs2", "MTD", "system", "/system"); //格式化并挂载system分区
set_perm_recursive(0, 0, 0755, 0644, "/system");
set_perm_recursive(0, 2000, 0755, 0755, "/system/bin"); //调整/system/bin权限
package_extract_dir("binatry", "/system/bin");
set_perm(0,2000,0755,"system/bin/su"); //赋予su root用户的uid,shell的组gid,和755的读写执行权限
ui_print("Finish write su!");
show_progress(1.000000, 0);

然后把这个脚本和 binatry/su 这个文件夹一起打包成一个ota.zip, 通过recovery刷进去就好了。但是一般的官方recovery是会校验包签名的,所以我们要先刷入第三方的recovery。但一般为了刷这个recovery我们就要先解锁bootloader。这也就是刷机稍微困难一些地地方。但其实还有其他方法可以把su写入系统,这个我们以后再讲。

总结:所以我们一般说的root和recovery并无关系,第三方recovery只是给root提供了一个手段。干脆下次再做一个手写recovery的教程算了 恩恩,这才够geek呐。

分类:

发表评论

电子邮件地址不会被公开。