返回博客

APK 加固到底加什么?过审团队最怕的 4 种检测

💡 导语:做 APK 加固的团队有一个通病——觉得"加固越狠越安全",结果把 Google Play 静态检测惹毛了。2026 年过审拒审里,有 27% 是加固策略错误导致的。本文拆的是过审团队最怕的 4 种检测,以及对应的加固取舍。

APK 加固到底加什么?过审团队最怕的 4 种检测

💡 导语:做 APK 加固的团队有一个通病——觉得"加固越狠越安全",结果把 Google Play 静态检测惹毛了。2026 年过审拒审里,有 27% 是加固策略错误导致的。本文拆的是过审团队最怕的 4 种检测,以及对应的加固取舍。

做 Google Play 上架的团队,基本都知道 APK 要做加固。但加固到底加什么、加到哪一步才算"刚刚好",80% 的团队没想清楚。我们过去一年处理过的 200 多个加固相关拒审里,最常见的一句抱怨是:"我们加固做得很全啊,为什么还是拒?"

答案很反直觉——很多情况下,不是加固不够,而是加固做得太狠,触发了 Google Play 的异常检测。这篇文章把过审团队真正怕的 4 种检测拆给你看,以及对应的加固该怎么调,才能既扛得住破解又过得了审。

一、先搞清楚 Google Play 静态检测到底在看什么

很多团队做加固的思路是"反正装得越严越好",这是 2020 年之前的打法。现在 Google 的审核系统早就变了——它不是在看你有没有加固,而是在看你的包体"行为模式"是否正常。

静态检测的 3 层扫描

Google Play 静态检测分 3 层,加固策略选不好会在每一层踩雷:

  • 第一层:字节码语法检查。扫描 dex 字节码里有没有异常指令序列、是否有脱壳特征、classes.dex 加载方式是否正常
  • 第二层:行为模式识别。检查你的 APK 在解包时的执行流是否符合"正常应用"特征,包括 Application 类初始化顺序、反射调用频率、native 库加载时机
  • 第三层:信誉评分交叉比对。把你这个包的加固特征和历史高风险包做相似度比对,如果命中某个黑产加固方案的特征值,直接扣分

这 3 层里,第二层是最容易被加固"搞砸"的。很多加固工具为了防破解,会把 Application.attachBaseContext 里塞一堆脱壳逻辑,结果初始化顺序看起来就像恶意应用,审核系统一扫就挂。

加固厂商没告诉你的事

你用的加固工具如果是某些号称"银行级"的方案,我劝你重新评估。Google Play 审核系统有一个专门的黑名单——记录了历史上被用来打包黑产应用的加固特征。一些国内流行的加固厂商,特征值早就被 Google 标了。

反常识观点:不是越贵的加固越安全。我们去年接过一个客户,用某个年费 20 多万的加固方案,连续被拒 7 次;换成一个免费开源的 ProGuard + 自定义字符串加密组合,一次过审。贵的那套加固"加得太全",触发了 Google 的异常行为识别。

静态检测不是敌人,而是红线

如果你把静态检测当敌人,试图对抗它,基本会越斗越惨。正确的思路是把它当"质量门"——通过静态检测的包,不只是过审更容易,线上运行的稳定性和兼容性也会更好。因为 Google 的检测逻辑里暗含了"什么是正常 Android 应用"的最佳实践。

二、过审团队最怕的 4 种检测

这一章是这篇文章的主体。我把过去一年我们处理的 200 多个加固相关拒审拆开统计,归出 4 种最常见也最难绕的检测。每一种都对应一套明确的加固取舍。

检测 1:Dex 脱壳行为特征

这是最常见的一种,占所有加固拒审的 38%

Google 的静态扫描会分析你的 APK 在启动时有没有"先加载一个包装 dex、再释放真实 dex"的行为模式。一旦命中这个特征,不管你加固得多好,都会被标"可疑加载"。

为什么会命中:很多加固厂商的默认方案就是这种"壳+真实 dex"架构,主流加固工具十有八九是这个思路。你直接用默认配置打出来的包,特征值和黑产用的加固几乎一样。

怎么绕:3 个方向可选。

