HTTPS抓包与逆向分析:从中间人代理到App签名算法还原

1. 分析前的工程准备:抓包、反编译与绕过证书检测

1.1 为什么抓包环境会直接决定后续分析效率

我第一次处理某虾App的数据需求时,心里想得很简单:把接口请求抓到,照着参数模拟一套不就完事了?结果打开抓包工具一看,请求头里多了一个sign字段,每次请求都变,根本没法直接搬。后面一连串的 403、风控提示,才让我意识到这类App早就不是“裸请求”时代了。加密参数分析这件事,看着是算法题,实际上第一步是环境题:抓包能不能抓干净、证书校验能不能绕过、反编译之后能不能顺利找到关键代码,每一步都决定你后面是走直线还是绕远路。

先说抓包。某虾App走的是HTTPS,抓包工具常见就是 Charles 或 mitmproxy,原理都是中间人代理:客户端信任代理证书,代理把流量解密后转发给服务端。听起来简单,但实际会遇到两个大坑:一是 Android 7.0 及以上版本默认不信任用户安装的证书,你装了 Charles 证书到“用户证书”区域,对大多数App根本不生效;二是某虾App在客户端做了 SSL Pinning,也就是证书锁定,即使你信任了代理证书,它校验的还是服务端证书指纹,校验不过直接断开连接。

所以真正的准备工作,不是“装个证书”就完事,而是要让目标App老老实实走你的代理。我的习惯是:会用真机加 Frida,而不是一上来就重打包。重打包虽然也能用,但很多App有签名校验,重打包之后根本跑不起来,白白浪费时间。Frida 的优势是不改App文件,运行期注入脚本,既能绕过证书锁定,又能顺手做动态调试,后面定位加密函数时也要靠它。

1.2 绕过SSL校验的两种实操方案

方案一:重打包并修改系统证书信任区域。这个方案适合“没有反篡改校验”的App,操作路径是先用 apktool 解包,把抓包证书转成系统证书格式(/system/etc/security/cacerts/下的.0文件),塞进 APK 的res/raw目录,再修改AndroidManifest.xml里的networkSecurityConfig,最后重打包签名安装。缺点很明显:某虾App这种体量的应用基本都有签名校验和完整性检测,只要检测到 APK 被改动过,要么闪退要么接口直接拒绝。我一般不把它作为首选。

方案二:Frida Hook 绕过 SSL Pinning。这才是主流。核心思路是运行时替换掉App内部的证书校验逻辑,让代理证书“合法化”。你需要在电脑上装 Frida,手机端跑 frida-server,两端版本要对齐,然后写一段 JavaScript 脚本注入目标进程。常用的姿势是 HookTrustManagerImpl的checkServerTrusted,或者直接替换X509TrustManager的实现:

Java.perform(function () { var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager'); var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl'); TrustManagerImpl.checkTrustedRecursive.implementation = function () { return null; }; });

这段脚本的意思是“绕过递归信任校验”,让客户端不再严格核实服务端证书链。执行frida -U -f com.xia.app -l bypass_ssl.js之后再去触发请求,Charles 里就能正常看到明文数据了。这里有个经验:不要在 App 启动前急着注入,有时 App 启动阶段的反调试检测会先跑起来,容易把注入过程打断。我习惯先启动App再附加进程,虽然会漏掉启动阶段的部分请求,但后续主要接口都能抓到,分析效率更高。

1.3 反编译工具链与壳处理的注意点

抓包拿到请求后,下一步是反编译。某虾App这类商业应用大概率会加壳,常见如腾讯加固、阿里聚安全等。直接用 jadx 打开 APK 会看到壳的加载入口,真正的业务代码不在里面。这时候要么先脱壳,要么换一个思路:如果只是为了找加密函数,可以先跑起来再 hook 内存,不一定非要静态脱壳。但静态反编译依然很有价值,尤其是拿到加固前的包,或者通过 dump 内存获取 dex 后反编译。

我的处理顺序是这样:先放着apktool解包看资源文件和清单,再用jadx尝试反编译,如果发现关键类被加密或抽空,就借助 Frida 的 DEX dump 脚本把运行时加载的 dex 拉出来,再丢给 jadx 分析。有关键代码之后,搜索范围立刻缩小到“签名”“加密”“md5”这些关键词附近。这个阶段别急着读全部代码,先列出所有可疑类和方法,再逐个验证。

