Android虚拟机与虚拟空间检测实战详解<二>

Android虚拟机与虚拟空间检测实战详解

本文系统介绍如何在Android应用中检测虚拟机(Emulator)和虚拟空间(多开、沙箱等),并结合代码示例,涵盖系统配置、硬件信息、签名校验、内存映射等多维度检测方案。适用于提升应用安全性和防作弊需求。


1. 虚拟机检测

虚拟机检测主要针对常见模拟器环境(如Genymotion、Google Emulator、VirtualBox等),主要通过系统配置和硬件特征进行识别。

kotlin 复制代码
kotlin
复制编辑
fun isEmulator(): Boolean {
    val checkProperty = Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.lowercase().contains("vbox")
            || Build.FINGERPRINT.lowercase().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"))
            || Build.PRODUCT == "google_sdk"
    if (checkProperty) return true

    val tm = Utils.getApp().getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
    val operatorName = tm?.networkOperatorName ?: ""
    if (operatorName.lowercase() == "android") return true

    val intent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:123456"))
    if (intent.resolveActivity(Utils.getApp().packageManager) == null) return true

    return false
}

也可参考AntiFakerAndroidChecker库,通过Native层辅助检测,提升检测精度。


2. 虚拟空间检测

虚拟空间指宿主/沙箱机制,多开环境中App运行在隔离环境,绕过部分安全策略。针对虚拟空间,推荐多角度检测:

2.1 UID异常检测

正常第三方应用UID一般≥10000,低于该值可能为多开环境。

kotlin 复制代码
kotlin
复制编辑
fun isUidSuspicious(context: Context): Boolean {
    return context.applicationInfo.uid < 10000
}

2.2 硬件信息异常

检测MAC地址是否为虚拟默认值。

kotlin 复制代码
kotlin
复制编辑
fun isHardwareInfoAbnormal(): Boolean {
    val mac = getMacAddress().lowercase()
    val virtualMacs = setOf("00:00:00:00:00:00", "02:00:00:00:00:00", "aa:bb:cc:dd:ee:ff")
    return virtualMacs.contains(mac)
}

2.3 签名校验

对比App签名哈希、公钥和证书信息,防止被篡改或注入。

kotlin 复制代码
kotlin
复制编辑
object SignatureChecker {
    fun isSignatureTampered(context: Context, sha256: String, publicKey: String, issuerCN: String): Boolean {
        return try {
            val packageInfo = context.packageManager.getPackageInfo(
                context.packageName,
                PackageManager.GET_SIGNATURES or PackageManager.GET_SIGNING_CERTIFICATES
            )
            val signatures = packageInfo.signatures ?: return true
            signatures.any { signature ->
                val signSha256 = getSignatureSha256(signature)
                val key = getPublicKeyFromSignature(signature)
                val cert = getX509Certificate(signature)
                signSha256 != sha256 || key != publicKey || cert.issuerDN.name != issuerCN || cert.notAfter.before(Date())
            }
        } catch (e: Exception) {
            true
        }
    }
    // 省略辅助方法,实现请参照源码
}

2.4 反射检测包名异常

检测是否存在Hook篡改。

kotlin 复制代码
kotlin
复制编辑
fun isPackageNameHooked(context: Context): Boolean {
    return try {
        val method = Class.forName("android.content.Context").getMethod("getPackageName")
        val result = method.invoke(context) as String
        result != context.packageName
    } catch (e: Exception) {
        true
    }
}

2.5 读取 /proc/self/maps 判断内存映射异常

kotlin 复制代码
kotlin
复制编辑
fun isMapsFileAbnormal(packageName: String): Boolean {
    val mapsFile = File("/proc/self/maps")
    if (!mapsFile.exists() || !mapsFile.canRead()) return false
    mapsFile.useLines { lines ->
        lines.forEach { line ->
            val lowerLine = line.lowercase()
            if (lowerLine.contains(packageName) && lowerLine.contains("/data/data/") && !lowerLine.endsWith("/data/data/")) {
                return true
            }
        }
    }
    return false
}

注意:Android高版本读取/proc/self/maps受限,可结合Native层读取绕过限制。

2.6 类加载器路径检测

检测ClassLoader路径中是否含虚拟空间关键词。