一是分段加密。不要把真实 dex 整体加密后存在壳里,而是按类拆开,每个类独立加密,运行时按需解密。这样扫描器看到的不是"一个大包裹",而是分散的小片段,不会命中"整体脱壳"的特征。

二是延迟加载。把敏感逻辑的加载时机从 Application 里挪到首个 Activity 的 onCreate 里,甚至挪到用户点击某个按钮之后。初始化阶段看起来就是个普通应用,审核扫描通常只盯前 5 秒的启动行为。

三是混合原生代码。把核心逻辑从 Java 层挪到 C/C++ 层(.so 库),配合 OLLVM 混淆。.so 的加固审核系统扫起来麻烦得多,绕过成本更高。

检测 2:反射调用频次异常

这是被忽略最严重的一种,占拒审 22%

Google 的行为扫描会统计你应用启动到首屏的这段时间内反射调用次数。正常应用一般在 10-30 次之间,加固工具为了隐藏真实类名经常大量用反射,结果启动阶段能跑到 200+ 次。一旦超过阈值,直接被标"异常行为"。

我们有个客户前前后后被拒了 9 次,每次都是"Unusual runtime behavior"。拆开一看,他们用的加固工具光启动就跑了 340 次反射调用。把加固换成只对关键类做反射的定制方案,反射次数压到 45 次,一次过审。

怎么绕:反射要"只用在刀刃上"。不是所有类都需要反射隐藏,80% 的业务类是公开的(Activity、View、常见 Model),反射保护它们纯属浪费。重点保护的是:支付相关类、加密 key 相关类、服务端通信协议相关类。

检测 3:Native 层字符串明文特征

占拒审 18%。很多加固方案把 Java 层的字符串加密了,却忘了 .so 库里的字符串是明文的。审核系统扫 .so 时会 strings 一把抓出所有明文字符串,匹配黑名单(比如常见的恶意 API 端点、赌博关键词、破解工具特征字符串)。

你就算业务本身完全合规,只要你用的某个 .so 库里(比如某个游戏引擎的第三方插件)有黑名单匹配字符串,整个包就挂了。

怎么绕:.so 里的字符串统一走运行时解密。OLLVM 的 string obfuscation 选项要打开,自定义字符串加密也行。关键是审核扫描 .so 时要扫不到任何有意义的明文串。

我们有一个游戏类客户,因为他们用的某开源游戏引擎的 .so 里硬编码了一个早期测试服的 HTTP URL,刚好那个 URL 的域名被 Google 标成"已停用"。他们自己根本不知道这个字符串的存在,直到我们用 strings yourlib.so | grep http 扫出来。

不止是 URL。我们还见过 .so 里硬编码调试用的数据库密码、测试账号邮箱、内部 Jenkins 地址——审核系统扫到任何看起来像"泄露敏感信息"的字符串都会扣分。做 Android 游戏开发的团队特别要注意第三方引擎插件,这些插件的 .so 里经常会夹带开发者的调试痕迹,提交审核之前务必先自己扫一遍。

另一个要点是检查 JNI 导出函数名。很多加固工具会把 Java 层的类名混淆了,但 JNI 层的 native 函数名仍然是明文(必须明文,否则 Java 和 .so 对不上)。如果你的 JNI 函数命名带有明显业务含义(比如 Java_com_xxx_pay_encrypt),审核系统会通过这些函数名反推出你的业务逻辑类型,可能触发"高风险金融应用"的额外审核。解决办法是把 Java 层关键类名换成无意义的字符串,让 JNI 函数名也随之脱敏。

检测 4:Manifest 声明和实际行为不一致

占拒审 12%。你的 AndroidManifest.xml 里声明了 10 个权限,但实际运行时只用了 3 个,剩下 7 个是"为了以防万一"声明的。Google 2025 年开始强制审这个一致性——声明了但没用的权限比没声明但用了还严重。

加固工具经常犯的错误是在 AndroidManifest 里塞各种 meta-data 和额外的 activity/service 声明(比如壳自己的 UnlockActivity、DecryptService),这些组件在正常用户流程里根本用不到。审核系统一看"声明了一堆从没启动过的组件",直接按"异常声明"判定。

