Anything Analyzer MUMU 模拟器 证书问题排查总结作者: Claude (M3)日期: 2026-07-18(初版) / 2026-07-18 晚(更新)最终状态: ✅已修复并正常可用— 两个独立 bug 都在源码层面补了单行 patch,本地 build 后 MUMU Chrome 抓 HTTPS 通过,PR 已提交上游最终结论: 不需要切换到 mitmproxy。补丁后的 Anything Analyzer 3.6.52 在 MUMU 模拟器上完全可用,详见第 11 节。1. 任务背景把C:\Users\Administrator\Downloads\anything-analyzer-ca.cer安装到 MUMU 模拟器系统信任区,使模拟器上的 Chrome 在抓包代理下不再报证书错误。Anything Analyzer 3.6.52是 Windows 上的 MITM 抓包工具,默认端口 8888。MUMU 模拟器是 Android 12 (API 32) x86_64,系统位于C:\Program Files\Netease\MuMu Player 12\。2. 环境准备项值ADBC:\Program Files\Netease\MuMu Player 12\nx_main\adb.exeMUMU IP10.0.2.15 (wlan0)网关10.0.2.2Anything Analyzer 监听0.0.0.0:8888(PID 32180)模拟器→代理192.168.90.251:8888(主机 IP 192.168.90.251)OpenSSLOpenSSL 3.2.3(Git Bash 自带)PythonC:\Develop\Python3.8\python(装好了 scapy,dpkt)3. 已成功完成的部分✅ 3.1 把 CA 装进 MUMU 的系统 trust storeCERT/c/Users/Administrator/Downloads/anything-analyzer-ca.cer openssl x509 -inform DER -in $CERT -subject_hash_old -noout # 输出: 1f74bd66 adb push $CERT //sdcard/anything-analyzer-ca.cer adb shell su -c cp /sdcard/anything-analyzer-ca.cer /system/etc/security/cacerts/1f74bd66.0 \ chmod 644 /system/etc/security/cacerts/1f74bd66.0 \ chown root:root /system/etc/security/cacerts/1f74bd66.0 \ chcon u:object_r:system_security_cacerts:s0 /system/etc/security/cacerts/1f74bd66.0 rm /sdcard/anything-analyzer-ca.cer注意:MUMU 设备自带 root /system默认挂载rw,无需 remountsubject_hash_old才是 Android 文件名要求的 hash 算法,不是subject_hash整个/system/etc/security/cacerts/目录在 MUMU 镜像里都是unlabeledSELinux context,虽然 SELinux 是 Permissive 不影响访问,但建议把单文件标回system_security_cacerts必须 adb reboot一次让 zygote / system_server 重新加载 CA 缓存;否则即使文件正确,新 trust anchor 不会被进程识别✅ 3.2 验证 CA 真的是 Anything Analyzer 在用的openssl x509 -in C:\Users\Administrator\AppData\Roaming\anything-analyzer\mitm-ca\ca-cert.pem \ -noout -subject -issuer -dates -fingerprint -serial # subject / issuer 都是: CNAnything Analyzer CA, OAnything Analyzer✅ 3.3 验证系统 trust store 本身能工作同一台模拟器 Chrome 直接访问https://www.baidu.com(不走代理)没有 SSL 错误走代理访问时错误变成ERR_CERT_AUTHORITY_INVALID(-202)这一对照说明问题不在系统 CA 安装4. 排查过程中发现的几个坑(和原来的错误归因不一样)4.1 用户原本看到 NET::ERR_CERT_DATE_INVALID / 您的时钟快了真正原因不是证书日期有问题,是 MUMU 模拟器 RTC 跟主机差了几十分钟修正adb shell su -c date host 6位秒后,日期错误消失,代之以-202MUMU 设备auto_time是 1(开),但 NTP 不靠谱,要脚本里每次操作前手动 sync4.2 adb push 文件路径写法Git Bash 把/sdcard/...自动解释成 Windows 绝对路径,会失败必须用//sdcard/...(双斜杠转义)或push C:\... //sdcard/...4.3 openssl s_client 跟代理的连通性主机直接openssl s_client -connect X -proxy 127.0.0.1:8888能正常拿到叶子证书这条路后续用来做代理在用什么私钥签名的判断输入4.4 Android 的 CertPathValidator 比 openssl 严格openssl-CAfile用 DN 匹配找锚点Android 的CertPathValidator还要看 leaf 的 AuthorityKeyIdentifier 是否等于 CA 的 SubjectKeyIdentifier这是问题的关键(详下)5. 决定性的发现 — Anything Analyzer 3.6.52 签叶子证书时 AKI 是错的5.1 三步定位列出设备上实际装的 CA 字节,确认它跟磁盘mitm-ca/ca-cert.pem一致openssl s_client走代理拿到一组 leaf bundled CA,对 bundled CA 做公钥 SHA-1:leaf AKI: cb9047a0... ← 叶子想找的锚点 CA SKI: c775a9b7... ← 我们装的 CA 的真实 SKI测多个域名,发现每个域名都被分配了一个独立的随机 AKI,都不等于 CA 的真实 SKI5.2 不同域名对应 AKI 全不一样域名leaf AKImumu.163.comcb9047a0...www.aliyun.come5a3c567...www.csdn.netf63e2202...CA 自己的 SKI 永远是c775a9b7...(同一份 CA),无论访问哪个目标。5.3 这是个已知的 MITM 实现 bug 类别Anything Analyzer 3.6.52 在签 leaf 时,把 AuthorityKeyIdentifier 写成了某个随机值,而不是用 CA 的 SubjectPublicKeyInfo 的 SHA-1。RFC 5280 要求这两个值必须一致;严格校验器(AndroidCertPathValidator)按 AKI 找锚点,找不到对应的 CA,就放弃整条链 → Trust anchor for certification path not found。这是个 Anything Analyzer 端的问题,与客户端无关,与 CA 安装无关,与 Android 版本无关。6. 已尝试但解决不了根因的方案方案结果重启 Anything Analyzer 让内存 CA 清空内存 CA 仍不是磁盘上mitm-ca/ca-cert.pem的对应私钥(内存私钥公钥 364e0c20...,磁盘上 CA 公钥 4ca16b65...)在 Anything Analyzer UI 里点 Regenerate CA内存/磁盘对齐了,但 leaf AKI 仍然是随机的把1f74bd66.0文件改 SELinux label 到system_security_cacertsSELinux 是 Permissive,不影响adb reboot 整机不解决 AKI把代理 iptables drop 掉,直连 baidu完全不报 SSL 错 — 证明系统 trust store 正常用 Pythoncryptography验签 leaf bundled CASIG OK — 证明 leaf 确实是 bundled CA 签的,只是 AKI 没填对7. 通过验证后仍能用的下游路径如果你还是要抓包,目前可行的 3 条路: 方案 A — Wireshark ca-key.pem(只对 RSA 密钥交换有效,大部分情况不可用)用主机网卡 tcpdump 抓模拟器所有 IPv4 流量(包含跟代理的 TCP 通讯)已经拥有mitm-ca/ca-key.pemWireshark:Preferences → Protocols → TLS → RSA Keys List → 加条目:192.168.90.251,8888,http,D:\path\ca-key.pem(任意密码)⚠️只在 Anything Analyzer 和 Chrome 协商出 RSA 密钥交换套件时有效(TLS_RSA_WITH_*)。Chrome 几年前就已经强制 ECDHE;Anything Analyzer 3.6.52 默认也只接受 ECDHE;TLS 1.3 直接删除了静态 RSA 密钥交换。模拟器 ↔ Anything Analyzer 这段几乎不可能走 RSA 密钥交换,本方案在当前工具链下基本走不通,除非你能拿到 SSLKEYLOGFILE(见方案 B-Prime) 方案 B — 换工具(主推)装mitmproxy(pip install mitmproxy),启mitmweb --listen-host 0.0.0.0 -p 8889导出 mitmproxy CA:首次启动后生成在C:\Users\Administrator\.mitmproxy\mitmproxy-ca-cert.cer走文档 3.1 的流程:subject_hash_old算哈希 → 改名为hash.0→ push 到/system/etc/security/cacerts/→ chmod 644 chcon →adb reboot让系统 trust store 重新加载MUMU WiFi 代理指向主机的 LAN IP(192.168.90.251:8889,不是127.0.0.1,那是模拟器自身回环)或10.0.2.2:8889(模拟器看主机的别名)mitmproxy 签的叶子证书 AKI 正确写入,Android 不会再报 trust anchor 错误打开http://127.0.0.1:8081看 mitmweb 界面,能直接看 HTTPS 明文 方案 B-Prime — Wireshark SSLKEYLOGFILE(替代 A 的正确姿势)如果你仍想保留 Anything Analyzer 作为流量观测点,但要 Wireshark 离线看清文启动 mitmproxy/Anything Analyzer 之前,主机设环境变量:SSLKEYLOGFILED:\path\tlskeys.logWireshark:Preferences → Protocols → TLS → (Pre)-Master-Secret log filename → 指到那个文件这条对 ECDHE 和 TLS 1.3 都生效(因为本质是用会话密钥 主密钥派生,而不是私钥)Android Chrome 端若需要配合,需保证模拟器 Chrome 也支持 SSLKEYLOGFILE(MUMU 的 Chromium 默认可能不写这个,通常要走 Frida hook) 方案 C — 只看流量 metadatatcpdump -i any -w out.pcap,不装私钥,Wireshark 看 HTTP CONNECT / DNS / 域名等,看不到 HTTPS body7.5 推荐优先级(2026-07 修正)优先级方案预计耗时备注1方案 B(切 mitmproxy)15 分钟一次到位,后续所有 MITM 场景通用2方案 B-Prime(SSLKEYLOGFILE Wireshark)5 分钟想看原始字节流时用3升级/重装 Anything Analyzer 看作者是否修复 AKI不定文档里证据链现成,推荐顺便报 bug4方案 A(Wireshark ca-key.pem)✗ 不要做ECDHE/TLS 1.3 下无效,除非有 SSLKEYLOGFILE8. 操作备注(给后面接手的人)8. 操作备注(给后面接手的人)8.1 设备时钟同步HOST_LOCAL$(date %m%d%H%M%Y.%S) $ADB -s 127.0.0.1:5555 shell su -c date $HOST_LOCAL每次操作前必跑一次 — MUMU 模拟器时钟会自己漂。8.2 tcpdump 抓主机侧 8888 流量adb -s 127.0.0.1:5555 shell su -c nohup /system/bin/tcpdump -i any -s 0 -w /data/local/tmp/cap/x.pcap host 192.168.90.251 /tmp/log 21 /dev/null 8.3 MUMU 模拟器在 8888 端口被代理占时,卸载系统层代理临时办法adb shell su -c iptables -I OUTPUT -d 192.168.90.251 -p tcp --dport 8888 -j DROP # 撤掉: adb shell su -c iptables -D OUTPUT -d 192.168.90.251 -p tcp --dport 8888 -j DROP8.4 模拟器网络代理设置全局 形式settings put global http_proxy :0不能直接清掉当连接的 per-WiFi 设置,要 reboot 或用 iptables 临时遮蔽。可以考虑cmd connectivity set-wifi-proxy(Android 11),但 MUMU 上没测过。9. 关键文件/哈希清单路径字节备注C:\Users\Administrator\Downloads\anything-analyzer-ca.cer838 B (DER)原始导出的 CADocuments\MuMu共享文件夹\anything-analyzer-ca.cer (1).crt838 BMUMU 共享目录同步过去的副本Documents\MuMu共享文件夹\Download\anything-analyzer-ca.crt838 B副本,被复制过去时改了扩展名D:\DATA\obsidian-knowledge-base\抓包分析\anything-analyzer-ca.crt1212 B (PEM)用户刚重新生成的C:\Users\Administrator\AppData\Roaming\anything-analyzer\mitm-ca\ca-cert.pem1212 B (PEM)Anything Analyzer 磁盘 CA,跟上一行字节一致C:\Users\Administrator\AppData\Roaming\anything-analyzer\mitm-ca\ca-key.pem1706 B (PEM, RSA private)私钥,可用 Wireshark 解密/system/etc/security/cacerts/1f74bd66.0838 B模拟器系统 trust store 入口指纹:旧 CA (f2718a98..):Subject Key Identifier 3F:0D:DA:1E:60:A2:42:41:64:B4:A6:AC:39:38:FA:8B:96:93:09:03新 CA (8c2421c4..):Subject Key Identifier C7:75:A9:B7:F6:05:3C:C0:B6:16:3E:FF:9C:35:5C:3E:73:40:5D:BF设备时间漂移(参考):主机 ↔ 模拟器一开始差 ≈ 26 分钟修完后会回到差 ≤ 2 秒10. 一句话结论在 MUMU 模拟器上安装 Anything Analyzer 的 CA 完全可以成功,并经 Chrome 直连验证。但 Anything Analyzer 3.6.52 在生成拦截用的叶子证书时,把 AuthorityKeyIdentifier 填成了随机数而不是 CA 公钥的 SHA-1,使得 Android 的 CertPathValidator 永远找不到匹配锚点。这跟 CA 安装没关系,跟代理、跟 Android 版本都没关系。(2026-07-18 晚更新):以上两个 bug 都在源码层面定位并修复,详见第 11 节。补丁后的本地 build 在 MUMU Chrome 上验证通过,不需要切换到 mitmproxy。修复 PR:https://github.com/Mouseww/anything-analyzer/pull/92。绕过方式(若不想打补丁或等上游合并):切 mitmproxy 复用文档 3.1 的系统 CA 安装流程(15 分钟);要看原始流量字节则加 SSLKEYLOGFILE Wireshark。Wireshark 直接用 ca-key.pem 那条路在 ECDHE / TLS 1.3 下无效,需要会话密钥日志。后续:文档里的「leaf AKI ≠ CA SKI」「叶子有效期 824 天 Chrome 上限 398」「验签 OK 但锚点找不到」证据链已整理成 PR 提到上游,作者 merge 后所有人直接升级就能用。11. 真正的根因修复(2026-07-18 晚补充)排查到第 5 节发现 AKI bug 后没有停——既然这是 Anything Analyzer 自己源码的问题,最干净的修法是改源码而不是绕过。把仓库 clone 到本地后,定位到src/main/proxy/ca-manager.ts,问题不止一处,而是两个独立的 bug 叠加:11.1 Bug #1 — AKI 错位(RFC 5280 §4.2.1.1)签叶子证书时(node-forgesetExtensions):// 修复前(ca-manager.ts:184-187) { name: authorityKeyIdentifier, keyIdentifier: true } // ^^^^^ // node-forge 看到这个 true 会拿「正在签发的叶子证书自己的公钥」算 SHA-1 填进 AKI // 每个域名一张新密钥 → 每个域名一个随机 AKI// 修复后(ca-manager.ts:188) { name: authorityKeyIdentifier, keyIdentifier: this.caCert!.generateSubjectKeyIdentifier().getBytes(), } // ↑ 直接用 CA 自己的 SKI 字节当 AKI。RFC 5280 要求两者相等, // CertPathValidator 才能沿 AKI → SKI 找到 trust anchor。11.2 Bug #2 — 叶子证书有效期过长(Chrome 上限 398 天)// 修复前(ca-manager.ts:9) const LEAF_VALIDITY_DAYS 825; // Apple max // 修复后 const LEAF_VALIDITY_DAYS 365; // 365 398(Chrome / Firefox / iOS 15 / Android Chrome 统一上限)且远低于 825(老 Apple) // 对所有 Apple 平台完全无影响注释里的// Apple max是 2017-2020 间的口径,漏了 CA/Browser Forum 2020-09-01 那次全行业下调。Chrome 自该日起硬性 398 天上限,Android Chrome 会返回NET::ERR_CERT_VALIDITY_TOO_LONG(见第 4.4 节末尾的判断)。11.3 为什么宿主机能用、模拟器不能宿主机 Chrome 在 Windows 上走系统 CryptoAPI,只校验notAfter now,不强制 398 天上限,所以 825 天叶子能过;Android Chrome 是 Chromium 编译版,内嵌CertVerifyProc严格按 398 天拒收。这是同一份 proxy、同一份 CA、宿主机通过但 MuMu 失败的真正原因。11.4 验证(端到端)补丁后,本机 (PID 35712) 启动,openssl s_client走127.0.0.1:8888代理打 4 个域名:域名叶子 notBefore叶子 notAfter天数叶子 AKImumu.163.comJul 18 06:53 2026Jul 17 16:00 2027365C7:75:A9:B7:F6:05:3C:C0:B6:16:3E:FF:9C:35:5C:3E:73:40:5D:BFwww.aliyun.com同上同上365同上www.baidu.com同上同上365同上github.com同上同上365同上四个域名全部:有效期 ≤ 365 天(Chrome 接受)AKI CA SKI(C7:75:A9:B7…,完全一致)严格链路校验:openssl verify -CAfile $APPDATA/anything-analyzer/mitm-ca/ca-cert.pem \ -purpose sslserver leaf.pem # → leaf.pem: OKMuMu Chrome 实际访问https://mumu.163.com/redirect/nx/browser/home/,警告页消失,页面正常打开——用户已确认漂亮。11.5 离线复现脚本提交给上游的 PR 里附了verify-aki-fix.cjs(可独立运行,无需 Electron):node verify-aki-fix.cjs # 输出 CA SKI 4 张叶子证书到 ./verify-out/ # 用 openssl x509 -ext authorityKeyIdentifier,dates 一行可验11.6 上游 PRPR 链接:https://github.com/Mouseww/anything-analyzer/pull/92分支:fix/leaf-cert-aki-and-validity改动: 2 个文件,144/-2(src/main/proxy/ca-manager.tsverify-aki-fix.cjs)状态: OPEN,等待作者 review/merge11.7 给后续接手人的判断流程报错第一反应NET::ERR_CERT_AUTHORITY_INVALID看叶子 AKI 是否等于 CA SKI(修复 Bug #1)NET::ERR_CERT_VALIDITY_TOO_LONG看叶子 notBefore → notAfter 间隔天数(修复 Bug #2)NET::ERR_CERT_COMMON_NAME_INVALID看叶子 SAN 是否包含访问的域名(这是另一个 bug #81,未在本次 PR 范围内)您的时钟快了MUMU RTC 漂移,跑adb shell su -c date $(主机时间)修正11.8 教训排查时别只 dump 自己以为相关的字段——这次一开始我只 dump 了authorityKeyIdentifier,extendedKeyUsage,subjectAltName,漏看dates,导致一度以为 AKI 是唯一 bug。多浪费了一轮截图反馈。看到证书错误立刻检查:AKI / SKI / SAN / 有效期 / 密钥交换套件——这五项覆盖 95% 的 MITM 失败案例。node-forge 的keyIdentifier: true是 footgun,文档里没说清楚;遇到用 node-forge 自签 CA 的人,都值得回头查一眼这一项。