kotlin 复制代码
kotlin
复制编辑
fun isClassLoaderSuspicious(): Boolean {
    return try {
        val path = YourClass::class.java.classLoader.toString().lowercase()
        listOf("virtual", "xspace", "dual", "multi", "parallel", "cloner", "xposed").any { path.contains(it) }
    } catch (e: Exception) {
        false
    }
}

2.7 父进程检测

检测当前进程父进程是否属于已知多开环境。

kotlin 复制代码
kotlin
复制编辑
private val VIRTUAL_APPS = setOf(
    "com.cmaster.cloner",
    "com.lbe.parallel",
    "com.vmos",
    "org.app.virtual",
    "de.robv.android.xposed.installer",
    "com.excelliance.dualaid",
    "com.bly.dkplat",
    "com.qihoo.magic",
    "com.oem.oemclone",
    "com.island",
    "com.shelter"
)

fun isParentProcessVirtual(): Boolean {
    return try {
        val pid = Process.myPid()
        val stat = File("/proc/$pid/stat").readText().split(" ")
        val ppid = stat.getOrNull(3)?.toIntOrNull() ?: return false
        val parentCmd = File("/proc/$ppid/cmdline").readText().trim()
        val parentPackage = parentCmd.substringAfterLast("/", parentCmd)
        VIRTUAL_APPS.contains(parentPackage)
    } catch (e: Exception) {
        false
    }
}

2.8 检测已安装虚拟空间App

kotlin 复制代码
kotlin
复制编辑
fun isKnownVirtualAppInstalled(context: Context): Boolean {
    val pm = context.packageManager
    val installed = pm.getInstalledPackages(0).map { it.packageName }
    return VIRTUAL_APPS.any { installed.contains(it) }
}

2.9 挂载点检测

检测挂载点路径中是否包含虚拟环境关键词。

kotlin 复制代码
kotlin
复制编辑
fun hasSuspiciousMounts(): Boolean {
    return try {
        File("/proc/self/cgroup").useLines { lines ->
            lines.any { it.contains("vmos") || it.contains("virtual") || it.contains("parallel") }
        }
    } catch (e: Exception) {
        false
    }
}

3. 注意事项

  • Android不同版本和厂商对系统文件访问限制不同,检测结果可能存在差异。
  • 建议多种检测方案结合使用,降低误判率。
  • 防止误杀:检测逻辑应预留后门或远程配置,避免正常用户被误判影响体验。
  • 测试时尽量覆盖主流Android版本(10、11、13等)和机型。

4. 总结

虚拟机和虚拟空间检测是提升Android应用安全的有效手段。本文通过多维度代码示例,介绍了常见模拟器检测、UID及硬件异常检测、签名校验、进程和挂载点检测等方法。建议结合Native层和动态配置,持续完善检测逻辑。

相关推荐
EQ-雪梨蛋花汤1 分钟前
【NDK / JNI】Sceneform-EQR 集成 Filament JNI 源码:关键点与逐步操作记录
android·jni·sceneform-eqr
消失的旧时光-19434 分钟前
从命令式跳转到声明式路由:前端、Android、Flutter 的一次统一演进
android·前端·flutter·状态模式
不急不躁1235 分钟前
Android16 跳过GMS测试项
android·java
2501_9159214320 分钟前
iPhone HTTPS 抓包在真机环境下面临的常见问题
android·ios·小程序·https·uni-app·iphone·webview
nono牛1 小时前
Android init服务.rc文件,支持开机自启动和手动控制
android
消失的旧时光-19431 小时前
从前端路由到 Android ARouter:观察者模式在不同平台的同一种落地
android·前端·观察者模式·flutter
nono牛1 小时前
安卓rc-属性触发Hello World服务设计
android
2501_915918411 小时前
iOS 图片资源保护方法,分析图片在二次打包和资源篡改中的实际风险
android·ios·小程序·https·uni-app·iphone·webview
2501_937193142 小时前
中兴机顶盒纯净固件|多机型适配+刷机解析
android·源码·源代码管理·机顶盒
TAEHENGV2 小时前
提醒列表模块 Cordova 与 OpenHarmony 混合开发实战
android·java·harmonyos