Skip to content

加密与加固逆向:AES-GCM、代码混淆、Root 检测与 Frida ​

回到总览:00 基础知识(Foundations)相关模块:TLS 1.2、ECDHE 密钥协商与 CA 信任链 · 09. 现代移动端网络底座:HTTP/1.1、HTTP/2、HTTP/3(QUIC) 与弱网治理

一句话定义 ​

「加密与加固逆向」是语言无关的安全基础:用 AES-GCM 等认证加密保护数据机密与完整性,用代码混淆/加固提高逆向成本,用 Root/越狱检测与 Frida 等动态注入检测识别被篡改的运行环境——它和 TLS 同属「安全底座」,但 TLS 守通信、这一页守客户端自身的代码与数据。

代码索引 ​

对应 Lab:aes-gcm-and-frida-detect —— AES-GCM 加解密 + Root/Frida 特征检测(源码内联于 README)

为什么需要 ​

  • 为什么不能直接把接口密钥/令牌明文写进客户端代码?
    • 一句话答:客户端包体(APK/IPA/JS bundle)终会被反编译或解包提取,硬编码的密钥等于「公开」;密钥必须来自服务端下发或经安全协商,客户端只持有短期凭据。
  • 为什么 AES 要用 GCM 而不是更老的 CBC 模式?
    • 一句话答:CBC 只保证机密性、不防篡改(还怕 Padding Oracle 攻击),GCM 是 AEAD(带认证的加密),一次运算同时产出密文和 Tag,能同时验证完整性,省掉单独的 MAC。
  • 为什么做了代码混淆,安全团队还说「混淆不是加密」?
    • 一句话答:混淆只是重命名/控制流打乱,提高阅读成本,并不隐藏密钥或阻止运行;它拖延逆向,但配合动态注入(Frida)仍可在运行时提取内存中的明文,所以只能当第一道门槛,不能作为机密保护手段。

底层机制 ​

1. AES-GCM 的「密钥 + Nonce + AAD → 密文 + Tag」 ​

GCM 是带关联数据的认证加密:除明文外,还可以把不需加密但要参与完整性校验的 AAD(如报文头)一起算进 Tag。

  • 关键约束(最容易踩的坑)
    • Nonce 绝不能复用:同一个 Key 下两次加密用了相同 Nonce,攻击者可反推出明文异或关系,直接破坏保密性——这是 GCM 头号事故源。
    • Tag 必须校验:解密端先验证 Tag 再使用明文;跳过校验等于退回「只加密不防篡改」。
  • 可能输出(Android javax.crypto 片段示意)
    java
    Cipher c = Cipher.getInstance("AES/GCM/NoPadding"); // 12 字节 IV 推荐的 GCM 参数
    c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"),
           new GCMParameterSpec(128, iv));              // 128 = Tag 长度 bit
    byte[] cipher = c.doFinal(plaintext);
  • 预期现象:doFinal 返回的字节里,前 12 字节是 IV(若未单独传)、其后为密文与末尾 16 字节 Tag,按协议约定拆分存储/传输即可。

2. 代码混淆与加固(提高逆向成本的层层手段) ​

  • 可能输出(R8 规则片段)
    -obfuscate
    -keep class com.example.sdk.public.** { *; }   // 公开 API 不混淆,避免反射断裂
    -printmapping mapping.txt                      // 保留映射,用于崩溃还原
  • 预期现象:混淆后类名变 a.b.c,但 -keep 保留的公开边界不变;mapping.txt 是还原混淆堆栈的钥匙,必须像 TLS 的 symbols 一样归档。

3. Root 检测与 Frida 动态注入检测 ​

  • 常见检测点
    • Root:是否存在 /system/bin/su、/system/xbin/su;Magisk 的 magisk 挂载点;Build.TAGS 含 test-keys;SafetyNet / Play Integrity 远端证明。
    • Frida:进程 maps 中出现 frida-agent、frida-gadget;默认 TCP 27042;尝试 dlopen("libfrida")。
  • 预期现象:这些检测本质是「提高门槛」,不是绝对防线——越狱/Root 环境和 Frida 都能针对性绕过,所以检测到后业务侧应降权或要求二次验证,而不是当作铁证阻断。

Android / Flutter / Web / Backend 对照 ​

维度AndroidFlutterWeb(前端)Backend
对称加密javax.crypto (AES-GCM)encrypt / pointycastle 包WebCrypto AES-GCMOpenSSL / 各类语言 crypto 库
混淆/加固R8 / 加固 SDKDart 编译产物本身难读 + 混淆代码本就下发,靠压缩/混淆服务端代码不落地,天然更可控
运行环境校验Root/越狱 + Frida 检测同宿主(走 MethodChannel 调原生检测)无可信环境,只能风控服务器可信,无需自证
密钥保护Keystore / KeyChain 硬件级同宿主 Keystore无安全存储,密钥不下发前端KMS / Vault 托管

