当前位置:首页 > 知识 > 

AndroidRoot的本质

AndroidRoot的本质

AndroidRoot的本质 这篇文章是我博客之前写好的,博客地址: 拿来水一水 前言 本来说暑假学一点安卓,结果看来看去还是被Root吸引了,《第一行代码》看了一小部分,然后凭着自己的理

AndroidRoot的本质

这篇文章是我博客之前写好的,博客地址:

拿来水一水

前言

本来说暑假学一点安卓,结果看来看去还是被Root吸引了,《第一行代码》看了一小部分,然后凭着自己的理解,大概明白了Root的原理。这篇文章就是就当培养兴趣,也没啥技术干货,当故事讲。

因为笔者水平有限,如果这篇文章有技术错误,可以在下方指出,我会及时更改

Android系统

众所周知,Android系统是在Linux的基础上开发的,安卓本质上就是Linux的二次开发,用的依旧是Linux内核,只不过安卓封装了一层。对于Linux的底层,/为根目录的文件系统,/bin目录下的cd ls su命令,都依旧存在在手机中,只不过安卓做好了封装,对于用户是不可见的,就像安卓机上系统不会给你一个终端让你玩,当然很多第三方app有这种功能(要root才能使用)

在我还没学安卓的时候我一直有一个疑惑,为什么安卓一般都用Java写。C才应该是跟系统打交道的语言啊。要回答这个问题我首先会介绍一些系统知识,以防止不太了解的同学听不懂

可执行文件

一般来说,我们提到的应用软件都指的是可执行文件,在Windows上,这个文件是EXE,在Linux上,一般指的是ELF,操作系统提供了对可执行文件的支持,可执行文件不需要任何其他环境就可以执行。所以我们编写软件,也一般指的是编写EXE或ELF文件。

对于exe或者elf,C语言家族肯定是老大哥,c的编译默认就是生成可执行文件,编译完成只需要双击就可以运行。(这里不讨论系统库(dll或者so))而对于其他热门语言来说,首先很大一部分不支持生成可执行文件,其次对于一些和系统打交道的底层细节处理上无法实现或者很难实现(比如我要给我的硬件发送硬件信号,读取内存为0x80000的内容)

系统调用

为什么会这样,就要介绍系统调用了,这方面内容比较复杂,详细的话可以百度,我这里简单介绍一下。

我们把上图的用户当作是我们写的程序,对于操作系统来说,操作系统承当负责用户与计算机硬件中间的翻译者,操作系统提供了很多名为系统调用的函数,对于操作系统来说,程序不需要也不允许直接操控硬件,一切直接与硬件交互的事情都交给操作系统来做,这就是内核态。

程序只需要使用系统调用就可以完成大多数功能。这就是用户态。

因为对于硬件来说,硬件的控制过于麻烦,不可能每个程序员都需要深入了解硬件的控制才能写程序,比如程序员想读取一个文件,需要先判断文件在哪个扇区磁道,然后编程序向硬盘发送对应硬件信号,读取xx扇区xx磁道。估计世界上没几个人想当程序员了。而如果拥有操作系统,只需要使用操作系统提供的系统调用函数 open和read函数,就可以轻松读取文件。

比如C语言中最常见的printf函数,其实这个函数在系统调用函数的基础上继续做了封装,最底层的系统函数是write函数。

C语言

扯远了,继续谈为什么系统应用常用c语言来做,如上所说,要实现最所有基本的功能,就需要程序能够调用系统提供的系统调用函数。系统调用函数本质就是在内存中存在的一串汇编代码。所以理论上只需要知道这串代码的起始地址,就可以调用系统调用函数。而对于C语言,首先默认支持调用系统调用函数,原因是C的函数调用默认就是指针(内存地址)调用。

而对于其他语言,内存地址大部分都是被屏蔽的,所以我们无法通过指针调用系统原始的系统调用。虽然一般这些语言会在底层封装好一些常见的系统调用提供使用,但封装肯定会遗失一部分功能,对于一些底层功能,用高级语言就难以实现,再就是之前说的,很多语言不支持生成exe,而且还需要运行库。所以一些时候,用其他语言直接做软件比较麻烦,当然也能做。

Android 系统

