Android 模仿器检测

打印 上一主题 下一主题

主题 1020|帖子 1020|积分 3060

最近看到某客户端有一个检测模仿器的方法,我正常手机结果被判定是模仿器了,很好奇,于是找了一下原因。
广泛检测代码如下:

  1. public boolean isEmulator() {
  2.     String url = "tel:" + "123456";
  3.     Intent intent = new Intent();
  4.     intent.setData(Uri.parse(url));
  5.     intent.setAction(Intent.ACTION_DIAL);
  6.     // 是否可以处理跳转到拨号的 Intent
  7.     boolean canResolveIntent = intent.resolveActivity(mContext.getPackageManager()) != null;
  8.     return Build.FINGERPRINT.startsWith("generic")
  9.         || Build.FINGERPRINT.toLowerCase().contains("vbox")
  10.         || Build.FINGERPRINT.toLowerCase().contains("test-keys")
  11.         || Build.MODEL.contains("google_sdk")
  12.         || Build.MODEL.contains("Emulator")
  13.         || Build.SERIAL.equalsIgnoreCase("unknown")
  14.         || Build.SERIAL.equalsIgnoreCase("android")
  15.         || Build.MODEL.contains("Android SDK built for x86")
  16.         || Build.MANUFACTURER.contains("Genymotion")
  17.         || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
  18.         || "google_sdk".equals(Build.PRODUCT)
  19.         || ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
  20.             .getNetworkOperatorName().toLowerCase().equals("android")
  21.         || !canResolverIntent;
  22. }
复制代码
这个代码检测模仿器有两个问题:
1、拨号检测,Android10.0及以上均为false
2、Build.SERIAL,Android8.0以上均为unknown
这导致8.0以上体系均会被误判
推荐模仿器检测方法:

设备信息检测代码:

  1. private static final String[] known_numbers = {"15555215554", "15555215556", "15555215558", "15555215560", "15555215562", "15555215564", "15555215566", "15555215568", "15555215570", "15555215572", "15555215574", "15555215576", "15555215578", "15555215580", "15555215582", "15555215584",};
  2. private boolean detectEmulator() {
  3.         if (Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.startsWith("unknown")
  4.                 || Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator")
  5.                 || Build.MODEL.contains("Android SDK built for x86") || Build.MANUFACTURER.contains("Genymotion")
  6.                 || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
  7.                 || "google_sdk".equals(Build.PRODUCT)) {
  8.             return true;
  9.         }
  10.         if (Build.PRODUCT.equals("sdk") || Build.PRODUCT.equals("sdk_x86")
  11.                 || Build.PRODUCT.equals("vbox86p") || Build.PRODUCT.equals("emulator")) {
  12.             return true;
  13.         }
  14.         if (Build.BOARD == null) {
  15.             return true;
  16.         }
  17.         if (Build.BOARD.equals("unknown")
  18.                 || Build.BOARD.contains("android")
  19.                 || Build.BOARD.contains("droid")) {
  20.             return true;
  21.         }
  22.         if (Build.DEVICE == null) {
  23.             return true;
  24.         }
  25.         if (Build.DEVICE.equals("unknown")
  26.                 || Build.DEVICE.contains("android")
  27.                 || Build.DEVICE.contains("droid")) {
  28.             return true;
  29.         }
  30.         if (Build.HARDWARE == null) {
  31.             return true;
  32.         }
  33.         if (Build.HARDWARE.equals("goldfish")
  34.                 || Build.HARDWARE.equals("ranchu")
  35.                 || Build.HARDWARE.contains("ranchu")) {
  36.             return true;
  37.         }
  38.         if (Build.BRAND == null) {
  39.             return true;
  40.         }
  41.         if (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) {
  42.             return true;
  43.         }
  44.         if (Build.MANUFACTURER.equals("unknown")) {
  45.             return true;
  46.         }
  47.         if (Build.MANUFACTURER.equals("Genymotion")) {
  48.             return true;
  49.         }
  50.         if ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
  51.                 || "google_sdk".equals(Build.PRODUCT)) {
  52.             return true;
  53.         }
  54.         if (Build.PRODUCT == null) {
  55.             return true;
  56.         }
  57.         if (Build.PRODUCT.equals("sdk")
  58.                 || Build.PRODUCT.equals("sdk_x86")
  59.                 || Build.PRODUCT.equals("vbox86p")
  60.                 || Build.PRODUCT.equals("emulator")) {
  61.             return true;
  62.         }
  63.         if (Build.HARDWARE.equals("goldfish")
  64.                 || Build.HARDWARE.equals("ranchu")) {
  65.             return true;
  66.         }
  67.         if (Build.FINGERPRINT.startsWith("generic")
  68.                 || Build.FINGERPRINT.startsWith("unknown")
  69.                 || Build.MODEL.contains("google_sdk")
  70.                 || Build.MODEL.contains("Emulator")
  71.                 || Build.MODEL.contains("Android SDK built for x86")
  72.                 || Build.MANUFACTURER.contains("Genymotion")
  73.                 || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
  74.                 || "google_sdk".equals(Build.PRODUCT)) {
  75.             return true;
  76.         }
  77.         if (Build.PRODUCT == null) {
  78.             return true;
  79.         }
  80.         if (Build.PRODUCT.equals("sdk")
  81.                 || Build.PRODUCT.equals("sdk_x86")
  82.                 || Build.PRODUCT.equals("vbox86p")
  83.                 || Build.PRODUCT.equals("emulator")) {
  84.             return true;
  85.         }
  86.         if (Build.HARDWARE.equals("goldfish")
  87.                 || Build.HARDWARE.equals("ranchu")) {
  88.             return true;
  89.         }
  90.         if (new File("/dev/socket/qemud").exists()
  91.                 || new File("/dev/qemu_pipe").exists()) {
  92.             return true;
  93.         }
  94.         try {
  95.             TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
  96.             if (telephonyManager != null) {
  97.                 String deviceId = telephonyManager.getDeviceId();
  98.                 List<String> knownNumbers = Arrays.asList(known_numbers);
  99.                 if (knownNumbers.contains(deviceId)) {
  100.                     return true;
  101.                 }
  102.             }
  103.         } catch (Exception e) {
  104.         }
  105.         return false;
  106.     }
