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层和动态配置,持续完善检测逻辑。

相关推荐
百锦再3 小时前
第11章 泛型、trait与生命周期
android·网络·人工智能·python·golang·rust·go
会跑的兔子4 小时前
Android 16 Kotlin协程 第二部分
android·windows·kotlin
键来大师4 小时前
Android15 RK3588 修改默认不锁屏不休眠
android·java·framework·rk3588
江上清风山间明月7 小时前
Android 系统超级实用的分析调试命令
android·内存·调试·dumpsys
百锦再7 小时前
第12章 测试编写
android·java·开发语言·python·rust·go·erlang
用户693717500138411 小时前
Kotlin 协程基础入门系列:从概念到实战
android·后端·kotlin
SHEN_ZIYUAN11 小时前
Android 主线程性能优化实战:从 90% 降至 13%
android·cpu优化
曹绍华11 小时前
android 线程loop
android·java·开发语言
雨白11 小时前
Hilt 入门指南:从 DI 原理到核心用法
android·android jetpack
介一安全11 小时前
【Frida Android】实战篇3:基于 OkHttp 库的 Hook 抓包
android·okhttp·网络安全·frida