Android笔记:判断是否为模拟器(实测夜神通过)

简介: Android笔记:判断是否为模拟器(实测夜神通过)

因为不确定因素太多,最近公司需要禁止本程序在虚拟机上运行。

我网上找了好多,各种方法什么设备号,拨打电话,蓝牙设备,模拟器的检测往往是防作弊中的重要一关,这里把这两天收集到的代码写在这偏文章里,和大家进行一个简单的分享。


传统方法

传统的检测方法主要是对模拟器的IMSI、IDS、默认文件等几个方面进行检测。


(1)默认号码:

   private static String[] known_numbers = {"15555215554", "15555215556",

               "15555215558", "15555215560", "15555215562", "15555215564",

               "15555215566", "15555215568", "15555215570", "15555215572",

               "15555215574", "15555215576", "15555215578", "15555215580",

               "15555215582", "15555215584"};

1

2

3

4

5

(2)默认ID:

private static String[] known_device_ids = {"000000000000000"};

1

(3)默认IMSI:

private static String[] known_imsi_ids = {"310260000000000"};

1

(4)默认文件路径:

   private static String[] known_files = {

               "/system/lib/libc_malloc_debug_qemu.so",

               "/sys/qemu_trace",

               "/system/bin/qemu-props"};

1

2

3

4

在得知了这些信息后,只需在运行时进行检测,如果检测结果和默认值吻合,那么检测设备便是模拟器。不过随着防反作弊技术的迭代,现在很多模拟器都可以改变这些值来逃避检测,所以上述传统方法在很多时候未曾达到开发者的预期效果。


拨打电话


public boolean isEmulator() {
        String url = "tel:" + "123456";
        Intent intent = new Intent();
        intent.setData(Uri.parse(url));
        intent.setAction(Intent.ACTION_DIAL);
        // 是否可以处理跳转到拨号的 Intent
        boolean canResolveIntent = intent.resolveActivity(mContext.getPackageManager()) != null;
        return Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.toLowerCase().contains("vbox")
            || Build.FINGERPRINT.toLowerCase().contains("test-keys")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.SERIAL.equalsIgnoreCase("unknown")
            || Build.SERIAL.equalsIgnoreCase("android")
            || Build.MODEL.contains("Android SDK built for x86")
            || Build.MANUFACTURER.contains("Genymotion")
            || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
            || "google_sdk".equals(Build.PRODUCT)
            || ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
                .getNetworkOperatorName().toLowerCase().equals("android")
            || !canResolverIntent;

光传感器

/**
 * 判断是否存在光传感器来判断是否为模拟器
 * 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
 * @return true 为模拟器
 */
public static Boolean notHasLightSensorManager(Context context) {
    SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
    Sensor sensor8 = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光
    if (null == sensor8) {
        return true;
    } else {
        return false;
    }
}

蓝牙

    /*
     *判断蓝牙是否有效来判断是否为模拟器
     *返回:true 为模拟器
     */
    public static boolean notHasBlueTooth() {
        BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
        if (ba == null) {
            return true;
        } else {
            // 如果有蓝牙不一定是有效的。获取蓝牙名称,若为null 则默认为模拟器
            String name = ba.getName();
            if (TextUtils.isEmpty(name)) {
                return true;
            } else {
                return false;
            }
        }
    }

设备参数

  /*
    *根据部分特征参数设备信息来判断是否为模拟器
    *返回:true 为模拟器
    */
   public static boolean isFeatures() {
       return Build.FINGERPRINT.startsWith("generic")
               || Build.FINGERPRINT.toLowerCase().contains("vbox")
               || Build.FINGERPRINT.toLowerCase().contains("test-keys")
               || Build.MODEL.contains("google_sdk")
               || Build.MODEL.contains("Emulator")
               || Build.MODEL.contains("Android SDK built for x86")
               || Build.MANUFACTURER.contains("Genymotion")
               || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
               || "google_sdk".equals(Build.PRODUCT);
   }

CPU

   /*
    *根据CPU是否为电脑来判断是否为模拟器
    *返回:true 为模拟器
    */
   public static boolean checkIsNotRealPhone() {
       String cpuInfo = readCpuInfo();
       if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
           return true;
       }
       return false;
   }
   /*
    *根据CPU是否为电脑来判断是否为模拟器(子方法)
    *返回:String
    */
   public static String readCpuInfo() {
       String result = "";
       try {
           String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
           ProcessBuilder cmd = new ProcessBuilder(args);
           Process process = cmd.start();
           StringBuffer sb = new StringBuffer();
           String readLine = "";
           BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
           while ((readLine = responseReader.readLine()) != null) {
               sb.append(readLine);
           }
           responseReader.close();
           result = sb.toString().toLowerCase();
       } catch (IOException ex) {
       }
       return result;
   }

大家有什么问题或者新的方法可以留言评论。


Android笔记:多开/分身检测



目录
相关文章
|
7月前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
248 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
7月前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
349 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
安全 Android开发
夜神模拟器 安卓7.0 burp抓包 https流量
夜神模拟器 安卓7.0 burp抓包 https流量
427 0
|
2月前
|
Web App开发 安全 程序员
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
多年的互联网寒冬在今年尤为凛冽,坚守安卓开发愈发不易。面对是否转行或学习新技术的迷茫,安卓程序员可从三个方向进阶:1)钻研谷歌新技术,如Kotlin、Flutter、Jetpack等;2)拓展新功能应用,掌握Socket、OpenGL、WebRTC等专业领域技能;3)结合其他行业,如汽车、游戏、安全等,拓宽职业道路。这三个方向各有学习难度和保饭碗指数,助你在安卓开发领域持续成长。
81 1
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
|
2月前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
28 3
|
2月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
106 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
4月前
|
JavaScript 前端开发 Java
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
IT寒冬使APP开发门槛提升,安卓程序员需转型。选项包括:深化Android开发,跟进Google新技术如Kotlin、Jetpack、Flutter及Compose;研究Android底层框架,掌握AOSP;转型Java后端开发,学习Spring Boot等框架;拓展大前端技能,掌握JavaScript、Node.js、Vue.js及特定框架如微信小程序、HarmonyOS;或转向C/C++底层开发,通过音视频项目如FFmpeg积累经验。每条路径都有相应的书籍和技术栈推荐,助你顺利过渡。
108 3
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
|
4月前
|
编解码 安全 Ubuntu
Android Selinux 问题处理笔记
这篇文章是关于处理Android系统中SELinux权限问题的笔记,介绍了如何通过分析SELinux拒绝的日志、修改SELinux策略文件,并重新编译部署来解决权限问题,同时提供了一些SELinux的背景知识和实用工具。
101 0
|
7月前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
123 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
6月前
|
Java API Android开发
技术经验分享:Android源码笔记——Camera系统架构
技术经验分享:Android源码笔记——Camera系统架构
63 0