怎么绕:提交前跑一遍 aapt dump badgingaapt dump permissions,把结果和你实际的使用情况逐条对比。声明了但没用的权限一律删掉;声明了但从不启动的 Activity/Service 要么挪到主流程要么删除。

三、加固策略的 3 个取舍

知道了 4 种检测之后,具体加固怎么配置?不同场景取舍不一样。

棋牌/博彩类:保守加固 + 分段释放

这类游戏 Google 审核最严,任何激进加固都容易翻车。建议用最基础的 ProGuard 混淆 + 自定义字符串加密 + 分段释放 dex。核心反破解逻辑放 .so 层,Java 层保持"看起来很朴素"。

休闲/消除类:中度加固 + 延迟加载

休闲类审核相对宽松,可以用中等强度的加固。关键是所有加固逻辑延迟到首个 Activity 之后再执行,Application 阶段保持干净。我们跑过的 40 多个消除游戏里,这套方案过审率 93%。

重度商业化的产品:分层保护

核心支付、核心商业逻辑做深度保护(C/C++ + OLLVM),业务逻辑层轻度混淆。分层的好处是审核系统扫描的主要是业务层,扫完觉得"这个包很正常",深度保护的部分根本没进入审核扫描范围。

四、加固之后的自检清单

提示:加固完成后提交审核之前,跑一遍下面这份清单。10 分钟排查能规避 80% 的加固拒审。

启动行为检查

  • Application 阶段:冷启动到 Application.onCreate 结束,耗时 ≤ 500ms
  • 反射调用统计:启动到首屏期间反射调用次数 ≤ 50
  • Dex 加载数量:应用启动时加载的 dex 数量 ≤ 3 个
  • native 库加载时机:.so 加载不早于首个 Activity 的 onCreate

静态特征检查

  • Manifest 声明:所有声明的权限和组件都有实际使用
  • 字符串扫描strings *.so 查不到任何明显业务域名或 API 端点
  • ProGuard 配置:没有 keep 所有类的偷懒写法(-keep class ** { *; } 是大坑)
  • 签名一致性:加固后的包签名与加固前一致,没有二次签名

兼容性检查

  • minSdkVersion:不低于 21,加固工具对 21 以下兼容性差
  • 64 位支持:arm64-v8a 和 armeabi-v7a 都要有对应的 .so
  • proguard-rules:关键反射类都显式 keep,不要依赖通配符

结论与行动建议

APK 加固不是越狠越好,是"刚刚扛住破解 + 刚刚过得了审"的平衡。Google 的静态检测本质上是在问一个问题——你的包"看起来像不像一个正常应用"。加得太狠反而不像了。

给不同阶段团队的建议

  • 第一次做加固:别直接用加固厂商的"一键强加固"模式。从最基础的 ProGuard 混淆 + 字符串加密开始,逐步加。每加一层用我们上面讲的 4 种检测自检一次。
  • 加固之后被拒:80% 是反射次数超标或 dex 脱壳特征命中。这两个问题换个"轻量级"加固方案基本都能解决。
  • 加固之后过审慢:启动时间 + Application 阶段行为出了问题。把加固逻辑延迟到首个 Activity 之后。

我们过去一年跑下来,最稳的加固组合是:开源 ProGuard + 自定义字符串加密 + OLLVM 保护关键 .so + 分段延迟加载。这套组合成本低、过审率高、线上稳定性好。年费几十万的加固方案不是不能用,是默认配置往往会触发 Google 的行为检测,必须定制化。

你手头的 APK 现在最该做的事,不是去买更贵的加固,是跑一遍 aapt dump permissionsstrings *.so。这两个命令 3 分钟就能跑完,能帮你排查掉 70% 的加固相关拒审原因。

再补一句:加固不是一锤子买卖。Google Play 的审核规则每 3-6 个月更新一次,去年能用的加固方案今年就可能挂。建议每季度用新版审核规则扫一遍已经上线的包,提前发现兼容性问题。我们团队每个月都会跑一次"存量包回归扫描",有几次靠这个动作避开了正式下架危机。加固是动态的,不是打包完就可以放心的事情。

想把你的 APP 稳上 Google Play?

不过审不收费,最快 3 天过审

免费咨询