继续回到安卓,安卓的开发者可能觉得用C开发手机应用比较麻烦,于是用了Java把常用系统调用封装了一遍,并且屏蔽了底层的所有细节。相当于安卓开发者用Java在linux的基础上在开发了一个新系统,而这个新系统提供的系统调用都是Java编写的,所以app开发者也必须用Java去调用这些系统调用函数,所以安卓就用Java开发最方便。如果当初开发者用Python封装这些系统调用函数,可能安卓就要用python写了。

我们可以理解安卓系统是建立在Linux上的一个沙盒,底层的细节都被屏蔽。

说了这么久还没说root的本质,其实手机root就是获取root权限,没错就是Linux最高权限用户root的权限。

但是安卓的开发者在开发的时候就对安卓系统做了严格的安全策略,只有内核部分权限具有root权限,一切用户态应用都是普通用户。也就是说我们编的程序在安卓上都是普通用户权限。

对于Linux,如果我们要成为root,大家都会想到使用su命令,然而安卓开发者也想到了这个命令,他们对su命令进行了更改,加入了一行逻辑,如果该用户不是root权限,那么不允许使用su命令。

这就形成了一个逻辑闭环

想成为root - 使用su命令 - 必须具有root权限 - 想成为root

利用漏洞ROOT

虽然安卓开发者的想法天衣无缝,按照系统规则,程序确实无法拥有root权限。但是早期的安卓系统存在许多漏洞,学过提权原理的同学应该不难理解,root的本质就是提权,提权的本质一般就是利用高权限程序,劫持高权限程序代码,执行任意代码,这些代码就具有了高权限。提权就成功了。

比如pwn里最经典的栈溢出,如果一个内核程序具备root权限,同时存在栈溢出漏洞,那么就可以劫持执行任意代码,对于安卓的root,一般方法就是把su文件替换为没有限制的su文件,当然替换su文件需要有root权限。而我们劫持完root权限程序以后,就可以随意替换。这样以后所有程序,只需要运行一下su文件,就具有了root权限。

我拿现实举个例子,假如说系统就是一个大厦,大厦里的人分为领导和普通职工。普通职工如果想成为领导,需要从保险处拿取一个领导的令牌即可。

但是现在大厦封禁了保险处,只有领导才能去拿令牌,这就导致了逻辑闭环。但我们可以劫持领导的行为,让领导去帮我们拿令牌。

比如某个领导每天都会把自己办公室电脑的备忘录上记录的事情都原封不动的做一遍,如果这个领导很蠢,备忘录上有什么就做什么,从不检查(就跟计算机程序一样),那我们可以偷偷溜进他的办公室,在他电脑的备忘录上写一条,“去保险处拿一个令牌给我”。这就是漏洞提权的原理

当然安卓这么多版本,具体的漏洞原理我肯定不会讲,但是安卓发展这么久了,就跟软件一样,漏洞越来越难挖。以至于现在新版android已经几乎没有办法通过漏洞root了

boot和recovery root

boot是开机启动时要执行的一段代码,recovery是一个与安卓系统平行的一个小工具系统,类似Windows PE

具体原理就是,既然安卓系统层面上无法root,我就绕过系统,在不加载系统的时候先把su文件替换了。

具体可以看看

这篇文章

物理root (自己想的)

学过逆向的肯定知道一句话,没有破不了的软件,只有不值得破的软件

我觉得在安卓身上也是,虽然软件层面不可破,但是毕竟自己的手机在自己手里啊。

既然我只需要替换一个su文件就可以root,su文件无法更改是操作系统的限制,那我能不能把手机磁盘取下来,用其他硬件设备或者其他手机连上去,然后放回原来的手机。

就跟windows一样,我一直有个想法,如果windows密码忘记了,如果密码是一个文件存储的,那能不能把磁盘取下来,放到别的电脑上,把密码文件改了,再插回去,毕竟电脑手机在自己手里。IOS越狱也同理。

虽然理论逻辑听上去没有什么问题,但是好像这方面的资料找不到,网上也没有相关信息,这个只能是猜测。

但是自己想一下,如果硬盘是微电子嵌入在主板中的可能就取不下来了。或者操作系统会对一些文件做签名校验?不过这样应该只会增大破解难度。

可惜,这个只是猜测,我没找到比较详细的资料(可能我搜索关键字不太对?)如果有师傅了解这个的,欢迎和我探讨。不甚感激

以上就是(AndroidRoot的本质)全部内容,收藏起来下次访问不迷路!