Android root检测方法总结
一 为什么要进行root检测?
出于安全原因,我们的应用程序不建议在已经root的设备上运行,所以需要检测是否设备已经root,以提示用户若继续使用会存在风险。
二 root了会有什么风险?
在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者。
在系统中,每个文件、目录和进程,都归属于某一个用户,没有用户许可其它普通用户是无法操作的,但对root除外。
root用户的特权性还表现在:root可以超越任何用户和用户组来对文件或目录进行读取、修改或删除(在系统正常的许可范围内);对可执行程序的执行、终止;对硬件设备的添加、创建和移除等;也可以对文件和目录进行属主和权限进行修改,以适合系统管理的需要(因为root是系统中权限最高的特权用户);root是超越任何用户和用户组的,基于用户ID的权限机制的沙盒是隔离不了它的。
三 不root为什么就安全了呢?
Android安全架构是基于Linux多用户机制的访问控制。应用程序在默认的情况下不可以执行其他应用程序,包括读或写用户的私有数据(如联系人数据或email数据),读或写另一个应用程序的文件。
一个应用程序的进程就是一个安全的沙盒(在受限的安全环境中运行应用程序,在沙盒中的所有改动对操作系统不会造成任何危害)。它不能干扰其它应用程序,除非显式地声明了“permissions”,以便它能够获取基本沙盒所不具备的额外的能力。
每一个Android应用程序都会在安装时就分配一个独有的Linux用户ID,这就为它建立了一个沙盒,使其不能与其他应用程序进行接触。这个用户ID会在安装时分配给它,并在该设备上一直保持同一个数值。
所有的Android应用程序必须用证书进行签名认证,而这个证书的私钥是由开发者保有的。该证书可以用以识别应用程序的作者。签名影响安全性的最重要的方式是通过决定谁可以进入基于签名的permisssions,以及谁可以share 用户IDs。通过这样的机制,在不考虑root用户的情况下,每个应用都是相互隔离的,实现了一定的安全。
四 root的方式有哪些?
通常可以分为2种,不完全Root和完全Root
目前获取Android root 权限常用方法是通过各种系统漏洞,替换或添加SU程序到设备,获取Root权限,而在获取root权限以后,会装一个程序用以提醒用户是否给予程序最高权限,可以一定程度上防止恶意软件,通常会使用Superuser或者 SuperSU ,这种方法通常叫做“不完全Root”。
而 “完全ROOT”是指,替换设备原有的ROM,以实现取消secure设置。
五 检测Android设备是否root有哪些方法?
1、查看系统是否是测试版
我们可以查看发布的系统版本,是test-keys(测试版),还是release-keys(正式版)。
可以先在adb shell中运行下命令查看:
root@android:/ # cat /system/build.prop | grep ro.build.tags
ro.build.tags=release-keys
这个返回结果“release-keys”,代表此系统是正式版。
在代码中的检测方法如下:
public static boolean checkDeviceDebuggable() {String buildTags = android.os.Build.TAGS;if (buildTags != null && buildTags.contains("test-keys")) {Log.i(LOG_TAG, "buildTags=" + buildTags);return true;}return false;}
若是非官方发布版,很可能是完全root的版本,存在使用风险。
可是在实际情况下,我遇到过某些厂家的正式发布版本,也是test-keys,可能大家对这个标识也不是特别注意吧。所以具体是否使用,还要多考虑考虑呢。也许能解决问题,也许会给自己带来些麻烦。
2、检查是否存在Superuser.apk
Superuser.apk是一个被广泛使用的用来root安卓设备的软件,所以可以检查这个app是否存在。
检测方法如下:
public static boolean checkSuperuserApk() {try {File file = new File("/system/app/Superuser.apk");if (file.exists()) {Log.i(LOG_TAG, "/system/app/Superuser.apk exist");return true;}} catch (Exception e) {}return false;}
3、检查su命令
su是Linux下切换用户的命令,在使用时不带参数,就是切换到超级用户。通常我们获取root权限,就是使用su命令来实现的,所以可以检查这个命令是否存在。这样,系统就会在PATH路径中搜索su,如果找到,就会执行,执行成功后,就是获取到真正的超级权限了。
public static synchronized boolean checkGetRootAuth() {Process process = null;DataOutputStream os = null;try {Log.i(LOG_TAG, "to exec su");process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.writeBytes("exit\n");os.flush();int exitValue = process.waitFor();Log.i(LOG_TAG, "exitValue=" + exitValue);if (exitValue == 0) {return true;} else {return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;} finally {try {if (os != null) {os.close();}process.destroy();} catch (Exception e) {e.printStackTrace();}}}
这种检测su的方法,应该是最靠谱的,不过,也有个问题,就是在已经root的设备上,会弹出提示框,请求给app开启root权限。这个提示不太友好,可能用户会不喜欢。
如果想安静的检测,可以用上两种方法的组合;如果需要尽量安全的检测到,还是执行su吧。
4、执行busybox
Android是基于Linux系统的,可是在终端Terminal中操作,会发现一些基本的命令都找不到。这是由于Android系统为了安全,将可能带来风险的命令都去掉了,最典型的,例如su,还有find、mount等。对于一个已经获取了超级权限的人来讲,这是很不爽的事情,所以,便要想办法加上自己需要的命令了。一个个添加命令也麻烦,有一个很方便的方法,就是使用被称为“嵌入式Linux中的瑞士军刀”的Busybox。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令。
所以若设备root了,很可能Busybox也被安装上了。这样我们运行busybox测试也是一个好的检测方法。
public static synchronized boolean checkBusybox() {try {Log.i(LOG_TAG, "to exec busybox df");String[] strCmd = new String[]{"busybox", "df"};ArrayList<String> execResult = executeCommand(strCmd);if (execResult != null) {Log.i(LOG_TAG, "execResult=" + execResult.toString());return true;} else {Log.i(LOG_TAG, "execResult=null");return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;}}
5、访问/data目录,查看读写权限
在Android系统中,有些目录是普通用户不能访问的,例如 /data、/system、/etc 等。
我们就已/data为例,来进行读写访问。本着谨慎的态度,我是先写入一个文件,然后读出,查看内容是否匹配,若匹配,才认为系统已经root了。
public static synchronized boolean checkAccessRootData() {try {Log.i(LOG_TAG, "to write /data");String fileContent = "test_ok";Boolean writeFlag = writeFile("/data/su_test", fileContent);if (writeFlag) {Log.i(LOG_TAG, "write ok");} else {Log.i(LOG_TAG, "write failed");}Log.i(LOG_TAG, "to read /data");String strRead = readFile("/data/su_test");Log.i(LOG_TAG, "strRead=" + strRead);if (fileContent.equals(strRead)) {return true;} else {return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;}}
六、具体如何使用?
只需调用以下代码即可
CheckRoot.isDeviceRooted()
其中CheckRoot.java的完整代码如下:
import android.util.Log;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;public class CheckRoot {private static String LOG_TAG = CheckRoot.class.getName();public static boolean isDeviceRooted() {if (checkDeviceDebuggable()) {return true;}//check buildTagsif (checkSuperuserApk()) {return true;}//Superuser.apk//if (checkRootPathSU()){return true;}//find su in some path//if (checkRootWhichSU()){return true;}//find su use 'which'if (checkBusybox()) {return true;}//find su use 'which'if (checkAccessRootData()) {return true;}//find su use 'which'if (checkGetRootAuth()) {return true;}//exec sureturn false;}public static boolean checkDeviceDebuggable() {String buildTags = android.os.Build.TAGS;if (buildTags != null && buildTags.contains("test-keys")) {Log.i(LOG_TAG, "buildTags=" + buildTags);return true;}return false;}public static boolean checkSuperuserApk() {try {File file = new File("/system/app/Superuser.apk");if (file.exists()) {Log.i(LOG_TAG, "/system/app/Superuser.apk exist");return true;}} catch (Exception e) {}return false;}public static synchronized boolean checkGetRootAuth() {Process process = null;DataOutputStream os = null;try {Log.i(LOG_TAG, "to exec su");process = Runtime.getRuntime().exec("su");os = new DataOutputStream(process.getOutputStream());os.writeBytes("exit\n");os.flush();int exitValue = process.waitFor();Log.i(LOG_TAG, "exitValue=" + exitValue);if (exitValue == 0) {return true;} else {return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;} finally {try {if (os != null) {os.close();}process.destroy();} catch (Exception e) {e.printStackTrace();}}}public static synchronized boolean checkBusybox() {try {Log.i(LOG_TAG, "to exec busybox df");String[] strCmd = new String[]{"busybox", "df"};ArrayList<String> execResult = executeCommand(strCmd);if (execResult != null) {Log.i(LOG_TAG, "execResult=" + execResult.toString());return true;} else {Log.i(LOG_TAG, "execResult=null");return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;}}public static ArrayList<String> executeCommand(String[] shellCmd) {String line = null;ArrayList<String> fullResponse = new ArrayList<String>();Process localProcess = null;try {Log.i(LOG_TAG, "to shell exec which for find su :");localProcess = Runtime.getRuntime().exec(shellCmd);} catch (Exception e) {return null;}BufferedWriter out = new BufferedWriter(new OutputStreamWriter(localProcess.getOutputStream()));BufferedReader in = new BufferedReader(new InputStreamReader(localProcess.getInputStream()));try {while ((line = in.readLine()) != null) {Log.i(LOG_TAG, "–> Line received: " + line);fullResponse.add(line);}} catch (Exception e) {e.printStackTrace();}Log.i(LOG_TAG, "–> Full response was: " + fullResponse);return fullResponse;}public static synchronized boolean checkAccessRootData() {try {Log.i(LOG_TAG, "to write /data");String fileContent = "test_ok";Boolean writeFlag = writeFile("/data/su_test", fileContent);if (writeFlag) {Log.i(LOG_TAG, "write ok");} else {Log.i(LOG_TAG, "write failed");}Log.i(LOG_TAG, "to read /data");String strRead = readFile("/data/su_test");Log.i(LOG_TAG, "strRead=" + strRead);if (fileContent.equals(strRead)) {return true;} else {return false;}} catch (Exception e) {Log.i(LOG_TAG, "Unexpected error - Here is what I know: "+ e.getMessage());return false;}}//写文件public static Boolean writeFile(String fileName, String message) {try {FileOutputStream fout = new FileOutputStream(fileName);byte[] bytes = message.getBytes();fout.write(bytes);fout.close();return true;} catch (Exception e) {e.printStackTrace();return false;}}//读文件public static String readFile(String fileName) {File file = new File(fileName);try {FileInputStream fis = new FileInputStream(file);byte[] bytes = new byte[1024];ByteArrayOutputStream bos = new ByteArrayOutputStream();int len;while ((len = fis.read(bytes)) > 0) {bos.write(bytes, 0, len);}String result = new String(bos.toByteArray());Log.i(LOG_TAG, result);return result;} catch (Exception e) {e.printStackTrace();return null;}}
}
Android root检测方法总结相关推荐
- Android root检测方法小结
出于安全原因,我们的应用程序不建议在已经root的设备上运行,所以需要检测是否设备已经root,以提示用户若继续使用会存在风险. 那么root了会有什么风险呢,为什么不root就没有风险,又怎么来检查 ...
- Android设备Root检测方法
app发布后,一些root用户可能会修改我们应用的一些信息,如传感器获得的数据,那么这些用户的数据就不再具有参考价值,应该被单独列出, 以方便数据的分析,所以就有了本文. 下面是检测Android设备 ...
- android 绕过root检测,公主连结怎么绕过root检测 绕过root检测方法一览
公主连结刷初始怎么绕过root检测呢?很多小伙伴想刷初始可是经常被root检测,有没有什么办法才能绕过检测呢? 实机可以用magisk自带的hide功能,xposed框架可以选择rootcloak,A ...
- android内存检测方法,Android_Android系统检测程序内存占用各种方法,1.检查系统总内存
复制代码 - phpStudy...
Android系统检测程序内存占用各种方法 1.检查系统总内存 liuhx@uc ~ $ adb shell cat /proc/meminfo MemTotal: 840868 kB ...
- android+root+新方法,安卓手机最新Root通用教程
直接运行superSu Root失败 直接运行superSu等Root工具在很多手机上都会Root失败,关键在于没有相关权限,那么怎么才能在这些手机上获取Root权限呢? 开发者选项 首先打开开发者选 ...
- android判断软件是否已root权限,Android应用开发Android 判断手机是否有root权限方法...
本文将带你了解Android应用开发Android 判断手机是否有root权限方法,希望本文对大家学Android有所帮助. root权限是安卓最高的操作权限,俗称superuser,简称su,一般来 ...
- android 隐私泄露 路径,一种Android应用隐私泄露漏洞检测方法与流程
本发明涉及Android查漏的技术领域,尤其涉及到一种Android应用隐私泄露漏洞检测方法. 背景技术: 在目前的Android隐私泄露漏洞检测方法中,静态污点分析是最常用且最有效的方法.首先对an ...
- android获取录音读写权限设置,Android编程检测手机录音权限是否打开的方法
本文实例讲述了Android编程检测手机录音权限是否打开的方法.分享给大家供大家参考,具体如下: 6.0之前的权限检测只是检测到是否在清单文件中注册 Boolean flag = (PackageMa ...
- Android隐私合规检测方法
背景: 公司的APP被工信部通报:1.在用户确认隐私权限以前会获取用户的mac地址.2.在app内频繁的获取定位,超过了场景所必须的频次. 排查过程 收到通报我们一脸懵,我们排查业务代码中没有获取ma ...
最新文章
- JavaScript的编译模式
- 用偷梁换柱法清除腾讯QQ迷你首页的方法
- List 的add()与addAll()的区别
- 3. std::string::size_type
- 快速排序的性能和名字一样优秀
- CF903G-Yet Another Maxflow Problem【线段树,最大流】
- 利用POI 技术动态替换word模板内容
- 网游服务器通信架构设计
- Santander Customer Transaction Prediction(2)
- mysql1232_Mysql执行流程
- 3 EDA技术实用教程 【基础知识1】
- LCD 12864B V2.0的使用
- Java 前后端分离部署方式
- Adding Powers
- windows 强制关闭程序并强制删除文件
- Android 状态栏常规操作(状态栏显示,状态栏颜色,沉浸式状态栏)
- java 生僻字 问号_csv导出姓名生僻字变问号
- 网络与信息安全实验总结(报文监听与分析,漏洞扫描,逆向工程,安全产品)
- 无线路由器的基础配置(一)
- 黑客教父龚蔚:是谁打开了潘多拉的魔盒
热门文章
- location 拦截所有_超强广告拦截软件,简直手机必备App,太太太太太太太太太好用了!...
- linux查看IO情况
- maya 中切换当前渲染器的方法和设置
- codevs 1227 方格取数2
- ruby rails + grape + sidekiq 项目实践
- 2020604 Java基础复习
- 云计算机服务英文翻译,基于云的服务,Cloud Based Service,音标,读音,翻译,英文例句,英语词典...
- 计算机管理员考核指标库,仓库管理员绩效考核指标.docx
- CODESYS 赛搏机器智能MIC7001总线控制器+松下A6BE总线驱动器
- python Dataframe 根据某一列的值来删除多行