手机如何绕过Root检测
一、Root检测原理
- 手机一旦root,在某些目录下就会生成对应的特征文件(su),app做root检测时,就是通过java或者so代码来检查这些特征
二、Root绕过方案
-
方案1:通用frida hook脚本
const commonPaths = [ "/data/local/bin/su", "/data/local/su", "/data/local/xbin/su", "/dev/com.koushikdutta.superuser.daemon/", "/sbin/su", "/system/app/Superuser.apk", "/system/bin/failsafe/su", "/system/bin/su", "/su/bin/su", "/system/etc/init.d/99SuperSUDaemon", "/system/sd/xbin/su", "/system/xbin/busybox", "/system/xbin/daemonsu", "/system/xbin/su", "/system/sbin/su", "/vendor/bin/su", "/cache/su", "/data/su", "/dev/su", "/system/bin/.ext/su", "/system/usr/we-need-root/su", "/system/app/Kinguser.apk", "/data/adb/magisk", "/sbin/.magisk", "/cache/.disable_magisk", "/dev/.magisk.unblock", "/cache/magisk.log", "/data/adb/magisk.img", "/data/adb/magisk.db", "/data/adb/magisk_simple", "/init.magisk.rc", "/system/xbin/ku.sud", "/data/adb/ksu", "/data/adb/ksud" ]; const ROOTmanagementApp = [ "com.noshufou.android.su", "com.noshufou.android.su.elite", "eu.chainfire.supersu", "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.koushikdutta.rommanager", "com.koushikdutta.rommanager.license", "com.dimonvideo.luckypatcher", "com.chelpus.lackypatch", "com.ramdroid.appquarantine", "com.ramdroid.appquarantinepro", "com.topjohnwu.magisk", "me.weishu.kernelsu" ]; function stackTraceHere(isLog){ var Exception = Java.use('java.lang.Exception'); var Log = Java.use('android.util.Log'); var stackinfo = Log.getStackTraceString(Exception.$new()) if(isLog){ console.log(stackinfo) }else{ return stackinfo } } function stackTraceNativeHere(isLog){ var backtrace = Thread.backtrace(this.context, Backtracer.ACCURATE) .map(DebugSymbol.fromAddress) .join("\n\t"); console.log(backtrace) } function bypassJavaFileCheck(){ var UnixFileSystem = Java.use("java.io.UnixFileSystem") UnixFileSystem.checkAccess.implementation = function(file,access){ var stack = stackTraceHere(false) const filename = file.getAbsolutePath(); if (filename.indexOf("magisk") >= 0) { console.log("Anti Root Detect - check file: " + filename) return false; } if (commonPaths.indexOf(filename) >= 0) { console.log("Anti Root Detect - check file: " + filename) return false; } return this.checkAccess(file,access) } } function bypassNativeFileCheck(){ var fopen = Module.findExportByName("libc.so","fopen") Interceptor.attach(fopen,{ onEnter:function(args){ this.inputPath = args[0].readUtf8String() }, onLeave:function(retval){ if(retval.toInt32() != 0){ if (commonPaths.indexOf(this.inputPath) >= 0) { console.log("Anti Root Detect - fopen : " + this.inputPath) retval.replace(ptr(0x0)) } } } }) var access = Module.findExportByName("libc.so","access") Interceptor.attach(access,{ onEnter:function(args){ this.inputPath = args[0].readUtf8String() }, onLeave:function(retval){ if(retval.toInt32()==0){ if(commonPaths.indexOf(this.inputPath) >= 0){ console.log("Anti Root Detect - access : " + this.inputPath) retval.replace(ptr(-1)) } } } }) } function setProp(){ var Build = Java.use("android.os.Build") var TAGS = Build.class.getDeclaredField("TAGS") TAGS.setAccessible(true) TAGS.set(null,"release-keys") var FINGERPRINT = Build.class.getDeclaredField("FINGERPRINT") FINGERPRINT.setAccessible(true) FINGERPRINT.set(null,"google/crosshatch/crosshatch:10/QQ3A.200805.001/6578210:user/release-keys") // Build.deriveFingerprint.inplementation = function(){ // var ret = this.deriveFingerprint() //该函数无法通过反射调用 // console.log(ret) // return ret // } var system_property_get = Module.findExportByName("libc.so", "__system_property_get") Interceptor.attach(system_property_get,{ onEnter(args){ this.key = args[0].readCString() this.ret = args[1] }, onLeave(ret){ if(this.key == "ro.build.fingerprint"){ var tmp = "google/crosshatch/crosshatch:10/QQ3A.200805.001/6578210:user/release-keys" var p = Memory.allocUtf8String(tmp) Memory.copy(this.ret,p,tmp.length+1) } } }) } //android.app.PackageManager function bypassRootAppCheck(){ var ApplicationPackageManager = Java.use("android.app.ApplicationPackageManager") ApplicationPackageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(str,i){ // console.log(str) if (ROOTmanagementApp.indexOf(str) >= 0) { console.log("Anti Root Detect - check package : " + str) str = "ashen.one.ye.not.found" } return this.getPackageInfo(str,i) } //shell pm check } function bypassShellCheck(){ var String = Java.use('java.lang.String') var ProcessImpl = Java.use("java.lang.ProcessImpl") ProcessImpl.start.implementation = function(cmdarray,env,dir,redirects,redirectErrorStream){ if(cmdarray[0] == "mount"){ console.log("Anti Root Detect - Shell : " + cmdarray.toString()) arguments[0] = Java.array('java.lang.String',[String.$new("")]) return ProcessImpl.start.apply(this,arguments) } if(cmdarray[0] == "getprop"){ console.log("Anti Root Detect - Shell : " + cmdarray.toString()) const prop = [ "ro.secure", "ro.debuggable" ]; if(prop.indexOf(cmdarray[1]) >= 0){ arguments[0] = Java.array('java.lang.String',[String.$new("")]) return ProcessImpl.start.apply(this,arguments) } } if(cmdarray[0].indexOf("which") >= 0){ const prop = [ "su" ]; if(prop.indexOf(cmdarray[1]) >= 0){ console.log("Anti Root Detect - Shell : " + cmdarray.toString()) arguments[0] = Java.array('java.lang.String',[String.$new("")]) return ProcessImpl.start.apply(this,arguments) } } return ProcessImpl.start.apply(this,arguments) } } console.log("Attach") bypassNativeFileCheck() bypassJavaFileCheck() setProp() bypassRootAppCheck() bypassShellCheck()
项目地址:https://github.com/AshenOneYe/FridaAntiRootDetection
-
方案2:利用magisk + Shamiko模块 + 隐藏magisk应用
- 手机安装magisk
- magisk中安装Shamiko模块:https://pan.baidu.com/s/1WjzIlHriXEhQH6SEQ9SS9g?pwd=uj7u
- adb push xxx.zip /sdcard/Download/xxx.zip
- 在magisk右上角设置中:
- 开启zygisk,重启手机
- 隐藏magisk应用
- 配置排除列表(点击xx应用图标,然后勾选,这种才是全部勾选)
-
方案3:【不通用】
- 思路:反编译App -> 根据app上的提示词或者su相关的字眼,比如"/system/bin/su"进行搜索,找到root检测位置 -> 通过hook让代码不执行
-
方案4:AOSP【安卓开源项目】刷机方案