一次手游上报数据造假的排查记录:从值域校验到服务端重演

现象

放置类项目,后台监控到离线收益结算异常:一批账号到手的产出明显高于服务端按规则应发的量,且集中在几个高价值道具上。

先看协议层,排除最常见的两种情况。抓包比对上报请求,包签名正确、ts 在窗口内、nonce 无重复,说明既不是链路篡改也不是请求重放:签名保证包没被中间改过,nonce 保证同一个包没被重复提交,但这两样都不涉及包体内容本身的真伪。问题出在上报的数据是假的,而校验一路放行。

排查过程

第一层:值域校验

服务端已有值域校验,拿玩家面板快照算理论上限,超限丢弃:

maxDamage = atk × critMulCap × hitCap

但日志显示异常账号的上报值普遍卡在上限的 90%~95%,没有触发任何丢弃。定位到两个问题:

一是校验用的阈值来源。伤害系数、暴击上限等参数写在随包下发的数值表里,客户端可解包获取,作弊者据此把上报值压在阈值之下。二是校验失败的返回行为:值域不通过时接口返回明确的错误码,等价于向客户端暴露了一个判定 oracle,通过二分探测即可逼近阈值边界。

第二层:自洽校验

补充字段间的物理约束校验,检查单个请求内部是否自相矛盾。例如同一技能的释放次数与其冷却时间、战斗总时长之间存在硬约束:

// 同一技能释放 n 次,至少要跨 (n-1) 个 CD
foreach (var g in req.SkillCasts.GroupBy(c => c.Id)) {
    long need = (g.Count() - 1) * SkillTable[g.Key].CooldownMs;
    if (need > req.DurationMs) {
        Flag(uid, "cd_overflow");   // 打标,返回照常成功
    }
}

上线后拦截到一批伪造请求,但仍有一部分账号的上报数据完全自洽,产出却对不上。复现分析后确认:这部分作弊不修改协议包,而是修改客户端运行时——内存改写攻击力、变速工具放大帧率,正常完成整局战斗后如实上报。战斗过程在客户端真实发生,因此数据在值域和自洽两个维度都无懈可击。值域与自洽校验到此失效。

第三层:服务端重演

对上述情况,唯一可验证的方式是服务端重算,即上报输入而非结果:客户端提交随机种子与操作序列,服务端用同一套战斗逻辑重跑一遍,比对结果 hash 是否一致。

var sim = new BattleSim(snapshot, req.Seed);   // 与客户端同一份战斗核
foreach (var act in req.Actions)
    sim.Step(act);

if (sim.ResultHash != req.ResultHash)
    Flag(uid, "replay_mismatch");
Settle(sim.Result);                            // 一律以服务端重演结果结算

落地前提是双端计算结果逐位一致,否则无法比对。主要有两点:浮点运算跨端不一致,战斗核需改为定点数实现;随机数不能使用引擎自带的 UnityEngine.Random,改用自带种子的确定性实现,且双端每一步的调用次数严格对齐。该改动在项目早期成本可控,系统成型后再改动代价很高。

一个容易误判的坑

重演上线初期,replay_mismatch 打标量会异常偏高,容易被误判为大规模作弊。实际排查后发现,绝大多数是客户端与服务端逻辑未对齐导致,例如技能结算顺序相差一帧、某处随机调用次数不一致,真实作弊占比很低。

因此重演上线阶段应仅打标观察,不接入封号或拦截结算,待双端对齐、mismatch 率降至个位数后再启用处置逻辑,否则首轮误伤的多为正常玩家。

部署与成本

全量重演还是抽样,取决于品类的单局输入规模:

  • 回合制、卡牌、放置:单局输入仅几十字节,重跑是纯逻辑运算,可每局全量重演;
  • 实时动作、MOBA、射击:每帧都是输入,单局数据量与重跑开销高出两个数量级,只能抽样,另对榜单 Top、高价值掉落、已打标账号做触发式全量。

处置策略

数据判定为异常不等于直接封号。弱网重传、断线补包、低端机 RTC 跳变等正常情况都会产生"不合理"的数据,单条信号误伤率高。采用分级处置:先打标,再限制变现路径(交易、提现、榜单结算),多维信号累积到阈值后再人工介入。

检查项小结

检查项常见疏漏排查要点
值域校验阈值随数值表下发客户端校验用阈值服务端单独存,不随包下发
失败返回校验不过返回明确错误码照常返回成功,异步打标,不暴露判定
自洽校验只查单字段,不查字段间约束校验技能次数×CD、消耗与命中等硬约束
上报粒度上报客户端聚合后的均值上报原始采样序列,判定放服务端
服务端重演直接采信客户端结果上报种子+操作序列,双端一致后重跑
重演上线一上线即接封号先打标观察,mismatch 降下来再处置
处置策略单条信号即封号分级:打标→限制变现→人工

排查到最后,校验该做到哪一层,本质是成本问题:投入与这份数据的变现价值匹配即可。纯本地、数据只影响自身显示的,值域足够;涉及交易与提现的,服务端重演的工程成本再高也需要覆盖。

完整的分层判断逻辑另有整理,可搜索「字节暗面 服务端校验」。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值