前言
现在很多app特别是银行、政务app等在使用时,假如你的手机已经被ROOT了,就会弹框提醒你的运行环境不安全,然后某些特定功能就无法使用。在逆向过程中常常会遇到ROOT检测的问题,假如无法绕过,就很难使用Xposed和Frida等常用工具,给逆向造成很大的困难。我个人认为ROOT的检测与绕过是一种基于Pattern的对抗,检测方根据ROOT后手机的一些特征Pattern来检测ROOT,而绕过方则是根据检测方的各种检测方式来设计各种绕过方法。本文主要总结一下平时遇到过的ROOT检测方式,以及绕过的一些思路。
ROOT检测
ROOT检测的方式多种多样,现在市面上很多app都直接或间接的使用这个项目进行ROOT检测:RootBeer
这个项目的Readme也说的很清楚,主要是分为Java层和Native层两层进行ROOT检测,检测的对象如下:
- checkRootManagementApps
- checkPotentiallyDangerousApps
- checkRootCloakingApps
- checkTestKeys
- checkForDangerousProps
- checkForBusyBoxBinary
- checkForSuBinary
- checkSuExists
- checkForRWSystem
还是比较全面的,基本上能够覆盖市面上其他APP的ROOT检测方式了。总结一下主要分为几类
- 已安装App检测,如是否有magisk
- 文件检测,如”/sbin/su”
- Prop检测,如”ro.debuggable”
- System分区是否可写
检测使用的API也是多种多样,比如Java层的File.exists和File.canRead都能用来检测文件是否存在,Native层的fopen和access也一样。目前我见识过并成功分析的ROOT检测就是上面这些了。
于是基于上面这些,我写了个通用的ROOT检测绕过脚本,对于大多数app都能很好的work,不过最近遇到一个case,我很明确知道它有ROOT检测,但是用我的脚本却没有打印出任何ROOT检测的痕迹,这搞得我很头大,一度放弃了正面硬刚,采取了一些Trick绕过了ROOT检测(下文会讲)。
不过这几天突然想起来,这个app明明连壳都没有加,没道理只有ROOT检测强的离谱。事实上,它的ROOT检测并不强。它ROOT检测时会新开一个子进程来做,所以我HOOK上原始进程是没有用的。
此外Google的safetynet也能用于做ROOT检测,貌似很强,但是由于我逆向的国外app比较少所以没怎么见识过。
ROOT绕过
检测ROOT的方式相对固定,但是ROOT绕过的方式可以有很多
硬刚
最最直接的ROOT检测方式就是找到APP中ROOT检测的逻辑然后直接返回False就行了,不多赘述
Objection
Objection集成了Root bypass功能,只需输入
代码语言:javascript复制android root disable
即可绕过许多app的root检测,但是看了一下这部分的源码,objection只是绕过了Java层的一些文件检测而已,所以很多情况下是不奏效的。不过即便如此,它还是很好的帮我度过了新手期。
通用bypass脚本
既然上面的RootBeer这么牛逼,覆盖面这么广,那么我们就针对它来写一个对应的绕过脚本,根据它使用的api以及检测的对象,来一个一个的hook。
最初版本就是一板一眼的照着它的api进行hook,后来进行优化,去看安卓源码,然后对这些api从更加底层的位置进行hook,一方面可以找到多个函数之间可能存在的公共底层函数,这样就没必要去hook多个函数了;另一方面可以防止app使用反射来逃避我们的hook。最后考虑到多进程ROOT检测的问题,使用Python-binding的child-gating来对子进程进行hook。参考frida 如何hook 多进程
我的绕过脚本开源在这:FridaAntiRootDetection
其他旁门左道
重打包
通过给app植入Frida-gadget或者xposed框架后重打包就能在无root的手机上使用frida。实际上上面提到的那个多进程的case我就是用这个方法来逃避root检测的,这种方法适用于ROOT检测很强但是签名校验很弱的情况,因为重打包必须要绕过签名校验。
临时ROOT
我在其他文章中也多次提到这个,主要的思路就是使用magisk将boot.img进行patch后,使用fastboot boot magisk.img
进行启动,而不是用fastboot flash boot magisk
,这样就能拥有临时ROOT,这个ROOT在重启之后就会消失。所以在ROOT期间,我们可以对目标app进行SO文件的patch,完成后重启,patch不会随着ROOT而消失。
编译系统
通过编译系统,植入frida或者修改主要的目标系统源码,就能在无ROOT的情况下,达到与ROOT相同的效果。
magisk模块
我没怎么用过这些模块,不太清楚,这边只是提一下有这个方法,原理大概就是隐藏su文件之类的吧。