2. 拆解请求参数:从原始数据中圈定签名生成规则

2.1 一次完整请求里有哪些值得关注的字段

抓包正常之后,我对着某虾App的评论接口看了很久。一个典型请求长这样:

{ "pageNum": 1, "pageSize": 20, "songId": "778899", "ts": 1699999999, "devId": "3e4a6e8c9f2b7d1a", "sign": "a3f2c09d8b7e6f1a2c45d0e9b8a7c6f5" }

一眼扫过去,pageNum、pageSize、songId这些是业务参数,ts是时间戳,devId是设备标识,只有sign看起来像“签名”。签名是典型的32位十六进制字符串,长度和 MD5 一致,但也可能是 MD5 之后再加工。我们不能光凭外观下结论,真正要搞清楚的是:哪些字段参与了签名计算、计算顺序是什么、有没有附加的盐或密钥。

2.2 用差分法确认sign的输入范围

这里的核心方法我叫它“差分法”:固定其它输入,只改一个字段,观察sign是否变化。具体操作是,在 Charles 里复制同一个请求,右键修改参数后重发,对比返回结果。

我建议每个关键字段都单独测一遍,像下面这样记录:

变更字段sign是否变化结论
pageNum从 1 改成 2变化参与签名
songId从 778899 改成 778800变化参与签名
ts改早 1 秒变化参与签名
devId固定不变时改值变化参与签名
请求头User-Agent改成其他值最终返回 403可能作为签名上下文

这个表格做完,签名输入的范围就大致锁定了:pageNum、pageSize、songId、ts、devId这些参数基本都参与了计算。还要注意,App 端对请求体可能有“参数按字典序排列再拼接”的规则,所以我们要在还原代码时仔细检查排序逻辑,不能想当然按肉眼看到的顺序来。

2.3 常见签名外观特征速判

签名分析多了之后,我习惯先看外观再猜算法。像a3f2c09d...这种32位hex,大概率是 MD5;如果是40位hex,可能是 SHA-1;64位hex,基本就是 SHA-256 或对应的 HMAC 变体。如果末尾带着=,可能是 Base64 编码的结果;如果字符串里大小写混排且字符集明显不是十六进制,那就是自定义编码,难度会高一个量级。

某虾App这里看起来是32位hex,所以我第一猜测是某种 MD5 加盐变种。但这只是猜测,最终要回到代码里去验证。外观特征的意义在于帮你缩小搜索范围,而不是直接给出答案,别在这上面投入太多精力。

3. 静态定位加上动态Hook:找到加密函数的真实入口

3.1 静态代码分析:搜索签名相关字符串

拿到反编译代码后,第一步是全局搜索关键词。在 jadx 里直接搜sign、md5、encrypt、secret、api_key这类字符串,能快速定位到某个工具类。某虾App的代码里大概率会有一个类似SignUtils或EncryptUtil的类,里面集中了签名逻辑。

我见过的大部分签名工具类,代码结构都挺相似:一个入口方法接收业务参数,转成字符串,拼上时间戳和密钥,再调用 MD5 或 HMAC 方法,最后返回签名。比如反编译后可能是这个样子:

public class SignUtils { private static final String SECRET_KEY = "xI@#2024_XiaSign"; public static String getSign(Map<String, String> params, long ts) { StringBuilder sb = new StringBuilder(); try { TreeMap<String, String> sortedParams = new TreeMap<>(params); for (Map.Entry<String, String> entry : sortedParams.entrySet()) { sb.append(entry.getKey()).append("="); sb.append(entry.getValue()).append("&"); } String raw = ts + sb.toString() + SECRET_KEY; return MD5Util.md5(raw); } catch (Exception e) { return ""; } } }

看到TreeMap要注意:Java 的TreeMap默认按字典序排序,这说明参数排序就是“按 key 升序”。如果换成HashMap,顺序就不可控,签名结果会乱,所以这类代码几乎都会刻意用有序结构。排序细节,是所有还原过程中最容易被忽略又最容易出错的地方。

3.2 动态Hook确认调用链

