字节暗面

模拟器、多开和云手机:零成本 Root 的环境怎么查


最近在梳理 Root 检测的处置规则,模拟器、云手机这几类设备怎么都排不顺。它们的 su 是镜像自带的,检测一跑就中,可里面既有在 PC 上正常玩的,也有批量刷号的工作室。按 Root 一刀切,全放或全封都不对。

这类环境查 Root 没意义,要看的是:它是不是一台一个人在用的真机,能从游戏里拿走多少收益。

先看环境长什么样

模拟器的痕迹最多:构建属性(ro.boot.qemu 只有 AOSP 自家模拟器认,第三方不一定遵守)、虚拟设备节点、缺失的电话能力,x86 机器上还有跑 ARM SO 用的转译库。Unity 里最顺手的是 GPU 名:

string gpu = SystemInfo.graphicsDeviceName;  // 真机多为 Adreno / Mali / PowerVR / Immortalis
bool suspicious = Regex.IsMatch(gpu,
    "GeForce|Radeon|NVIDIA|Intel|SwiftShader|llvmpipe", RegexOptions.IgnoreCase);

只能当信号。各家模拟器的返回值得实测,三星有些机型是 AMD 架构 GPU,正则写宽了会误伤。

多开不一定要 Root。虚拟框架用占位 Activity 拉起游戏,反射替换 ActivityThread 里的 Application,再 Hook libc 的 open()、mkdir() 把读写重定向到宿主目录,游戏一启动就跑在别人的进程里,Hook 能力是现成的。常规查法是看 getDataDir() 在不在 /data/data/<pkg>、调用栈里有没有宿主帧。

这些我不太指望,查的全是对方能改的东西:改机工具能伪造构建属性和 GPU 名,宿主能在 Java 层伪造数据目录。

给手机换“外观”

换个它不好改的地方查

宿主的代码得加载进游戏进程才能拉起游戏,所以它的 APK 一定出现在 /proc/self/maps 里。藏掉这一行要改内核视图,比改 Java 返回值贵得多。

// 示意代码,生产要处理跨块截断的行
int fd = syscall(__NR_openat, AT_FDCWD, "/proc/self/maps", O_RDONLY);
ssize_t n = syscall(__NR_read, fd, buf, sizeof(buf) - 1);
syscall(__NR_close, fd);
for (char *line = strtok(buf, "\n"); line; line = strtok(NULL, "\n")) {
    if (!strstr(line, "/base.apk") || strstr(line, self_pkg)) continue;
    if (strstr(line, "webview") || strstr(line, "trichrome")) continue;  // 系统 WebView 正常会映射进来
    return 1;  // 别人的代码出现在本进程
}

WebView 白名单不加,真机会大面积误报。走 syscall 是因为宿主最常 Hook 的就是 libc,绕开它,对手只能去动内核。大型 Unity / UE 进程的 maps 可能有几千行,放在登录、进副本时抽查,耗时在低端机上测过再定。

另一条是硬件证明。模拟器、手机内虚拟机、ARM 容器云手机没有可用的 TEE,Key Attestation 的 attestationSecurityLevel 到不了 TrustedEnvironment 或 StrongBox,Software 级在自带 Root 的镜像里等于没证明。challenge 服务端下发、至少 16 字节、一次一用,证书链在服务端验。生成密钥慢,登录时异步做一次缓存。

板卡云手机到这里就查不动了。机柜里插的是真机主板,硬件和 TEE 都是真的,证明也可能过,前面那些检测抓的是伪造的破绽,它没伪造任何东西。这类不常见,但工作室做大了迟早往这儿走。

抽屉里的真主板

标签打准,收益交给服务端

客户端的活是把标签打准,拦人交给服务端。服务端看规模痕迹:机房 IP 段、一个设备指纹挂一串账号、一批号的上线时间和操作间隔聚成一团。有客户端标签才能分层设阈值,不然只能一刀切。

模拟器我不主张封。外挂在模拟器上的收益主要来自键鼠和脚本压制手机玩家,进了单独匹配池,这部分收益就没了。

// 环境标签只调收益上限,不直接封号;比例为示意,按业务定
double cap = env switch {
    EnvTag.Emulator          => normalCap,        // 已进单独匹配池
    EnvTag.VirtualContainer  => normalCap * 0.5,  // 同设备账号数另有上限
    EnvTag.CloudPhoneSuspect => normalCap * 0.3,  // 机房 IP + 指纹聚类命中
    _                        => normalCap
};
GrantReward(Math.Min(claimed, cap));
环境 主要信号 处置
PC 模拟器 构建属性、GPU 名、转译库 单独匹配池,不拦截
虚拟框架 / 多开 maps 里有宿主代码、数据目录异常 限制同设备账号数
手机内虚拟机 / ARM 容器云手机 无硬件级证明、机房 IP、传感器缺失 限制交易和高价值产出
板卡真机云手机 客户端基本正常,看 IP 段、指纹、操作节奏 收益封顶,加人工抽查

拧紧收益上限

工作室的账按台算。想过这关,要么花钱弄一台能过硬件证明的单人真机,要么认了每个号都被压在上限以下,哪条路单台利润都变薄。

← 返回列表