常见场景 ​

  • 本地敏感缓存加密:把登录态 Token 之外的隐私数据落盘前用 AES-GCM 加密,Key 存进 Android Keystore(硬件级,不可导出),即使设备被 root 提取数据分区也解不开。
  • 接口应答防篡改:把报文头作为 AAD 参与 GCM 运算,服务端校验 Tag,防止中间人改包体或包头。
  • 风控识别作弊环境:游戏/营销活动检测到 Frida 注入或 Root,标记设备、限制领券或要求短信二次验证。

常见误配、事故后果与排障 ​

1. 事故:硬编码密钥 + Nonce 固定 → 数据可被批量解密 ​

  • 误配原因:为「方便」把 AES Key 写进代码,并用固定 IV(如全 0)。
  • 后果:攻击者在客户端提取密钥后,对同一 IV 下所有密文可做已知明文攻击,批量还原历史数据。
  • 排障与修法:密钥经安全协商/下发且不落客户端;每次加密用随机且唯一的 12 字节 Nonce,并随密文一起传出。

2. 误配:只做混淆,把混淆当加密防机密 ​

  • 现象:以为 R8 混淆后密钥就安全了,仍把密钥明文留在某字符串常量里。
  • 排障与修法:混淆不改变「字符串常量在包体可被搜到」的事实;机密必须走 Keystore/下发/协商,混淆只用于提高逆向阅读成本。

3. 误配:只在启动一次性检测 Root/Frida,被动态绕过 ​

  • 后果:攻击者先启动干净进程、绕过启动检测,再注入 Frida 运行时篡改逻辑。
  • 排障与修法:在敏感操作(支付、领券、校验)** 前置**做周期性/即时检测,并将结果上报风控,而非只在 Application.onCreate 验一次。

相近概念对比 ​

概念它是什么易混点
加密(AES-GCM)保护数据机密+完整性不等于「藏住密钥」,密钥管理才是难点
混淆(Obfuscation)提高代码阅读成本不是加密,运行时数据仍可提取
加固(Hardening)壳/反调试/反注入提高门槛,非绝对防线
Root/越狱检测识别被篡改环境可被绕过,应降权而非硬阻断
Frida 检测识别动态注入同样可被反检测,属攻防博弈

对应实验 ​

实验说明关键源码
aes-gcm-and-frida-detectAES-GCM 加解密链路 + 一组 Root/Frida 特征检测,观察检测命中时的行为代码内联于 README

复习检查题 ​

  1. 为什么说「AES-GCM 的 Nonce 复用」是整个模式最致命的误用? 答:GCM 的安全证明依赖「同一把 Key 下每个 Nonce 只用一次」。一旦两个明文用相同 Key+Nonce 加密,攻击者把两段密文异或,就能消去密钥流得到两段明文的异或值,结合已知明文即可还原另一段;等价于把一次性密钥流直接暴露。所以 Nonce 必须随机且全局唯一。

  2. 代码混淆能防住「客户端密钥被提取」吗?为什么安全团队坚持它只是第一道门槛? 答:不能。混淆只是把类名/方法名打乱、控制流复杂化,包体里该有的字符串常量、算法逻辑仍在,反编译或动态注入(Frida 在运行时 dump 内存)照样能拿到明文密钥。所以它只提高逆向时间与成本,真正的机密保护要靠 Keystore 硬件存储与密钥协商下发。

  3. Root 检测和 Frida 检测做到「检测到就阻断」是否足够安全? 答:不够。两者都属于客户端自证,运行在被攻击者控制的设备上,越狱/Root 隐藏与 Frida 反检测都能绕过「启动一次」式的检测。正确做法是把检测结果作为风控信号:在敏感操作前即时复检、上报服务端做设备画像与降权(如要求二次验证),而不是当作不可绕过的硬阻断。

速记 ​

  • AES-GCM:密钥+Nonce+AAD → 密文+Tag;Nonce 复用=灾难;Tag 必校验。
  • 混淆≠加密:只拖慢阅读,不改「常量可被搜、内存可被 dump」。
  • 密钥管理 > 算法:硬编码密钥再强的算法也白搭;用 Keystore/下发/协商。
  • 检测是信号不是铁证:Root/Frida 可绕过,应降权+上报风控。

站点构建时间:2026/8/24 23:43:17