静态代码只能证明“可能有这样一个函数”,不能证明线上请求真的调用了它。想要确认加密入口,我用 Frida 直接 hook 这个类的getSign方法,打印输入输出:

Java.perform(function () { var SignUtils = Java.use('com.xia.app.encrypt.SignUtils'); SignUtils.getSign.implementation = function (params, ts) { var sign = this.getSign(params, ts); console.log('[SignUtils.getSign] params=' + JSON.stringify(params)); console.log('[SignUtils.getSign] ts=' + ts); console.log('[SignUtils.getSign] sign=' + sign); return sign; }; });

运行脚本后,在 App 里随便触发一次评论列表加载,就会在 Frida 控制台看到对应的入参和返回值。对比 Charles 里抓到的sign值,如果一致,说明我们找到了真正的生成入口;如果不一致,说明签名逻辑还有别的分支,可能是走了另一个重载方法。

这一步比较关键的还有 hook 时机:App 刚启动时,某些加密类的加载还没完成,Java.use会失败。我通常先在 Frida 里用Java.perform包一层,同时给脚本加上延迟重试逻辑,或者直接在Java.classFactory.loader加载完成之后再 hook,避免“类还没加载”的问题。

3.3 原始算法还原:从jadx代码到伪代码转换

定位到函数只是第一步,真正费时间的是还原算法细节。某虾App的签名过程,从反编译代码和 Hook 日志综合下来,逻辑大致是:

  1. 将业务参数放入一个可排序 Map,按 key 升序排列;
  2. 拼接成key1=value1&key2=value2的形式;
  3. 最前面拼上当前时间戳ts;
  4. 最后拼上一个固定密钥字符串;
  5. 对整个字符串做 MD5,取32位十六进制小写结果。

这段伪代码看着简单,实际还原时我会反复确认几个细节:拼接时&放在哪个位置、末尾是否额外带有&、拼接顺序是ts + params + key还是params + ts + key、MD5 输出是十六进制还是 Base64。这些细节全都要靠 Frida 打印日志和实际抓包逐字符对比,否则你写的生成器只能在极少数请求下碰巧成功。

4. 把算法翻译成可运行的签名工具

4.1 某虾App签名过程的伪代码与Python实现

算法弄清楚之后,我用 Python 快速写了一个签名生成器。核心逻辑和 App 端保持完全一致:参数排序、拼接、加盐、MD5。一个可运行的示意版本如下:

import hashlib import time SECRET_KEY = "xI@#2024_XiaSign" def build_sign(params: dict, ts: str) -> str: sorted_items = sorted(params.items(), key=lambda item: item[0]) param_str = "&".join(f"{k}={v}" for k, v in sorted_items) raw = ts + param_str + SECRET_KEY return hashlib.md5(raw.encode("utf-8")).hexdigest() if __name__ == "__main__": params = { "pageNum": 1, "pageSize": 20, "songId": "778899", "devId": "3e4a6e8c9f2b7d1a" } ts = str(int(time.time())) sign = build_sign(params, ts) print("ts:", ts) print("sign:", sign)

你可能会问:为什么用 Python 而不是继续用 Java 写?因为后续做数据采集或自动化验证时,Python 的生态更顺手,requests 发请求、pandas 处理数据都不用额外搭环境。只要算法逻辑一致,语言本身无所谓。

4.2 对齐细节:大小写、URL编码、参数排序

代码写完,第一轮跑出来的签名大概率对不上。这不是算法错了,而是细节没对齐。我踩过的问题主要有三个:

第一是排序规则。Python 的sorted()默认按 Unicode 码点排序,Java 的TreeMap默认也是按字典序,但这个“字典序”在不同字符集和 Java 版本下可能略有差异。最好把参数名固定为纯 ASCII,避免非英文字符带来排序歧义。

第二是大小写。MD5 十六进制输出有的大写有的小写,某虾App的sign是小写,而我在最初实现时用了一个自动转大写的工具函数,结果怎么都对不上。这个只要看一眼抓包里的 sign 样例就能确定,但容易在代码里顺手埋坑。

第三是 URL 编码。如果业务参数里包含中文、空格、特殊符号,App 端在拼接前可能会有一次 URLEncoder.encode。我在某次请求里往keyword参数塞了中文,用模拟签名请求时签名校验一直失败,后来发现 App 端把中文编码成了%E6%9F%90%E8%99%BE再参与签名。所以参数值在参与拼接前是否编码、编码的字符集是什么,都要单独验证。

