环境检测:
一、HOOK环境
1、检测frida的特征:
进程/proc/self/fd/目录,寻找是否存在关键字 linjector
/data/local/tmp/下是否存在re.frida.server
public static boolean isFridaInjected() {
boolean back = false;
try {
String files = ToolUtil.getFiles("/proc/self/fd/");
if (files != null && files.length() > 0 && files.contains("linjector")) {
DeviceRiskMgr.sb.append("发现Frida特征: /proc/self/fd/ linjector");
back = true;
}
files = ToolUtil.getFiles("/data/local/tmp/");
if (files != null && files.length() > 0 && files.contains("re.frida.server")) {
DeviceRiskMgr.sb.append("发现Frida特征: /data/local/tmp/ re.frida.server");
back = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false; // 未发现Frida特征
}
2、检测Xposed特征: 方法1:检测下列文件或文件路径是否存在: "/sbin/.magisk/modules/riru_lsposed","/data/adb/lspd","/sbin/.magisk/modules/zygisk_lsposed","/sbin/.magisk/modules/riru_edxposed","/data/misc/riru/modules/edxp","/data/adb/riru/modules/edxp.prop","/sbin/.magisk/modules/taichi","/data/misc/taichi","/sbin/.magisk/modules/dreamland","/data/misc/riru/modules/dreamland","/data/adb/riru/modules/dreamland","/system/bin/app_process.orig","/system/xposed.prop","/system/framework/XposedBridge.jar","libxposed_art.so","libxposed_art.so",".no_orig","/system/lib64/","libxposed_art.so","/system/lib64/","libxposed_art.so",".no_orig","/system/bin/app_process_zposed","/system/framework/ZposedBridge.jar","/system/lib/","libzposed_art.so" 方法2:Hook loadClass加载类,检查程序加载的Class中是否包含名为de.robv.android.xposed.XposedBridge的类名路径。 方法3:遍历/data/data/目录,寻找有无以下包名: de.robv.android.xposed.installer #Xposed框架 org.meowcat.edxposed.manager #EdXposed框架 com.tsng.hidemyapplist #隐藏应用列表 com.tsng.hidemyroot #隐藏Root org.lsposed.manager #LSPosed框架 me.weishu.exp #VirtualXposed 太极 top.canyie.dreamland.manager #VirtualXposed 夢境 io.va.exposed #VirtualXposed 夢境 io.va.exposed64 #VirtualXposed 夢境 io.virtualapp #VirtualApp io.virtualapp.sandvxposed64 #VirtualApp
public static boolean isXposed() {
boolean back = false;
try {
List<String> files = Arrays.asList("/sbin/.magisk/modules/riru_lsposed", "/data/adb/lspd", "/sbin/.magisk/modules/zygisk_lsposed", "/sbin/.magisk/modules/riru_edxposed", "/data/misc/riru/modules/edxp", "/data/adb/riru/modules/edxp.prop", "/sbin/.magisk/modules/taichi", "/data/misc/taichi", "/sbin/.magisk/modules/dreamland", "/data/misc/riru/modules/dreamland", "/data/adb/riru/modules/dreamland", "/system/bin/app_process.orig", "/system/xposed.prop", "/system/framework/XposedBridge.jar", "/system/lib/libxposed_art.so", "/system/lib/.no_orig", "/system/lib64/libxposed_art.so", "/system/lib64/.no_orig", "/system/bin/app_process_zposed", "/system/framework/ZposedBridge.jar", "/system/lib/libzposed_art.so");
if (ToolUtil.checkFiles("xpose", files)) back = true;
files = Arrays.asList("de.robv.android.xposed.installer", "org.meowcat.edxposed.manager", "com.tsng.hidemyapplist", "com.tsng.hidemyroot", "org.lsposed.manager", "me.weishu.exp", "top.canyie.dreamland.manager", "io.va.exposed", "io.va.exposed64", "io.virtualapp", "io.virtualapp.sandvxposed64");
if (ToolUtil.isRunningApk(context, files)) back = true;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
二、机型和系统判定
1、检测是否是lineageOS系统,这个sdk主要的检测方法是:
1、查找是否存在特征文件:
/system/framework/org.lineageos.platform.jar
/system/framework/org.lineageos.hardware.jar
2、检测systemprop中是否存在:ro.lineage.build.version
2、检测是否是OpenHarmony系统,检测方法是:
检测systemprop中是否存在:ro.build.ohos.devicetype
3、检测品牌机系统和设备能否对应,检测方法是:
遍历/system/framework/下所有以.jar结尾的文件名称,与机型字符串进行比较(strcasestr比较,不区分大小写)
例如在vivo手机内,/system/framework/下存在以下文件,文件名中包含vivo:
public static boolean isModel_System() {
boolean back = false;
try {
//1、检测是否是lineageOS系统,
String files = ToolUtil.getFiles("/system/framework/");
if (files != null && files.length() > 0 && files.contains("org.lineageos.platform.jar")) {
sb.append("存在特征文件/system/framework/org.lineageos.platform.jar\n");
sb.append("检测是lineageOS系统\n");
}
if (files != null && files.length() > 0 && files.contains("org.lineageos.hardware.jar")) {
sb.append("存在特征文件/system/framework/org.lineageos.hardware.jar\n");
sb.append("检测是lineageOS系统\n");
}
if (ToolUtil.isProp("device model identification", "ro.lineage.build.version"))
back = true;
//2、检测是否是OpenHarmony系统
if (ToolUtil.isProp("system identification", "ro.build.ohos.devicetype"))
back = true;
//3.
boolean isBrand = false;
String brand = Build.MANUFACTURER.toLowerCase();
List<String> jarFiles = ToolUtil.getJarFiles("/system/framework/");
for (String jarFile : jarFiles) {
if (ToolUtil.containsBrand(jarFile, brand)) {
isBrand = true;
}
}
if (!isBrand) {
DeviceRiskMgr.sb.append("机型:" + brand + "\n");
DeviceRiskMgr.sb.append("未在/system/framework/下发现有关机型的以.jar结尾的文件名称\n");
back = true;
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
三、截图工具和模拟点击工具
1.检测运行的服务中是否存在minicap、minitouch、stfservice、minitouchagent、stfagent、testminicap关键字。
2.检查/data/local/tmp/有无以下文件或文件目录:
"minicap.so","minicap","minitouch","mini","mini/minicap","oat/arm64/scrcpy-server.odex","vysor.pwd","mobile_info.properties","tc/mobileagent","tc/input3.sh","tc/mainputjar7","com.cyjh.mobileanjian.id","com.cyjh.mobileanjianen.id","juejinAzykb/","minicap.so","juejinAzykb/TouchService.jar","mqc-scrcpy.jar","uiautomator-stub.jar","cloudtestig/cloudscreen","cloudtesting/touchserver","txysvr.apk","yijianwanservice.apk","screen-shread10x64.so","screen-shread5x32.so","maxpresent.jar","libtxysvr.so"
3.检查应用安装列表
检查有没有安装下列模拟点击的应用:
"com.cygery.repetitouch.pro","com.cyjh.mobileanjian","com.touchsprite.android","com.cjzs123.zhushou","com.touchspriteent.android","com.zidongdianji","org.autojs.autojspro","org.autojs.autojs","com.zdanjian.zdanjian","com.zdnewproject","com.ifengwoo.zyjdkj","com.angel.nrzs","com.cyjh.mobileanjian.vip","com.shumai.shudaxia","fun.tooling.clicker.cn","com.dianjiqi","com.miaodong.autoactionssss","com.mxz.wxautojiafujinderen","com.touchelf.app","com.stardust.scriptdroid","com.adinall.autoclick","com.i_cool.auto_clicker","com.kongshan.aidianji","com.xptech.catclicker","com.tingniu.autoclick","com.yicu.yichujifa","com.smallyin.autoclick","com.ksxkq.autoclick","com.x2.clicker","com.scott.autoclickhelper","com.auyou.auyouwzs",
检查有没有安装下列截图应用:
"com.github.uiautomator","com.github.uiautomator2","com.sigma_rt.totalcontrol","com.genymobile.scrcpy"
public static boolean isTool() {
boolean Back = false;
try {
//1.检测运行的服务中是否存在minicap、minitouch、stfservice、minitouchagent、stfagent、testminicap关键字。
List<String> packges = ToolUtil.getPackges(context);
if (packges != null && packges.size() > 0) {
String s = packges.toString();
List<String> keywords = Arrays.asList("minicap", "minitouch", "stfservice", "minitouchagent", "stfagent", "testminicap");
for (String re : keywords) {
if (s.contains(re)) {
sb.append("检测运行的服务中是否存在" + re + "关键字\n");
Back = true;
}
}
}
//2.检查/data/local/tmp/有无以下文件或文件目录:
List<String> file = Arrays.asList("minicap.so", "minicap", "minitouch", "mini", "mini/minicap", "oat/arm64/scrcpy-server.odex", "vysor.pwd", "mobile_info.properties", "tc/mobileagent", "tc/input3.sh", "tc/mainputjar7", "com.cyjh.mobileanjian.id", "com.cyjh.mobileanjianen.id", "juejinAzykb/", "minicap.so", "juejinAzykb/TouchService.jar", "mqc-scrcpy.jar", "uiautomator-stub.jar", "cloudtestig/cloudscreen", "cloudtesting/touchserver", "txysvr.apk", "yijianwanservice.apk", "screen-shread10x64.so", "screen-shread5x32.so", "maxpresent.jar", "libtxysvr.so");
for (int i = 0; i < file.size(); i++)
file.set(i, "/data/local/tmp/" + file.get(i));
if (ToolUtil.checkFiles("tool", file))
Back = true;
//3.检查应用安装列表
//检查有没有安装下列模拟点击的应用
List<String> list = Arrays.asList("com.cygery.repetitouch.pro", "com.cyjh.mobileanjian", "com.touchsprite.android", "com.cjzs123.zhushou", "com.touchspriteent.android", "com.zidongdianji", "org.autojs.autojspro", "org.autojs.autojs", "com.zdanjian.zdanjian", "com.zdnewproject", "com.ifengwoo.zyjdkj", "com.angel.nrzs", "com.cyjh.mobileanjian.vip", "com.shumai.shudaxia", "fun.tooling.clicker.cn", "com.dianjiqi", "com.miaodong.autoactionssss", "com.mxz.wxautojiafujinderen", "com.touchelf.app", "com.stardust.scriptdroid", "com.adinall.autoclick", "com.i_cool.auto_clicker", "com.kongshan.aidianji", "com.xptech.catclicker", "com.tingniu.autoclick", "com.yicu.yichujifa", "com.smallyin.autoclick", "com.ksxkq.autoclick", "com.x2.clicker", "com.scott.autoclickhelper", "com.auyou.auyouwzs");
if (ToolUtil.isRunningApk(context, list)) {
sb.append("检测到模拟点击应用\n");
}
// 检查有没有安装下列截图应用:
list = Arrays.asList("com.github.uiautomator", "com.github.uiautomator2", "com.sigma_rt.totalcontrol", "com.genymobile.scrcpy");
if (ToolUtil.isRunningApk(context, list)) {
sb.append("检测到截图应用\n");
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return Back;
}
四、模拟器
扫描常见的模拟器特征,主要检测的方法是:
1、是否存在以下文件目录:
"/system/bin/ldinit","/system/bin/ldmountsf","/system/lib/libldutils.so","/system/bin/microvirt-prop","/system/lib/libdroid4x.so","/system/bin/windroyed","/system/lib/libnemuVMprop.so","/system/bin/microvirtd","/system/bin/nox-prop","/system/lib/libnoxspeedup.so","/data/property/persist.nox.simulator_version","/data/misc/profiles/ref/com.bignox.google.installer","/data/misc/profiles/ref/com.bignox.app.store.hd","/system/bin/ttVM-prop","/system/bin/droid4x-prop","/system/bin/duosconfig","/system/etc/xxzs_prop.sh","/system/etc/mumu-configs/device-prop-configs/mumu.config","/boot/bstsetup.env","/boot/bstmods","/system/xbin/bstk","/data/bluestacks.prop","/data/data/com.anrovmconfig","/data/data/com.bluestacks.appmart","/data/data/com.bluestacks.home","/data/data/com.microvirt.market","/dev/nemuguest","/data/data/com.microvirt.toolst","/data/data/com.mumu.launcher","/data/data/com.mumu.store","/data/data/com.netease.mumu.cloner","/system/bin/bstshutdown","/sys/module/bstinput","/sys/class/misc/bstXqpb","/system/phoenixos","/xbin/phoenix_compat","/init.dundi.rc","/system/etc/init.dundi.sh","/data/data/com.ddmnq.dundidevhelper","/init.andy.cloud.rc","/system/bin/xiaopiVM-prop","/system/bin/XCPlayer-prop","/system/lib/liblybox_prop.so","/system/bin/tencent_virtual_input","/vendor/bin/init.tencent.sh","/data/youwave_id","/dev/vboxguest","/dev/vboxuser","/sys/bus/pci/drivers/vboxguest","/sys/class/bdi/vboxsf-c","/sys/class/misc/vboxguest","/sys/class/misc/vboxuser","/sys/devices/virtual/bdi/vboxsf-c","/sys/devices/virtual/misc/vboxguest","/sys/devices/virtual/misc/vboxuser","/sys/module/vboxguest","/sys/module/vboxsf","/sys/module/vboxvideo","/system/bin/androVM-vbox-sf","/system/bin/androVM_setprop","/system/bin/get_androVM_host","/system/bin/mount.vboxsf","/system/etc/init.androVM.sh","/system/etc/init.buildroid.sh","/system/lib/vboxguest.ko","/system/lib/vboxsf.ko","/system/lib/vboxvideo.ko","/system/xbin/mount.vboxsf","/dev/goldfish_pipe","/sys/devices/virtual/misc/goldfish_pipe","/sys/module/goldfish_audio","/sys/module/goldfish_battery","/sys/module/kvm_intel/","/sys/module/kvm_amd/","/init.android_x86_64.rc","/init.android_x86.rc","/init.androidVM_x86.rc","/init.intel.rc","/init.vbox2345_x86.rc"
2、system.prop下是否存在以下字段特征:
"init.svc.microvirtd","bst.version","ro.phoenix.version.code","ro.phoenix.version.codename","init.svc.droid4x","microvirt.memu_version","microvirt.imsi","microvirt.simserial","ro.px.version.build","ro.phoenix.os.branch","init.svc.su_kpbs_daemon","init.svc.noxd","init.svc.ttVM_x86-setup","init.svc.xxkmsg","ro.bild.remixos.version","microvirt.mut","init.svc.ldinit","sys.tencent.os_version","sys.tencent.android_id","ro.genymotion.version","init.svc.pkVM_x86-setup","ro.andy.version","ro.build.version.release","ro.product.model","ro.product.brand","ro.boot.bootloader","ro.build.version.securitypatch","ro.build.version.incremental","gsm.version.baseband","gsm.version.ril-impl","ro.build.fingerprint","ro.build.description","ro.build.product","ro.boot.vbmeta.digest","ro.hardware","ro.product.name","ro.product.board","ro.recovery_id","ro.expect.recovery_id","ro.board.platform","ro.product.manufacturer","ro.product.device","sys.usb.state","ro.setupwizard.mode","ro.build.id","ro.build.tags","ro.build.type","ro.debuggable",
3.检查挂载点,是否存在以下目录:
"/mnt/shared/Sharefolder","/tiantian.conf","/data/share1","/hardware_device.conf","/mnt/shared/products","/mumu_hardware.conf","/Andy.conf","/mnt/windows/BstSharedFolder","/bst.conf","/mnt/shared/Applications","/ld.conf"
检查挂载点,检查/proc/mounts中是否存在vboxsf字段.
4.检查是否安装了虚拟机软件:
1.VMOS虚拟机
方法1:运行服务查找:tomq_MANAGER_SERVICE
方法2:ROOT_DIR查找VMOS_SYS_NUM
方法3:/proc/self/root/data/data/查找包名:“com.vmos.app”、“com.vmos.pro”、 “com.vmos.ggp”
方法4:props查找:vmprop.androidid、vmprop.dev_ashmem、vmprop.ip、ro.vmos.simplest.rom
2.X8沙箱
方法1:props查找:ro.x8.version、ro.x8.uuid
方法2:查找文件目录:/x8/config/root.pkg.blacklist、/x8/config/full_vm是否存在
3.51虚拟机
/proc/self/root/data/data/查找包名:“com.f1player”、“com.f1player.play”
4.虚拟精灵和虚拟大师
/proc/self/root/data/data/查找包名:com.pspace.vandroid、com.yiqiang.xmaster
public static boolean isSimulator() {
boolean back = false;
try {
//是否存在以下文件目录:
List<String> Mult_File = Arrays.asList("/x8/config/root.pkg.blacklist", "/x8/config/full_vm", "/system/bin/ldinit", "/system/bin/ldmountsf", "/system/lib/libldutils.so", "/system/bin/microvirt-prop", "/system/lib/libdroid4x.so", "/system/bin/windroyed", "/system/lib/libnemuVMprop.so", "/system/bin/microvirtd", "/system/bin/nox-prop", "/system/lib/libnoxspeedup.so", "/data/property/persist.nox.simulator_version", "/data/misc/profiles/ref/com.bignox.google.installer", "/data/misc/profiles/ref/com.bignox.app.store.hd", "/system/bin/ttVM-prop", "/system/bin/droid4x-prop", "/system/bin/duosconfig", "/system/etc/xxzs_prop.sh", "/system/etc/mumu-configs/device-prop-configs/mumu.config", "/boot/bstsetup.env", "/boot/bstmods", "/system/xbin/bstk", "/data/bluestacks.prop", "/data/data/com.anrovmconfig", "/data/data/com.bluestacks.appmart", "/data/data/com.bluestacks.home", "/data/data/com.microvirt.market", "/dev/nemuguest", "/data/data/com.microvirt.toolst", "/data/data/com.mumu.launcher", "/data/data/com.mumu.store", "/data/data/com.netease.mumu.cloner", "/system/bin/bstshutdown", "/sys/module/bstinput", "/sys/class/misc/bstXqpb", "/system/phoenixos", "/xbin/phoenix_compat", "/init.dundi.rc", "/system/etc/init.dundi.sh", "/data/data/com.ddmnq.dundidevhelper", "/init.andy.cloud.rc", "/system/bin/xiaopiVM-prop", "/system/bin/XCPlayer-prop", "/system/lib/liblybox_prop.so", "/system/bin/tencent_virtual_input", "/vendor/bin/init.tencent.sh", "/data/youwave_id", "/dev/vboxguest", "/dev/vboxuser", "/sys/bus/pci/drivers/vboxguest", "/sys/class/bdi/vboxsf-c", "/sys/class/misc/vboxguest", "/sys/class/misc/vboxuser", "/sys/devices/virtual/bdi/vboxsf-c", "/sys/devices/virtual/misc/vboxguest", "/sys/devices/virtual/misc/vboxuser", "/sys/module/vboxguest", "/sys/module/vboxsf", "/sys/module/vboxvideo", "/system/bin/androVM-vbox-sf", "/system/bin/androVM_setprop", "/system/bin/get_androVM_host", "/system/bin/mount.vboxsf", "/system/etc/init.androVM.sh", "/system/etc/init.buildroid.sh", "/system/lib/vboxguest.ko", "/system/lib/vboxsf.ko", "/system/lib/vboxvideo.ko", "/system/xbin/mount.vboxsf", "/dev/goldfish_pipe", "/sys/devices/virtual/misc/goldfish_pipe", "/sys/module/goldfish_audio", "/sys/module/goldfish_battery", "/sys/module/kvm_intel/", "/sys/module/kvm_amd/", "/init.android_x86_64.rc", "/init.android_x86.rc", "/init.androidVM_x86.rc", "/init.intel.rc", "/init.vbox2345_x86.rc");
//sb.append("\n是否存在以下文件目录:");
if (ToolUtil.checkFiles("simulator", Mult_File))
back = true;
//system.prop下是否存在以下字段特征:
List<String> Mult_Prop = Arrays.asList("vmprop.androidid", "vmprop.dev_ashmem", "vmprop.ip", "ro.vmos.simplest.rom", "ro.x8.version", "ro.x8.uuid", "init.svc.microvirtd", "bst.version", "ro.phoenix.version.code", "ro.phoenix.version.codename", "init.svc.droid4x", "microvirt.memu_version", "microvirt.imsi", "microvirt.simserial", "ro.px.version.build", "ro.phoenix.os.branch", "init.svc.su_kpbs_daemon", "init.svc.noxd", "init.svc.ttVM_x86-setup", "init.svc.xxkmsg", "ro.bild.remixos.version", "microvirt.mut", "init.svc.ldinit", "sys.tencent.os_version", "sys.tencent.android_id", "ro.genymotion.version", "init.svc.pkVM_x86-setup", "ro.andy.version", "ro.build.version.release", "ro.product.model", "ro.product.brand", "ro.boot.bootloader", "ro.build.version.securitypatch", "ro.build.version.incremental", "gsm.version.baseband", "gsm.version.ril-impl", "ro.build.fingerprint", "ro.build.description", "ro.build.product", "ro.boot.vbmeta.digest", "ro.hardware", "ro.product.name", "ro.product.board", "ro.recovery_id", "ro.expect.recovery_id", "ro.board.platform", "ro.product.manufacturer", "ro.product.device", "sys.usb.state", "ro.setupwizard.mode", "ro.build.id", "ro.build.tags", "ro.build.type", "ro.debuggable");
// sb.append("\nsystem.prop下是否存在以下字段特征:");
if (ToolUtil.checkProps("simulator", Mult_Prop))
back = true;
//3.检查挂载点,是否存在以下目录:
//检查挂载点,检查/proc/mounts中是否存在vboxsf字段.
List<String> list = Arrays.asList("/mnt/shared/Sharefolder", "/tiantian.conf", "/data/share1", "/hardware_device.conf", "/mnt/shared/products", "/mumu_hardware.conf", "/Andy.conf", "/mnt/windows/BstSharedFolder", "/bst.conf", "/mnt/shared/Applications", "/ld.conf");
if (ToolUtil.checkFiles("simulator", list)) back = true;
String files1 = ToolUtil.getFiles("/proc/mounts");
if (files1 != null && files1.length() > 0 && files1.contains("vboxsf")) {
sb.append("检查/proc/mounts中是否存在vboxsf字段\n");
back = true;
}
// 4.检查是否安装了虚拟机软件:
String files = ToolUtil.getFiles("/proc/self/root/data/data/");
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.vmos.app", "com.vmos.pro", "com.vmos.ggp");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与VMOS虚拟机相关包名:" + re + "\n");
back = true;
}
}
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.f1player", "com.f1player.play");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与51虚拟机相关包名:" + re + "\n");
back = true;
}
}
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.pspace.vandroid", "com.yiqiang.xmaster");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与虚拟精灵和虚拟大师相关包名:" + re + "\n");
back = true;
}
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
五、改机软件 1.检测是否安装了改机软件: 检查包名是否存在:
"com.yztc.studio.plugin","com.soft.apk008v","com.uwish.app","zpp.wjy.xxsq","com.bigsing.changer","zap.fh.wipe","com.sollyu.xposed.hook.model","com.soft.apk008Tool","com.doubee.ig","com.variable.apkhook","com.addeasy.fastest","com.xenice.mask","com.shyl.artifact","com.android1500.androidfaker"
2.检查/dev/wgzs目录下的内容是否存在,若存在则获取值: "wg.cust.config.phone.id","wg.cust.s_android_id","wg.cust.sys.prop.filter","wg.cust.config.phone.imeimackey","wg.cust.config.phone.imei","wg.cust.config.pkg.name","wg.cust.destUids"
public static boolean isModification() {
boolean back = false;
try {
List<String> list = Arrays.asList("com.yztc.studio.plugin", "com.soft.apk008v", "com.uwish.app", "zpp.wjy.xxsq", "com.bigsing.changer", "zap.fh.wipe", "com.sollyu.xposed.hook.model", "com.soft.apk008Tool", "com.doubee.ig", "com.variable.apkhook", "com.addeasy.fastest", "com.xenice.mask", "com.shyl.artifact", "com.android1500.androidfaker");
if (ToolUtil.isRunningApk(context, list)) {
back = true;
}
list = Arrays.asList("wg.cust.config.phone.id", "wg.cust.s_android_id", "wg.cust.sys.prop.filter", "wg.cust.config.phone.imeimackey", "wg.cust.config.phone.imei", "wg.cust.config.pkg.name", "wg.cust.destUids");
String files = ToolUtil.getFiles("/dev/wgzs/");
if (files != null && files.length() > 0)
for (String re : list) {
if (files.contains(re)) {
back = true;
sb.append("检查/dev/wgzs目录存在参数:" + re + "\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
六、Root和Root工具 1.包名检测,遍历/data/data/目录,寻找有无以下包名:
"com.topjohnwu.magisk","eu.chainfire.supersu","com.noshufou.android.su","com.noshufou.android.su.elite","com.koushikdutta.superuser","com.thirdparty.superuser","com.yellowes.su","com.fox2code.mmm","io.github.vvb2060.magisk","com.kingroot.kinguser","com.kingo.root","com.smedialink.oneclickroot","com.zhiqupk.root.global","com.alephzain.framaroot","io.github.huskydg.magisk","me.weishu.kernelsu"
2.检查su文件是否存在 "/su/bin/su","/sbin/su","/data/local/xbin/su","/data/local/bin/su","/data/local/su","/system/xbin/su","/system/bin/su","/system/sd/xbin/su","/system/bin/failsafe/su","/system/bin/.ext/.su","/system/etc/.installed_su_daemon","/system/etc/.has_su_daemon","/system/xbin/sugote","/system/xbin/sugote-mksh","/system/xbin/supolicy","/system/etc/init.d/99SuperSUDaemon","/system/.supersu","/product/bin/su","/apex/com.android.runtime/bin/su","/apex/com.android.art/bin/su","/system_ext/bin/su","/system/xbin/bstk/su","/system/app/SuperUser/SuperUser.apk","/system/app/Superuser.apk","/system/xbin/mu_bak","/odm/bin/su","/vendor/bin/su","/vendor/xbin/su","/system/bin/.ext/su","/system/usr/we-need-root/su","/cache/su","/data/su","/dev/su","/system/bin/cph_su","/dev/com.koushikdutta.superuser.daemon","/system/xbin/daemonsu","/sbin/.mianju","/sbin/nvsu","/system/bin/.hid/su","/system/addon.d/99-magisk.sh"
3.检查magisk相关文件是否存在 "/cache/.disable_magisk","/dev/magisk/img","/sbin/.magisk","/cache/magisk.log","/data/adb/magisk","/system/etc/init/magisk","/system/etc/init/magisk.rc","/data/magisk.apk"
4.检测Android PATH环境变量,检测path路径下是否存在“/su”
5.检测 /proc/self/maps中的内容
1、检测 /proc/self/maps 是否存在名为“/memfd:/jit-cache”的段(加载zygisk模块时(也就是liblspd.so)的时候会讲其名称设置为jit-cache,这样的话so的内存段在maps中就是/memfd:/jit-cache)
2、通过检测map表是否存在匿名的并且具有可执行属性的内存判断是否存在lsposed
3、检测栈空间[stack]的权限是否为“rw-p”
6.检测ro.build.tags的值,读取 /system/build.prop并检测ro.build.tags的值是否为“test-keys”
7.检测seLinux安全上下文,cat /proc/%d/attr/prev检测app进程的selinux安全上下文是否为“u:r:zygote:s0”
8.检查/data/local/tmp/有无以下文件 shizuku shizuku_starter
public static boolean isRoot() {
boolean back = false;
try {
//1.包名检测,遍历/data/data/目录,寻找有无以下包名:
List<String> list = Arrays.asList("com.topjohnwu.magisk", "eu.chainfire.supersu", "com.noshufou.android.su", "com.noshufou.android.su.elite", "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.fox2code.mmm", "io.github.vvb2060.magisk", "com.kingroot.kinguser", "com.kingo.root", "com.smedialink.oneclickroot", "com.zhiqupk.root.global", "com.alephzain.framaroot", "io.github.huskydg.magisk", "me.weishu.kernelsu");
if (ToolUtil.isRunningApk(context, list)) back = true;
//2.检查su文件是否存在
list = Arrays.asList("/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/.ext/.su", "/system/etc/.installed_su_daemon", "/system/etc/.has_su_daemon", "/system/xbin/sugote", "/system/xbin/sugote-mksh", "/system/xbin/supolicy", "/system/etc/init.d/99SuperSUDaemon", "/system/.supersu", "/product/bin/su", "/apex/com.android.runtime/bin/su", "/apex/com.android.art/bin/su", "/system_ext/bin/su", "/system/xbin/bstk/su", "/system/app/SuperUser/SuperUser.apk", "/system/app/Superuser.apk", "/system/xbin/mu_bak", "/odm/bin/su", "/vendor/bin/su", "/vendor/xbin/su", "/system/bin/.ext/su", "/system/usr/we-need-root/su", "/cache/su", "/data/su", "/dev/su", "/system/bin/cph_su", "/dev/com.koushikdutta.superuser.daemon", "/system/xbin/daemonsu", "/sbin/.mianju", "/sbin/nvsu", "/system/bin/.hid/su", "/system/addon.d/99-magisk.sh");
if (ToolUtil.checkFiles("root su", list))
back = true;
//3.检查magisk相关文件是否存在
list = Arrays.asList("/cache/.disable_magisk", "/dev/magisk/img", "/sbin/.magisk", "/cache/magisk.ToolUtil.Log", "/data/adb/magisk", "/system/etc/init/magisk", "/system/etc/init/magisk.rc", "/data/magisk.apk");
if (ToolUtil.checkFiles("root magisk", list))
back = true;
//4.检测Android PATH环境变量,检测path路径下是否存在“/su”
if (new File("/path/su").exists()) {
sb.append("检测path路径下存在/su\n");
back = true;
}
// * 6.检测ro.build.tags的值,读取 /system/build.prop并检测ro.build.tags的值是否为“test-keys”
String property = System.getProperty("ro.build.tags");
if (property != null && "test-keys".equals(property)) {
sb.append("检测检测ro.build.tags的值为test-keys\n");
back = true;
}
//8.检查/data/local/tmp/有无以下文件
list = Arrays.asList("/data/local/tmp/shizuku", "/data/local/tmp/shizuku");
if (ToolUtil.checkFiles("root data", list))
back = true;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
检测手机是否刷了面具
public static boolean isMagisk() {
boolean back = false;
try {
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("command -v magisk", true);
System.out.println("isMagisk:" + commandResult.toString());
back = (commandResult.successMsg != null && commandResult.successMsg.contains("magisk"));
if (back) {
sb.append("command -v magisk: " + commandResult.successMsg + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
检测是否解锁了BL锁
public static boolean isBlOpen() {
boolean back = false;
try {
//getprop ro.boot.flash.locked
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("getprop ro.boot.flash.locked", true);
System.out.println("ro.boot.flash.locked:" + commandResult.toString());
back = "0".equals(commandResult.successMsg);
if (back) {
sb.append("ro.boot.flash.locked=0\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
是否selinux处于宽容模式
public static boolean isSELinuxInPermissiveMode() {
boolean back = false;
try {
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("getenforce", true);
// "permissive" 表示 SELinux 处于宽容模式
back = "Permissive".equals(commandResult.successMsg);
if (back) {
sb.append("getenforce-Permissive\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
VPN检测
public static boolean
isVPN() {
boolean Back = false;
try {
Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
if (niList != null) {
Iterator it = Collections.list(niList).iterator();
while (it.hasNext()) {
NetworkInterface intf = (NetworkInterface) it.next();
if (intf.isUp() && intf.getInterfaceAddresses().size() != 0 && ("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName()))) {
ToolUtil.Log("Risk has been detected", "VPN InterfaceAddresses " + intf.getName());
sb.append("检测到可疑参数:" + intf.getName() + "\n");
return true;
}
}
}
return false;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
是否开启代理
public static boolean isWifiProxy() {
try {
String proxyAddress;
int proxyPort;
boolean IS_ICS_OR_LATER = Build.VERSION.SDK_INT >= 14;
if (IS_ICS_OR_LATER) {
proxyAddress = System.getProperty("http.proxyHost");
String portStr = System.getProperty("http.proxyPort");
proxyPort = Integer.parseInt(portStr != null ? portStr : "-1");
} else {
proxyAddress = Proxy.getHost(context);
proxyPort = Proxy.getPort(context);
}
boolean b = ((TextUtils.isEmpty(proxyAddress) || proxyPort == -1) ? false : true);
if (b) {
ToolUtil.Log("openProxy", "WifiProxy proxyAddress=" + proxyAddress + "\tproxyPort=" + proxyPort);
sb.append("检测到可疑IP:" + String.format("ip=%s.prot=%s", proxyAddress, proxyPort) + "\n");
}
return b;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
是否应用多开
public static boolean isMulti_Launching_Apps() {
boolean Back = false;
try {
//uid=10000-19999
String filesdir = context.getFilesDir().getPath();
int uid = Process.myUid();
if (!filesdir.startsWith("/data/user/0/")) {
ToolUtil.Log("multi-launching apps", "filesdir error:" + filesdir);
sb.append("检测到可疑应用地址:" + filesdir + "\n");
Back = true;
}
if (!(uid >= 10000 && uid <= 19999)) {
ToolUtil.Log("multi-launching apps", "uid error:" + uid);
sb.append("检测到可疑进程id:" + uid + "\n");
Back = true;
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return Back;
}
是否开启无障碍服务
public static boolean isAccessibilitySettingsOn() {
try {
int accessibilityEnabled = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), "accessibility_enabled");
boolean isopen = (accessibilityEnabled == 1);
if (isopen) {
sb.append("检测到accessibility_enabled=1\n");
ToolUtil.Log("accessiblity", "open accessiblity");
}
return isopen;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
全部代码如下:
package com.example.risk.util;
import android.content.Context;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class RiskUtils {
public static StringBuilder sb=new StringBuilder();
//构造方法
//com.example.risk.util.RiskUtils getDeviceRisk Context
public static List<String> getDeviceRisk(Context context) {
// Log.e("Xposed测试:","Xposed测试",new Throwable());
DeviceRiskMgr.sb=RiskUtils.sb;
ToolUtil.sb=RiskUtils.sb;
DeviceRiskMgr.context=context;
sb.append("检测详情:"+"\n\n");
List<String> risks = new ArrayList<>();
if (DeviceRiskMgr.isVPN()) {
ToolUtil.Log("手机使用了VPN");
risks.add("vpn");
}
if (DeviceRiskMgr.isWifiProxy()) {
ToolUtil.Log("开启了网络代理");
risks.add("openProxy");
}
if (DeviceRiskMgr.isSimulator()) {
ToolUtil.Log("检测到模拟器");
risks.add("simulator");
}
if (DeviceRiskMgr.isMulti_Launching_Apps()) {
ToolUtil.Log("检测到应用多开");
risks.add("multi-launching apps");
}
if (DeviceRiskMgr.isRoot()) {
ToolUtil.Log("手机已root");
risks.add("root");
}
if (DeviceRiskMgr.isXposed()) {
ToolUtil.Log("安装了xpose");
risks.add("xpose");
}
if (DeviceRiskMgr.isModel_System()) {
ToolUtil.Log("机型和系统判定异常");
risks.add("model_system");
}
if (DeviceRiskMgr.isTool()) {
ToolUtil.Log("截图工具和模拟点击工具");
risks.add("tool");
}
if (DeviceRiskMgr.isAccessibilitySettingsOn()) {
ToolUtil.Log("开启了无障碍服务");
risks.add("accessiblity");
}
if (DeviceRiskMgr.isFridaInjected()) {
ToolUtil.Log("发现Frida特征");
risks.add("frida");
}
if (DeviceRiskMgr.isSIM()) {
ToolUtil.Log("发现SIM有异常");
risks.add("sim");
}
if (DeviceRiskMgr.isModification()) {
ToolUtil.Log("发现改机软件");
risks.add("modification");
}
if (DeviceRiskMgr.isSELinuxInPermissiveMode()) {
ToolUtil.Log("selinux处于宽容模式");
risks.add("selinux");
}
if (DeviceRiskMgr.isBlOpen()) {
ToolUtil.Log("BL已解锁");
risks.add("blopen");
}
if (DeviceRiskMgr.isMagisk()) {
ToolUtil.Log("找到Magisk");
risks.add("magisk");
}
return risks;
}
}
package com.example.risk.util;
import android.content.Context;
import android.net.Proxy;
import android.os.Build;
import android.os.Process;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import com.example.risk.tool.ShellUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class DeviceRiskMgr {
public static Context context;
public static StringBuilder sb;
public DeviceRiskMgr() {
}
/**
环境检测:
一、HOOK环境
在libNetHTProtect.so中主要检测了crc校验,还有frida和Xposed的一些特征:
<p>
1、检测frida的特征:
进程/proc/self/fd/目录,寻找是否存在关键字 linjector
/data/local/tmp/下是否存在re.frida.server
*/
public static boolean isFridaInjected() {
boolean back = false;
try {
String files = ToolUtil.getFiles("/proc/self/fd/");
if (files != null && files.length() > 0 && files.contains("linjector")) {
DeviceRiskMgr.sb.append("发现Frida特征: /proc/self/fd/ linjector");
back = true;
}
files = ToolUtil.getFiles("/data/local/tmp/");
if (files != null && files.length() > 0 && files.contains("re.frida.server")) {
DeviceRiskMgr.sb.append("发现Frida特征: /data/local/tmp/ re.frida.server");
back = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false; // 未发现Frida特征
}
/**
2、检测Xposed特征:
方法1:检测下列文件或文件路径是否存在:
"/sbin/.magisk/modules/riru_lsposed","/data/adb/lspd","/sbin/.magisk/modules/zygisk_lsposed","/sbin/.magisk/modules/riru_edxposed","/data/misc/riru/modules/edxp","/data/adb/riru/modules/edxp.prop","/sbin/.magisk/modules/taichi","/data/misc/taichi","/sbin/.magisk/modules/dreamland","/data/misc/riru/modules/dreamland","/data/adb/riru/modules/dreamland","/system/bin/app_process.orig","/system/xposed.prop","/system/framework/XposedBridge.jar","libxposed_art.so","libxposed_art.so",".no_orig","/system/lib64/","libxposed_art.so","/system/lib64/","libxposed_art.so",".no_orig","/system/bin/app_process_zposed","/system/framework/ZposedBridge.jar","/system/lib/","libzposed_art.so"
方法2:Hook loadClass加载类,检查程序加载的Class中是否包含名为de.robv.android.xposed.XposedBridge的类名路径。
方法3:遍历/data/data/目录,寻找有无以下包名:
de.robv.android.xposed.installer #Xposed框架 \\org.meowcat.edxposed.manager #EdXposed框架\\com.tsng.hidemyapplist #隐藏应用列表\\com.tsng.hidemyroot #隐藏Root//org.lsposed.manager #LSPosed框架\\ //me.weishu.exp #VirtualXposed 太极//top.canyie.dreamland.manager #VirtualXposed 夢境 //io.va.exposed #VirtualXposed 夢境 //io.va.exposed64 #VirtualXposed 夢境 //io.virtualapp #VirtualApp //io.virtualapp.sandvxposed64 #VirtualApp
*/
public static boolean isXposed() {
boolean back = false;
try {
List<String> files = Arrays.asList("/sbin/.magisk/modules/riru_lsposed", "/data/adb/lspd", "/sbin/.magisk/modules/zygisk_lsposed", "/sbin/.magisk/modules/riru_edxposed", "/data/misc/riru/modules/edxp", "/data/adb/riru/modules/edxp.prop", "/sbin/.magisk/modules/taichi", "/data/misc/taichi", "/sbin/.magisk/modules/dreamland", "/data/misc/riru/modules/dreamland", "/data/adb/riru/modules/dreamland", "/system/bin/app_process.orig", "/system/xposed.prop", "/system/framework/XposedBridge.jar", "/system/lib/libxposed_art.so", "/system/lib/.no_orig", "/system/lib64/libxposed_art.so", "/system/lib64/.no_orig", "/system/bin/app_process_zposed", "/system/framework/ZposedBridge.jar", "/system/lib/libzposed_art.so");
if (ToolUtil.checkFiles("xpose", files)) back = true;
files = Arrays.asList("de.robv.android.xposed.installer", "org.meowcat.edxposed.manager", "com.tsng.hidemyapplist", "com.tsng.hidemyroot", "org.lsposed.manager", "me.weishu.exp", "top.canyie.dreamland.manager", "io.va.exposed", "io.va.exposed64", "io.virtualapp", "io.virtualapp.sandvxposed64");
if (ToolUtil.isRunningApk(context, files)) back = true;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
/**
* 3、libc的CRC校验
* 拿到proc/self/maps中libc.so的基地址,并计算ELF文件中.text+.rodata+.eh_frame+.eh_frame_hdr 段的CRC校验值。
* <p>
二、机型和系统判定
1、检测是否是lineageOS系统,这个sdk主要的检测方法是:
1、查找是否存在特征文件:
/system/framework/org.lineageos.platform.jar
/system/framework/org.lineageos.hardware.jar
2、检测systemprop中是否存在:ro.lineage.build.version
2、检测是否是OpenHarmony系统,检测方法是:
检测systemprop中是否存在:ro.build.ohos.devicetype
3、检测品牌机系统和设备能否对应,检测方法是:
遍历/system/framework/下所有以.jar结尾的文件名称,与机型字符串进行比较(strcasestr比较,不区分大小写)
例如在vivo手机内,/system/framework/下存在以下文件,文件名中包含vivo:
*/
//机型和系统判定
public static boolean isModel_System() {
boolean back = false;
try {
//1、检测是否是lineageOS系统,
String files = ToolUtil.getFiles("/system/framework/");
if (files != null && files.length() > 0 && files.contains("org.lineageos.platform.jar")) {
sb.append("存在特征文件/system/framework/org.lineageos.platform.jar\n");
sb.append("检测是lineageOS系统\n");
}
if (files != null && files.length() > 0 && files.contains("org.lineageos.hardware.jar")) {
sb.append("存在特征文件/system/framework/org.lineageos.hardware.jar\n");
sb.append("检测是lineageOS系统\n");
}
if (ToolUtil.isProp("device model identification", "ro.lineage.build.version"))
back = true;
//2、检测是否是OpenHarmony系统
if (ToolUtil.isProp("system identification", "ro.build.ohos.devicetype"))
back = true;
//3.
boolean isBrand = false;
String brand = Build.MANUFACTURER.toLowerCase();
List<String> jarFiles = ToolUtil.getJarFiles("/system/framework/");
for (String jarFile : jarFiles) {
if (ToolUtil.containsBrand(jarFile, brand)) {
isBrand = true;
}
}
if (!isBrand) {
DeviceRiskMgr.sb.append("机型:" + brand + "\n");
DeviceRiskMgr.sb.append("未在/system/framework/下发现有关机型的以.jar结尾的文件名称\n");
back = true;
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
/**
* 三、Bootloader解锁状态
* 检测bootloader是否已解锁。
* <p>
* 方法1:检测props,主要检测项:
* 1、检测ro.boot.verifiedbootstate的值是否是orange
* 2、检测ro.secureboot.lockstate的值是否是unlocked
* 3、检测vendor.boot.vbmeta.device_state的值是否是unlocked
* 4、检测vendor.boot.verifiedbootstate的值是否是orange
* 5、检测ro.boot.vbmeta.device_state的值是否是unlocked
* 6、检测ro.boot.flash.locked的值是否是unlocked
* 方法2:获取sys.oem_unlock_allowed的值
* <p>
* 四、SIM卡
* 这个可以检测SIM卡是否存在,获取SIM卡的网络类型,SIM卡的ICCID等。
* <p>
* 1.检测SIM卡是否存在,这个一般是读取props,获取gsm.sim.state这个的属性
* <p>
* 2.获取SIM卡的网络运营商,通过系统服务TELEPHONY_SERVICE,然后调用getSubscriberId获取IMSIString,然后判断前5位:
* <p>
* 中国地区的运营商以及对应的号段见下表:
* 中国移动 :46000,46002,46004,46007,46008
* 中国联通 :46001,46006,46009,46010
* 中国电信 :46003,46005,46011,46012
* 中国广电 :46015
* 港澳地区:
* 中国移动(香港) :45412,45413,45430
* 中国电信(香港) :45407
* 中国电信(澳门) :45502,45507
*/
public static boolean isSIM() {
boolean back = false;
try {
Map<String, String> map = new HashMap<String, String>() {
{
put("46000", "中国移动");
put("46002", "中国移动");
put("46004", "中国移动");
put("46008", "中国移动");
put("46001", "中国联通");
put("46006", "中国联通");
put("46009", "中国联通");
put("46010", "中国联通");
put("46003", "中国电信");
put("46005", "中国电信");
put("46011", "中国电信");
put("46012", "中国电信");
put("45412", "中国移动(香港)");
put("45413", "中国移动(香港)");
put("45430", "中国移动(香港)");
put("45407", "中国电信(香港)");
put("45502", "中国电信(澳门)");
put("45507", "中国电信(澳门)");
}
};
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
boolean b = telephonyManager.hasIccCard();
if (b) {
String substring = telephonyManager.getSimSerialNumber();
if (map.containsKey(substring)) {
DeviceRiskMgr.sb.append("国内运营商:" + substring + "--" + map.get(substring) + "\n");
} else {
DeviceRiskMgr.sb.append("国外运营商:" + substring + "\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
/**
五、截图工具和模拟点击工具
1.检测运行的服务中是否存在minicap、minitouch、stfservice、minitouchagent、stfagent、testminicap关键字。
2.检查/data/local/tmp/有无以下文件或文件目录:
"minicap.so","minicap","minitouch","mini","mini/minicap","oat/arm64/scrcpy-server.odex","vysor.pwd","mobile_info.properties","tc/mobileagent","tc/input3.sh","tc/mainputjar7","com.cyjh.mobileanjian.id","com.cyjh.mobileanjianen.id","juejinAzykb/","minicap.so","juejinAzykb/TouchService.jar","mqc-scrcpy.jar","uiautomator-stub.jar","cloudtestig/cloudscreen","cloudtesting/touchserver","txysvr.apk","yijianwanservice.apk","screen-shread10x64.so","screen-shread5x32.so","maxpresent.jar","libtxysvr.so"
3.检查应用安装列表
检查有没有安装下列模拟点击的应用:
"com.cygery.repetitouch.pro","com.cyjh.mobileanjian","com.touchsprite.android","com.cjzs123.zhushou","com.touchspriteent.android","com.zidongdianji","org.autojs.autojspro","org.autojs.autojs","com.zdanjian.zdanjian","com.zdnewproject","com.ifengwoo.zyjdkj","com.angel.nrzs","com.cyjh.mobileanjian.vip","com.shumai.shudaxia","fun.tooling.clicker.cn","com.dianjiqi","com.miaodong.autoactionssss","com.mxz.wxautojiafujinderen","com.touchelf.app","com.stardust.scriptdroid","com.adinall.autoclick","com.i_cool.auto_clicker","com.kongshan.aidianji","com.xptech.catclicker","com.tingniu.autoclick","com.yicu.yichujifa","com.smallyin.autoclick","com.ksxkq.autoclick","com.x2.clicker","com.scott.autoclickhelper","com.auyou.auyouwzs",
检查有没有安装下列截图应用:
"com.github.uiautomator","com.github.uiautomator2","com.sigma_rt.totalcontrol","com.genymobile.scrcpy"
*/
//截图工具和模拟点击工具
public static boolean isTool() {
boolean Back = false;
try {
//1.检测运行的服务中是否存在minicap、minitouch、stfservice、minitouchagent、stfagent、testminicap关键字。
List<String> packges = ToolUtil.getPackges(context);
if (packges != null && packges.size() > 0) {
String s = packges.toString();
List<String> keywords = Arrays.asList("minicap", "minitouch", "stfservice", "minitouchagent", "stfagent", "testminicap");
for (String re : keywords) {
if (s.contains(re)) {
sb.append("检测运行的服务中是否存在" + re + "关键字\n");
Back = true;
}
}
}
//2.检查/data/local/tmp/有无以下文件或文件目录:
List<String> file = Arrays.asList("minicap.so", "minicap", "minitouch", "mini", "mini/minicap", "oat/arm64/scrcpy-server.odex", "vysor.pwd", "mobile_info.properties", "tc/mobileagent", "tc/input3.sh", "tc/mainputjar7", "com.cyjh.mobileanjian.id", "com.cyjh.mobileanjianen.id", "juejinAzykb/", "minicap.so", "juejinAzykb/TouchService.jar", "mqc-scrcpy.jar", "uiautomator-stub.jar", "cloudtestig/cloudscreen", "cloudtesting/touchserver", "txysvr.apk", "yijianwanservice.apk", "screen-shread10x64.so", "screen-shread5x32.so", "maxpresent.jar", "libtxysvr.so");
for (int i = 0; i < file.size(); i++)
file.set(i, "/data/local/tmp/" + file.get(i));
if (ToolUtil.checkFiles("tool", file))
Back = true;
//3.检查应用安装列表
//检查有没有安装下列模拟点击的应用
List<String> list = Arrays.asList("com.cygery.repetitouch.pro", "com.cyjh.mobileanjian", "com.touchsprite.android", "com.cjzs123.zhushou", "com.touchspriteent.android", "com.zidongdianji", "org.autojs.autojspro", "org.autojs.autojs", "com.zdanjian.zdanjian", "com.zdnewproject", "com.ifengwoo.zyjdkj", "com.angel.nrzs", "com.cyjh.mobileanjian.vip", "com.shumai.shudaxia", "fun.tooling.clicker.cn", "com.dianjiqi", "com.miaodong.autoactionssss", "com.mxz.wxautojiafujinderen", "com.touchelf.app", "com.stardust.scriptdroid", "com.adinall.autoclick", "com.i_cool.auto_clicker", "com.kongshan.aidianji", "com.xptech.catclicker", "com.tingniu.autoclick", "com.yicu.yichujifa", "com.smallyin.autoclick", "com.ksxkq.autoclick", "com.x2.clicker", "com.scott.autoclickhelper", "com.auyou.auyouwzs");
if (ToolUtil.isRunningApk(context, list)) {
sb.append("检测到模拟点击应用\n");
}
// 检查有没有安装下列截图应用:
list = Arrays.asList("com.github.uiautomator", "com.github.uiautomator2", "com.sigma_rt.totalcontrol", "com.genymobile.scrcpy");
if (ToolUtil.isRunningApk(context, list)) {
sb.append("检测到截图应用\n");
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return Back;
}
/**
六、模拟器
扫描常见的模拟器特征,主要检测的方法是:
1、是否存在以下文件目录:
"/system/bin/ldinit","/system/bin/ldmountsf","/system/lib/libldutils.so","/system/bin/microvirt-prop","/system/lib/libdroid4x.so","/system/bin/windroyed","/system/lib/libnemuVMprop.so","/system/bin/microvirtd","/system/bin/nox-prop","/system/lib/libnoxspeedup.so","/data/property/persist.nox.simulator_version","/data/misc/profiles/ref/com.bignox.google.installer","/data/misc/profiles/ref/com.bignox.app.store.hd","/system/bin/ttVM-prop","/system/bin/droid4x-prop","/system/bin/duosconfig","/system/etc/xxzs_prop.sh","/system/etc/mumu-configs/device-prop-configs/mumu.config","/boot/bstsetup.env","/boot/bstmods","/system/xbin/bstk","/data/bluestacks.prop","/data/data/com.anrovmconfig","/data/data/com.bluestacks.appmart","/data/data/com.bluestacks.home","/data/data/com.microvirt.market","/dev/nemuguest","/data/data/com.microvirt.toolst","/data/data/com.mumu.launcher","/data/data/com.mumu.store","/data/data/com.netease.mumu.cloner","/system/bin/bstshutdown","/sys/module/bstinput","/sys/class/misc/bstXqpb","/system/phoenixos","/xbin/phoenix_compat","/init.dundi.rc","/system/etc/init.dundi.sh","/data/data/com.ddmnq.dundidevhelper","/init.andy.cloud.rc","/system/bin/xiaopiVM-prop","/system/bin/XCPlayer-prop","/system/lib/liblybox_prop.so","/system/bin/tencent_virtual_input","/vendor/bin/init.tencent.sh","/data/youwave_id","/dev/vboxguest","/dev/vboxuser","/sys/bus/pci/drivers/vboxguest","/sys/class/bdi/vboxsf-c","/sys/class/misc/vboxguest","/sys/class/misc/vboxuser","/sys/devices/virtual/bdi/vboxsf-c","/sys/devices/virtual/misc/vboxguest","/sys/devices/virtual/misc/vboxuser","/sys/module/vboxguest","/sys/module/vboxsf","/sys/module/vboxvideo","/system/bin/androVM-vbox-sf","/system/bin/androVM_setprop","/system/bin/get_androVM_host","/system/bin/mount.vboxsf","/system/etc/init.androVM.sh","/system/etc/init.buildroid.sh","/system/lib/vboxguest.ko","/system/lib/vboxsf.ko","/system/lib/vboxvideo.ko","/system/xbin/mount.vboxsf","/dev/goldfish_pipe","/sys/devices/virtual/misc/goldfish_pipe","/sys/module/goldfish_audio","/sys/module/goldfish_battery","/sys/module/kvm_intel/","/sys/module/kvm_amd/","/init.android_x86_64.rc","/init.android_x86.rc","/init.androidVM_x86.rc","/init.intel.rc","/init.vbox2345_x86.rc"
2、system.prop下是否存在以下字段特征:
"init.svc.microvirtd","bst.version","ro.phoenix.version.code","ro.phoenix.version.codename","init.svc.droid4x","microvirt.memu_version","microvirt.imsi","microvirt.simserial","ro.px.version.build","ro.phoenix.os.branch","init.svc.su_kpbs_daemon","init.svc.noxd","init.svc.ttVM_x86-setup","init.svc.xxkmsg","ro.bild.remixos.version","microvirt.mut","init.svc.ldinit","sys.tencent.os_version","sys.tencent.android_id","ro.genymotion.version","init.svc.pkVM_x86-setup","ro.andy.version","ro.build.version.release","ro.product.model","ro.product.brand","ro.boot.bootloader","ro.build.version.securitypatch","ro.build.version.incremental","gsm.version.baseband","gsm.version.ril-impl","ro.build.fingerprint","ro.build.description","ro.build.product","ro.boot.vbmeta.digest","ro.hardware","ro.product.name","ro.product.board","ro.recovery_id","ro.expect.recovery_id","ro.board.platform","ro.product.manufacturer","ro.product.device","sys.usb.state","ro.setupwizard.mode","ro.build.id","ro.build.tags","ro.build.type","ro.debuggable",
3.检查挂载点,是否存在以下目录:
"/mnt/shared/Sharefolder","/tiantian.conf","/data/share1","/hardware_device.conf","/mnt/shared/products","/mumu_hardware.conf","/Andy.conf","/mnt/windows/BstSharedFolder","/bst.conf","/mnt/shared/Applications","/ld.conf"
检查挂载点,检查/proc/mounts中是否存在vboxsf字段.
4.检查是否安装了虚拟机软件:
1.VMOS虚拟机
方法1:运行服务查找:tomq_MANAGER_SERVICE
方法2:ROOT_DIR查找VMOS_SYS_NUM
方法3:/proc/self/root/data/data/查找包名:“com.vmos.app”、“com.vmos.pro”、“com.vmos.ggp”
方法4:props查找:vmprop.androidid、vmprop.dev_ashmem、vmprop.ip、ro.vmos.simplest.rom
2.X8沙箱
方法1:props查找:ro.x8.version、ro.x8.uuid
方法2:查找文件目录:/x8/config/root.pkg.blacklist、/x8/config/full_vm是否存在
3.51虚拟机
/proc/self/root/data/data/查找包名:“com.f1player”、“com.f1player.play”
4.虚拟精灵和虚拟大师
/proc/self/root/data/data/查找包名:com.pspace.vandroid、com.yiqiang.xmaster
*/
//是否模拟器 OK
public static boolean isSimulator() {
boolean back = false;
try {
//是否存在以下文件目录:
List<String> Mult_File = Arrays.asList("/x8/config/root.pkg.blacklist", "/x8/config/full_vm", "/system/bin/ldinit", "/system/bin/ldmountsf", "/system/lib/libldutils.so", "/system/bin/microvirt-prop", "/system/lib/libdroid4x.so", "/system/bin/windroyed", "/system/lib/libnemuVMprop.so", "/system/bin/microvirtd", "/system/bin/nox-prop", "/system/lib/libnoxspeedup.so", "/data/property/persist.nox.simulator_version", "/data/misc/profiles/ref/com.bignox.google.installer", "/data/misc/profiles/ref/com.bignox.app.store.hd", "/system/bin/ttVM-prop", "/system/bin/droid4x-prop", "/system/bin/duosconfig", "/system/etc/xxzs_prop.sh", "/system/etc/mumu-configs/device-prop-configs/mumu.config", "/boot/bstsetup.env", "/boot/bstmods", "/system/xbin/bstk", "/data/bluestacks.prop", "/data/data/com.anrovmconfig", "/data/data/com.bluestacks.appmart", "/data/data/com.bluestacks.home", "/data/data/com.microvirt.market", "/dev/nemuguest", "/data/data/com.microvirt.toolst", "/data/data/com.mumu.launcher", "/data/data/com.mumu.store", "/data/data/com.netease.mumu.cloner", "/system/bin/bstshutdown", "/sys/module/bstinput", "/sys/class/misc/bstXqpb", "/system/phoenixos", "/xbin/phoenix_compat", "/init.dundi.rc", "/system/etc/init.dundi.sh", "/data/data/com.ddmnq.dundidevhelper", "/init.andy.cloud.rc", "/system/bin/xiaopiVM-prop", "/system/bin/XCPlayer-prop", "/system/lib/liblybox_prop.so", "/system/bin/tencent_virtual_input", "/vendor/bin/init.tencent.sh", "/data/youwave_id", "/dev/vboxguest", "/dev/vboxuser", "/sys/bus/pci/drivers/vboxguest", "/sys/class/bdi/vboxsf-c", "/sys/class/misc/vboxguest", "/sys/class/misc/vboxuser", "/sys/devices/virtual/bdi/vboxsf-c", "/sys/devices/virtual/misc/vboxguest", "/sys/devices/virtual/misc/vboxuser", "/sys/module/vboxguest", "/sys/module/vboxsf", "/sys/module/vboxvideo", "/system/bin/androVM-vbox-sf", "/system/bin/androVM_setprop", "/system/bin/get_androVM_host", "/system/bin/mount.vboxsf", "/system/etc/init.androVM.sh", "/system/etc/init.buildroid.sh", "/system/lib/vboxguest.ko", "/system/lib/vboxsf.ko", "/system/lib/vboxvideo.ko", "/system/xbin/mount.vboxsf", "/dev/goldfish_pipe", "/sys/devices/virtual/misc/goldfish_pipe", "/sys/module/goldfish_audio", "/sys/module/goldfish_battery", "/sys/module/kvm_intel/", "/sys/module/kvm_amd/", "/init.android_x86_64.rc", "/init.android_x86.rc", "/init.androidVM_x86.rc", "/init.intel.rc", "/init.vbox2345_x86.rc");
//sb.append("\n是否存在以下文件目录:");
if (ToolUtil.checkFiles("simulator", Mult_File))
back = true;
//system.prop下是否存在以下字段特征:
List<String> Mult_Prop = Arrays.asList("vmprop.androidid", "vmprop.dev_ashmem", "vmprop.ip", "ro.vmos.simplest.rom", "ro.x8.version", "ro.x8.uuid", "init.svc.microvirtd", "bst.version", "ro.phoenix.version.code", "ro.phoenix.version.codename", "init.svc.droid4x", "microvirt.memu_version", "microvirt.imsi", "microvirt.simserial", "ro.px.version.build", "ro.phoenix.os.branch", "init.svc.su_kpbs_daemon", "init.svc.noxd", "init.svc.ttVM_x86-setup", "init.svc.xxkmsg", "ro.bild.remixos.version", "microvirt.mut", "init.svc.ldinit", "sys.tencent.os_version", "sys.tencent.android_id", "ro.genymotion.version", "init.svc.pkVM_x86-setup", "ro.andy.version", "ro.build.version.release", "ro.product.model", "ro.product.brand", "ro.boot.bootloader", "ro.build.version.securitypatch", "ro.build.version.incremental", "gsm.version.baseband", "gsm.version.ril-impl", "ro.build.fingerprint", "ro.build.description", "ro.build.product", "ro.boot.vbmeta.digest", "ro.hardware", "ro.product.name", "ro.product.board", "ro.recovery_id", "ro.expect.recovery_id", "ro.board.platform", "ro.product.manufacturer", "ro.product.device", "sys.usb.state", "ro.setupwizard.mode", "ro.build.id", "ro.build.tags", "ro.build.type", "ro.debuggable");
// sb.append("\nsystem.prop下是否存在以下字段特征:");
if (ToolUtil.checkProps("simulator", Mult_Prop))
back = true;
//3.检查挂载点,是否存在以下目录:
//检查挂载点,检查/proc/mounts中是否存在vboxsf字段.
List<String> list = Arrays.asList("/mnt/shared/Sharefolder", "/tiantian.conf", "/data/share1", "/hardware_device.conf", "/mnt/shared/products", "/mumu_hardware.conf", "/Andy.conf", "/mnt/windows/BstSharedFolder", "/bst.conf", "/mnt/shared/Applications", "/ld.conf");
if (ToolUtil.checkFiles("simulator", list)) back = true;
String files1 = ToolUtil.getFiles("/proc/mounts");
if (files1 != null && files1.length() > 0 && files1.contains("vboxsf")) {
sb.append("检查/proc/mounts中是否存在vboxsf字段\n");
back = true;
}
// 4.检查是否安装了虚拟机软件:
String files = ToolUtil.getFiles("/proc/self/root/data/data/");
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.vmos.app", "com.vmos.pro", "com.vmos.ggp");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与VMOS虚拟机相关包名:" + re + "\n");
back = true;
}
}
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.f1player", "com.f1player.play");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与51虚拟机相关包名:" + re + "\n");
back = true;
}
}
if (files != null && files.length() > 0) {
List<String> list1 = Arrays.asList("com.pspace.vandroid", "com.yiqiang.xmaster");
for (String re : list1)
if (files.contains(re)) {
sb.append("发现与虚拟精灵和虚拟大师相关包名:" + re + "\n");
back = true;
}
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
/**
七、改机软件
1.检测是否安装了改机软件:
检查包名是否存在:
"com.yztc.studio.plugin","com.soft.apk008v","com.uwish.app","zpp.wjy.xxsq","com.bigsing.changer","zap.fh.wipe","com.sollyu.xposed.hook.model","com.soft.apk008Tool","com.doubee.ig","com.variable.apkhook","com.addeasy.fastest","com.xenice.mask","com.shyl.artifact","com.android1500.androidfaker"
2.检查/dev/wgzs目录下的内容是否存在,若存在则获取值:
"wg.cust.config.phone.id","wg.cust.s_android_id","wg.cust.sys.prop.filter","wg.cust.config.phone.imeimackey","wg.cust.config.phone.imei","wg.cust.config.pkg.name","wg.cust.destUids"
*/
public static boolean isModification() {
boolean back = false;
try {
List<String> list = Arrays.asList("com.yztc.studio.plugin", "com.soft.apk008v", "com.uwish.app", "zpp.wjy.xxsq", "com.bigsing.changer", "zap.fh.wipe", "com.sollyu.xposed.hook.model", "com.soft.apk008Tool", "com.doubee.ig", "com.variable.apkhook", "com.addeasy.fastest", "com.xenice.mask", "com.shyl.artifact", "com.android1500.androidfaker");
if (ToolUtil.isRunningApk(context, list)) {
back = true;
}
list = Arrays.asList("wg.cust.config.phone.id", "wg.cust.s_android_id", "wg.cust.sys.prop.filter", "wg.cust.config.phone.imeimackey", "wg.cust.config.phone.imei", "wg.cust.config.pkg.name", "wg.cust.destUids");
String files = ToolUtil.getFiles("/dev/wgzs/");
if (files != null && files.length() > 0)
for (String re : list) {
if (files.contains(re)) {
back = true;
sb.append("检查/dev/wgzs目录存在参数:" + re + "\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
/**
八、Root和Root工具
1.包名检测,遍历/data/data/目录,寻找有无以下包名:
"com.topjohnwu.magisk","eu.chainfire.supersu","com.noshufou.android.su","com.noshufou.android.su.elite","com.koushikdutta.superuser","com.thirdparty.superuser","com.yellowes.su","com.fox2code.mmm","io.github.vvb2060.magisk","com.kingroot.kinguser","com.kingo.root","com.smedialink.oneclickroot","com.zhiqupk.root.global","com.alephzain.framaroot","io.github.huskydg.magisk","me.weishu.kernelsu"
2.检查su文件是否存在
"/su/bin/su","/sbin/su","/data/local/xbin/su","/data/local/bin/su","/data/local/su","/system/xbin/su","/system/bin/su","/system/sd/xbin/su","/system/bin/failsafe/su","/system/bin/.ext/.su","/system/etc/.installed_su_daemon","/system/etc/.has_su_daemon","/system/xbin/sugote","/system/xbin/sugote-mksh","/system/xbin/supolicy","/system/etc/init.d/99SuperSUDaemon","/system/.supersu","/product/bin/su","/apex/com.android.runtime/bin/su","/apex/com.android.art/bin/su","/system_ext/bin/su","/system/xbin/bstk/su","/system/app/SuperUser/SuperUser.apk","/system/app/Superuser.apk","/system/xbin/mu_bak","/odm/bin/su","/vendor/bin/su","/vendor/xbin/su","/system/bin/.ext/su","/system/usr/we-need-root/su","/cache/su","/data/su","/dev/su","/system/bin/cph_su","/dev/com.koushikdutta.superuser.daemon","/system/xbin/daemonsu","/sbin/.mianju","/sbin/nvsu","/system/bin/.hid/su","/system/addon.d/99-magisk.sh"
3.检查magisk相关文件是否存在
"/cache/.disable_magisk","/dev/magisk/img","/sbin/.magisk","/cache/magisk.log","/data/adb/magisk","/system/etc/init/magisk","/system/etc/init/magisk.rc","/data/magisk.apk"
4.检测Android PATH环境变量,检测path路径下是否存在“/su”
5.检测 /proc/self/maps中的内容
1、检测 /proc/self/maps 是否存在名为“/memfd:/jit-cache”的段(加载zygisk模块时(也就是liblspd.so)的时候会讲其名称设置为jit-cache,这样的话so的内存段在maps中就是/memfd:/jit-cache)
2、通过检测map表是否存在匿名的并且具有可执行属性的内存判断是否存在lsposed
3、检测栈空间[stack]的权限是否为“rw-p”
6.检测ro.build.tags的值,读取 /system/build.prop并检测ro.build.tags的值是否为“test-keys”
7.检测seLinux安全上下文,cat /proc/%d/attr/prev检测app进程的selinux安全上下文是否为“u:r:zygote:s0”
8.检查/data/local/tmp/有无以下文件
shizuku
shizuku_starter
*/
//Root检测
public static boolean isRoot() {
boolean back = false;
try {
//1.包名检测,遍历/data/data/目录,寻找有无以下包名:
List<String> list = Arrays.asList("com.topjohnwu.magisk", "eu.chainfire.supersu", "com.noshufou.android.su", "com.noshufou.android.su.elite", "com.koushikdutta.superuser", "com.thirdparty.superuser", "com.yellowes.su", "com.fox2code.mmm", "io.github.vvb2060.magisk", "com.kingroot.kinguser", "com.kingo.root", "com.smedialink.oneclickroot", "com.zhiqupk.root.global", "com.alephzain.framaroot", "io.github.huskydg.magisk", "me.weishu.kernelsu");
if (ToolUtil.isRunningApk(context, list)) back = true;
//2.检查su文件是否存在
list = Arrays.asList("/su/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/data/local/su", "/system/xbin/su", "/system/bin/su", "/system/sd/xbin/su", "/system/bin/failsafe/su", "/system/bin/.ext/.su", "/system/etc/.installed_su_daemon", "/system/etc/.has_su_daemon", "/system/xbin/sugote", "/system/xbin/sugote-mksh", "/system/xbin/supolicy", "/system/etc/init.d/99SuperSUDaemon", "/system/.supersu", "/product/bin/su", "/apex/com.android.runtime/bin/su", "/apex/com.android.art/bin/su", "/system_ext/bin/su", "/system/xbin/bstk/su", "/system/app/SuperUser/SuperUser.apk", "/system/app/Superuser.apk", "/system/xbin/mu_bak", "/odm/bin/su", "/vendor/bin/su", "/vendor/xbin/su", "/system/bin/.ext/su", "/system/usr/we-need-root/su", "/cache/su", "/data/su", "/dev/su", "/system/bin/cph_su", "/dev/com.koushikdutta.superuser.daemon", "/system/xbin/daemonsu", "/sbin/.mianju", "/sbin/nvsu", "/system/bin/.hid/su", "/system/addon.d/99-magisk.sh");
if (ToolUtil.checkFiles("root su", list))
back = true;
//3.检查magisk相关文件是否存在
list = Arrays.asList("/cache/.disable_magisk", "/dev/magisk/img", "/sbin/.magisk", "/cache/magisk.ToolUtil.Log", "/data/adb/magisk", "/system/etc/init/magisk", "/system/etc/init/magisk.rc", "/data/magisk.apk");
if (ToolUtil.checkFiles("root magisk", list))
back = true;
//4.检测Android PATH环境变量,检测path路径下是否存在“/su”
if (new File("/path/su").exists()) {
sb.append("检测path路径下存在/su\n");
back = true;
}
// * 6.检测ro.build.tags的值,读取 /system/build.prop并检测ro.build.tags的值是否为“test-keys”
String property = System.getProperty("ro.build.tags");
if (property != null && "test-keys".equals(property)) {
sb.append("检测检测ro.build.tags的值为test-keys\n");
back = true;
}
//8.检查/data/local/tmp/有无以下文件
list = Arrays.asList("/data/local/tmp/shizuku", "/data/local/tmp/shizuku");
if (ToolUtil.checkFiles("root data", list))
back = true;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return back;
}
//也可用于检测手机是否刷了面具:
//command -v magisk
public static boolean isMagisk() {
boolean back = false;
try {
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("command -v magisk", true);
System.out.println("isMagisk:" + commandResult.toString());
back = (commandResult.successMsg != null && commandResult.successMsg.contains("magisk"));
if (back) {
sb.append("command -v magisk: " + commandResult.successMsg + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
//检测是否解锁了BL锁:(0代表已解锁,1代表未解锁)
//getprop ro.boot.flash.locked
public static boolean isBlOpen() {
boolean back = false;
try {
//getprop ro.boot.flash.locked
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("getprop ro.boot.flash.locked", true);
System.out.println("ro.boot.flash.locked:" + commandResult.toString());
back = "0".equals(commandResult.successMsg);
if (back) {
sb.append("ro.boot.flash.locked=0\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
//是否selinux处于宽容模式
public static boolean isSELinuxInPermissiveMode() {
boolean back = false;
try {
ShellUtils.CommandResult commandResult = ShellUtils.execCommand("getenforce", true);
// "permissive" 表示 SELinux 处于宽容模式
back = "Permissive".equals(commandResult.successMsg);
if (back) {
sb.append("getenforce-Permissive\n");
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
//VPN检测
public static boolean
isVPN() {
boolean Back = false;
try {
Enumeration<NetworkInterface> niList = NetworkInterface.getNetworkInterfaces();
if (niList != null) {
Iterator it = Collections.list(niList).iterator();
while (it.hasNext()) {
NetworkInterface intf = (NetworkInterface) it.next();
if (intf.isUp() && intf.getInterfaceAddresses().size() != 0 && ("tun0".equals(intf.getName()) || "ppp0".equals(intf.getName()))) {
ToolUtil.Log("Risk has been detected", "VPN InterfaceAddresses " + intf.getName());
sb.append("检测到可疑参数:" + intf.getName() + "\n");
return true;
}
}
}
return false;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
//是否开启代理 OK
public static boolean isWifiProxy() {
try {
String proxyAddress;
int proxyPort;
boolean IS_ICS_OR_LATER = Build.VERSION.SDK_INT >= 14;
if (IS_ICS_OR_LATER) {
proxyAddress = System.getProperty("http.proxyHost");
String portStr = System.getProperty("http.proxyPort");
proxyPort = Integer.parseInt(portStr != null ? portStr : "-1");
} else {
proxyAddress = Proxy.getHost(context);
proxyPort = Proxy.getPort(context);
}
boolean b = ((TextUtils.isEmpty(proxyAddress) || proxyPort == -1) ? false : true);
if (b) {
ToolUtil.Log("openProxy", "WifiProxy proxyAddress=" + proxyAddress + "\tproxyPort=" + proxyPort);
sb.append("检测到可疑IP:" + String.format("ip=%s.prot=%s", proxyAddress, proxyPort) + "\n");
}
return b;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
//是否多开
public static boolean isMulti_Launching_Apps() {
boolean Back = false;
try {
//uid=10000-19999
String filesdir = context.getFilesDir().getPath();
int uid = Process.myUid();
if (!filesdir.startsWith("/data/user/0/")) {
ToolUtil.Log("multi-launching apps", "filesdir error:" + filesdir);
sb.append("检测到可疑应用地址:" + filesdir + "\n");
Back = true;
}
if (!(uid >= 10000 && uid <= 19999)) {
ToolUtil.Log("multi-launching apps", "uid error:" + uid);
sb.append("检测到可疑进程id:" + uid + "\n");
Back = true;
}
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
}
return Back;
}
//是否开启无障碍服务
public static boolean isAccessibilitySettingsOn() {
try {
int accessibilityEnabled = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), "accessibility_enabled");
boolean isopen = (accessibilityEnabled == 1);
if (isopen) {
sb.append("检测到accessibility_enabled=1\n");
ToolUtil.Log("accessiblity", "open accessiblity");
}
return isopen;
} catch (Exception e) {
ToolUtil.Log(e.getMessage());
return false;
}
}
}
package com.example.risk.tool;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class ShellUtils {
private static final String TAG = "ShellAdbUtils";
// public static final String COMMAND_SU = "su"; bart
public static final String COMMAND_SU = "su";
public static final String COMMAND_SH = "sh";
public static final String COMMAND_EXIT = "exit\n";
public static final String COMMAND_LINE_END = "\n";
private ShellUtils() {
throw new AssertionError();
}
/**
* execute shell command, default return result msg
*
* @param command command
* @param isRoot whether need to run with root
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public synchronized static CommandResult execCommand(String command, boolean isRoot) {
return execCommand(new String[]{command}, isRoot, true);
}
/**
* execute shell commands
*
* @param commands command array
* @param isRoot whether need to run with root
* @param isNeedResultMsg whether need result msg
* @return <ul>
* <li>if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and
* {@link CommandResult#errorMsg} is null.</li>
* <li>if {@link CommandResult#result} is -1, there maybe some excepiton.</li>
* </ul>
*/
public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
int result = -1;
if (commands == null || commands.length == 0) {
return new CommandResult(result, null, null);
}
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
os = new DataOutputStream(process.getOutputStream());
for (String command : commands) {
if (command == null) {
continue;
}
// donnot use os.writeBytes(commmand), avoid chinese charset error
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
}
os.writeBytes(COMMAND_EXIT);
os.flush();
result = process.waitFor();
// dl command result
if (isNeedResultMsg) {
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) {
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null) {
errorMsg.append(s);
}
}
} catch (Exception e) {
Log.e(TAG, Log.getStackTraceString(e));
} finally {
try {
if (os != null) {
os.close();
}
if (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (IOException e) {
Log.e(TAG,Log.getStackTraceString(e));
}
if (process != null) {
process.destroy();
}
}
return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
: errorMsg.toString());
}
/**
* result of command
* <ul>
* <li>{@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in
* linux shell</li>
* <li>{@link CommandResult#successMsg} means success message of command result</li>
* <li>{@link CommandResult#errorMsg} means error message of command result</li>
* </ul>
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16
*/
public static class CommandResult {
/**
* result of command
**/
public int result;
/**
* success message of command result
**/
public String successMsg;
/**
* error message of command result
**/
public String errorMsg;
public CommandResult(int result) {
this.result = result;
}
public CommandResult(int result, String successMsg, String errorMsg) {
this.result = result;
this.successMsg = successMsg;
this.errorMsg = errorMsg;
}
@Override
public String toString() {
return "CommandResult{" +
"result=" + result +
", successMsg='" + successMsg + '\'' +
", errorMsg='" + errorMsg + '\'' +
'}';
}
}
}