复制代码
上述代码使用了多种方法来检测设备是否为模仿器,这些方法包罗:


  • 检测 Build.FINGERPRINT 是否以 “generic” 或 “unknown” 开头
  • 检测 Build.MODEL 是否包含 “google_sdk”、“Emulator” 或 “Android SDK built for x86”
  • 检测 Build.MANUFACTURER 是否为 “Genymotion”
  • 检测 Build.PRODUCT 是否为 “sdk”、“sdk_x86”、“vbox86p” 或 “emulator”
  • 检测 Build.BOARD 是否为 “unknown” 或包含 “android” 或 “droid”
  • 检测 Build.DEVICE 是否为 “unknown” 或包含 “android” 或 “droid”
  • 检测 Build.HARDWARE 是否为 “goldfish”、“ranchu” 或包含 “ranchu”
  • 检测 Build.BRAND 是否以 “generic” 开头,且 Build.DEVICE 以 “generic” 开头
  • 检测 Build.PRODUCT 是否为 “google_sdk”
  • 检测是否存在文件 “/dev/socket/qemud” 或 “/dev/qemu_pipe”
  • 检测设备的电话号码是否为已知的模仿器电话号码
上述方法都是基于固件信息的判定,通过测试发现很多模仿器都失效,参考网上的教程,还有蓝牙、光线传感器、cpu检测,配合上面的固件信息,基本可以搞定大部门模仿器。
蓝牙检测代码:

  1. public boolean notHasBlueTooth() {
  2.     BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
  3.     if (ba == null) {
  4.         return true;
  5.     } else {
  6.         // 如果有蓝牙不一定是有效的。获取蓝牙名称,若为null 则默认为模拟器
  7.         String name = ba.getName();
  8.         if (TextUtils.isEmpty(name)) {
  9.             return true;
  10.         } else {
  11.             return false;
  12.         }
  13.     }
  14. }
复制代码
光传感器检测代码:

  1. public static Boolean notHasLightSensorManager(Context context) {
  2.     SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
  3.     Sensor sensor8 = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光
  4.     if (null == sensor8) {
  5.         return true;
  6.     } else {
  7.         return false;
  8.     }
  9. }
复制代码
CPU检测代码:

  1. public static boolean checkIsNotRealPhone() {
  2.     String cpuInfo = readCpuInfo();
  3.     if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
  4.         return true;
  5.     }
  6.     return false;
  7. }
  8. public static String readCpuInfo() {
  9.     String result = "";
  10.     try {
  11.         String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
  12.         ProcessBuilder cmd = new ProcessBuilder(args);
  13.         Process process = cmd.start();
  14.         StringBuffer sb = new StringBuffer();
  15.         String readLine = "";
  16.         BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
  17.         while ((readLine = responseReader.readLine()) != null) {
  18.             sb.append(readLine);
  19.         }
  20.         responseReader.close();
  21.         result = sb.toString().toLowerCase();
  22.     } catch (IOException ex) {
  23.     }
  24.     return result;
  25. }
复制代码
以上检测方法也不是完全可行,随着Android体系的更新,模仿器的增多,我们需要具体研究对应的一些变更来更新上述代码。
我们检测要注意一个问题,不肯定能检测出所有的模仿器,但是肯定不能误杀真机。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表