4.3 回归测试:用真实请求验证签名是否一致

签名工具写完,最后要做的就是回归验证。我的验证方式分两步。

第一步是回放验证:把抓包得到的真实请求原封不动(包括原始ts和sign)保存下来,用我的 Python 生成器传入同样的参数和ts,看生成的 sign 是否和抓到的 sign 完全一致。只要这一个请求能对上,就说明算法核心正确。

第二步是实弹验证:用 Python 重新构造一个新的请求,ts用当前时间,sign 由生成器计算,直接发送给某虾App接口。返回 HTTP 200 或包含业务数据的 JSON,说明签名通过;返回 403、401 或风控提示,就说明还有某个参与签名的参数没被覆盖。

这里有个细节要注意:有些请求头部也会参与签名,比如User-Agent、deviceId的自定义请求头。某虾App虽然主签名在 body 里,但有些接口的签名会把User-Agent一并拼进原文。我在实测中就遇到过“单独验签通过、整体请求失败”的情况,最后把请求头和 body 一起检查才发现问题。

5. 版本迭代后的维护思路与一些通用心得

5.1 App升级后签名变化的快速定位方法

某虾App大概每两个星期就会发一版,签名算法不一定会变,但密钥、拼接规则、校验策略都可能微调。一旦线上版本升级,旧签名大概率立刻失效。遇到这种情况,我重新分析的顺序是:

  1. 先看新版本是否有加壳变化,如果壳变了,优先跑 Frida 的 DEX dump 把新 dex 拉出来,重新反编译;
  2. 全局搜关键词sign、SECRET_KEY、getSign,对比和上一版的差异,重点看常量字符串;
  3. 直接 hook 旧版定位到的SignUtils类,如果类名和方法名还在,就能迅速确认改动范围;
  4. 用差分法重新跑一遍请求,确认参与签名的参数是否新增或减少。

多数情况下,算法骨架不会大改,变的只是密钥或者多了某个参与签名的字段。比如某次更新后,某虾App在签名输入里多拼了一个设备活跃时间变量,导致签名每次请求都不同,但那段时间我靠 Frida 日志对比,半天就定位到了新增字段。

5.2 长期维护的避坑清单与合规边界

最后整理一份避坑清单,给长期做这类分析的朋友参考:

  • Frida 连接不稳定时,先确认 frida-server 版本和手机架构匹配,x86 模拟器和 arm 真机的 frida-server 不是同一个文件;
  • 抓包证书一定要安装到系统证书目录,用户证书在 Android 7+ 上默认无效;
  • Hook 签名方法时尽量打印完整拼接原文,不要只打印入参对象,否则拼接细节错误时很难排查;
  • 模拟请求时把请求头里的User-Agent、X-Forwarded-For等敏感头保留原值,减少被风控误判的概率;
  • 自动化请求频率要克制,不建议高频并发,否则接口返回 403 之后会误以为是签名问题,实际上是被限流了。

还要强调一点:这类加密参数分析技术,只建议用于学习研究、接口调试或合规条件下的数据获取场景。任何绕过风控、高频抓取、商业化滥用行为,可能涉及法律风险。我的原则是:技术分析可以做,但使用边界必须想清楚,不要让工具变成给自己惹麻烦的东西。

最后再分享一个实际体会:加密参数分析这件事,真正难的往往不是算法本身,而是整个排查链路里那些“差一点就对了”的细节。一次成功的还原,背后通常是几十次抓包对比、几十段 Hook 日志、几十遍请求重放的累积。保持耐心,把每一步的输入输出都记录下来,你会发现这类 App 的签名再复杂,也终究有迹可循。

相关新闻

工控调试必修课:掌握字节、十六进制与大小端

工控调试必修课:掌握字节、十六进制与大小端

前阵子在某现场处理一台仪表的通信问题&#xff0c;报文已经抓出来了&#xff0c;十六进制字符串干干净净摆在屏幕上&#xff0c;可上位机显示的温度永远是乱码。折腾到最后&#xff0c;原因特别简单&#xff1a;寄存器里两个字节的顺序反了。类似的故事&#xff0c;在工控调试…

2026/10/20 10:45:37 阅读更多 →
降重降AI的软件哪个好?能同时降重复率和AI率的才省事,AI率降到20%以下!

降重降AI的软件哪个好?能同时降重复率和AI率的才省事,AI率降到20%以下!

降重降AI的软件哪个好&#xff1f;能同时降重复率和AI率的才省事&#xff0c;AI率降到20%以下&#xff01; 降重降AI的软件哪个好&#xff1f;这是很多同学在交稿前一周反复搜的问题。查重报告刚压到合格&#xff0c;AIGC报告又标了一片红&#xff1b;换个工具专门降AI&#x…

2026/10/20 10:45:37 阅读更多 →
为什么一降重AI率就升高?手动降重越改越像AI,降重降AI一起做才是正解!

为什么一降重AI率就升高?手动降重越改越像AI,降重降AI一起做才是正解!

为什么一降重AI率就升高&#xff1f;手动降重越改越像AI&#xff0c;降重降AI一起做才是正解&#xff01; 为什么一降重AI率就升高&#xff1f;不少同学都碰到过&#xff1a;查重报告上的红色总算改少了&#xff0c;再送去做AIGC检测&#xff0c;AI率反而比改之前还高。明明每…

2026/10/20 10:44:37 阅读更多 →

最新新闻

Audio2Face 2023.2.0:AI驱动面部动画与口型同步实战解析

Audio2Face 2023.2.0:AI驱动面部动画与口型同步实战解析

平时折腾过不少动画管线工具的人应该都知道&#xff0c;做虚拟人、做游戏过场、做短视频口播的时候&#xff0c;最烦的不是模型贴图和绑定&#xff0c;而是让角色的嘴型和表情在音频上对得自然。手动调 blend shape 帧曲线能调到怀疑人生&#xff0c;一段三十秒的语音&#xff…

2026/10/20 12:20:11 阅读更多 →
TCP三次握手与四次挥手原理及实战调优指南

TCP三次握手与四次挥手原理及实战调优指南

1. 为什么“三次握手、四次挥手”不是教条&#xff0c;而是网络世界里最精妙的握手礼仪你打开网页、刷短视频、发一条消息——这些动作背后&#xff0c;几乎每一次可靠的数据传输&#xff0c;都悄悄完成了一套标准流程&#xff1a;先互相确认身份、建立信任&#xff0c;再交换数…

2026/10/20 12:20:11 阅读更多 →
Java后端YOLO模型推理提速:FP32→FP16→INT8量化实战

Java后端YOLO模型推理提速:FP32→FP16→INT8量化实战

先说一次让我真正下决心做量化的经历。当时我在维护一个检测类Demo项目&#xff0c;服务端是纯Java&#xff0c;模型用的YOLO系轻量版本。功能倒是很快接完了&#xff0c;但性能怎么都压不下去&#xff1a;单张图像推理耗时接近80ms&#xff0c;QPS只有个位数&#xff0c;线上容…

2026/10/20 12:20:11 阅读更多 →
XSS攻击本质与全链路防御实战指南

XSS攻击本质与全链路防御实战指南

1. XSS不是“弹窗秀”&#xff0c;而是数据流的越界失控很多人第一次听说XSS&#xff0c;是在浏览器里看到一个突然弹出的alert("xss")——于是下意识觉得&#xff1a;“哦&#xff0c;就是让网页弹个框吓唬人”。这种理解偏差&#xff0c;恰恰是防御体系崩塌的第一道…

2026/10/20 12:20:11 阅读更多 →
AI写真的版权和肖像权:这4条必须写进交付说明

AI写真的版权和肖像权:这4条必须写进交付说明

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 12:20:11 阅读更多 →
teledart 机器人鸿蒙化适配:从云端到边缘节点的迁移实践

teledart 机器人鸿蒙化适配:从云端到边缘节点的迁移实践

前阵子我们团队把一套基于 teledart 的 Telegram 机器人自动化系统&#xff0c;从云端服务器整体迁移到了鸿蒙设备上。这套系统原本承担告警推送、定时巡检、远程指令执行这些运维工作&#xff0c;迁移的原因也很直接&#xff1a;希望让机器人能力真正落到边缘设备&#xff0c;…

2026/10/20 12:19:11 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →