ECB Oracle攻击实战:无需密钥逐字节破解加密秘密
大多数人第一次接触“ECB oracle attack”这个词都会先愣一下Oracle数据库其实这里的 Oracle 跟甲骨文数据库没有一毛钱关系它是密码学里的“预言机”Oracle——一个只会回答“是”或“否”的黑盒。而 ECB oracle attack 简单来说就是利用某个加密服务返回的密文或解密结果把一段本该保密的明文一个字节一个字节地抠出来。我第一次在 CTF 里跑通这套攻击的时候盯着屏幕上逐字节还原出来的 flag整个人是懵的原来不需要拿到密钥也能把一台加密服务的“判断结果”变成解密工具。这篇文章我会把 ECB 模式下最经典的 Oracle 攻击从头拆到尾先讲清楚 ECB 模式为什么天然容易泄漏信息再建立一个典型的攻击模型然后给出完整可复现的 Python 代码最后聊一聊它和更容易被混为一谈的 padding oracle attack 到底有什么区别以及防御侧的正确姿势。适合刚接触密码学攻击的 CTF 选手、写加密接口的后端开发以及所有想搞明白“为什么加密系统不能随便把错误细节吐给调用方”的人。1. 先从 ECB 最要命的特性说起相同明文块等于相同密文块1.1 分组密码与工作模式的关系要理解 ECB oracle attack首先要搞清楚一个基础概念像 AES 这样的分组密码每次只能加密固定长度的数据。AES-128 一次处理 16 字节也就是说不管你输入什么都会被切成 16 字节一块逐块加密。问题是真实数据长度不可能总是 16 的整数倍所以就有了各种“工作模式”和“填充方案”。ECBElectronic Codebook电子密码本是最原始、最直观的一种模式把明文切成 16 字节的块每一块独立用同一个密钥加密。说白了就是一把钥匙开一个块块与块之间毫无关联。正是这个“毫无关联”埋下了致命的隐患。我们来看一个最简单的例子。假设密钥固定加密函数E(key, block)是完全确定的。那么当明文里出现两个完全相同的 16 字节块时密文里也会出现两个完全相同的 16 字节块。这在 ECB 模式里是必然的也是检测 ECB 模式最经典的手段。1.2 ECB 的信息泄漏不只是“看起来重复”很多人觉得ECB 的问题只是密文有重复模式看起来不美观容易被看出来。其实远不止如此。因为块与块之间完全独立攻击者可以做两件很危险的事情重排攻击把密文块的位置调换解密端根本察觉不到解密结果里对应块的位置也会跟着调换。这在 CBC 等连锁模式下是不可想象的因为 CBC 里每个明文块都依赖前一个密文块。选择明文攻击如果服务端允许你控制一部分明文内容并且把你要保护的秘密拼接在里面一起加密那么你可以利用 ECB 的确定性通过精心构造输入让秘密的某个字节出现在一个块的特定位置然后枚举所有可能的取值观察哪一次密文块与目标密文块一致从而猜出这个字节。第二条就是 ECB oracle attack 的核心。攻击者不再是被动地“看”密文里的重复模式而是主动向服务器发起大量加密请求把服务器当成一个可以对明文做加密的 Oracle用密文的比对结果来推断秘密内容。1.3 为什么叫“Oracle”而不是“解密”这里需要澄清一个概念。密码学里的 Oracle 并不是指某个具体的算法而是指一个“黑盒接口”你给它输入它给你输出但你不能窥探内部状态。ECB oracle attack 里的 Oracle 通常是这样的攻击者提交一段可控数据input服务器在内部拼接input SECRET用一个固定密钥做 AES-ECB 加密然后返回完整密文你可能会问“这有什么好利用的我看到的只是密文又不知道密钥。”关键就在这里你不需要知道密钥。ECB 的确定性决定了只要input SECRET的某个 16 字节块与某个枚举值构造出的块完全一致加密结果就会一致。而服务器的加密函数是可重复调用的这给了攻击者无限次的猜测机会。想象一下如果服务器只允许你提交一次那确实没办法。但在真实场景里比如一个 Web 应用把“用户名 Cookie 标志”拼接后加密成令牌返回给前端你完全可以反复提交不同的用户名来观察密文变化。这就构成了一个实用攻击面。2. 攻击建模一个典型的 ECB Encryption Oracle 长什么样2.1 标准攻击模型为了把原理讲清楚我采用一个最常见的攻击模型几乎所有的 CTF 题目和真实场景都可以化归到这种形式plaintext user_input SECRET ciphertext AES_ECB_encrypt(pad(plaintext, 16))其中user_input完全由攻击者控制可以指定任意内容和长度SECRET是我们要恢复的目标字符串比如flag{...}或一个 session tokenpad是 PKCS#7 填充保证明文长度是 16 的倍数服务器把加密后的密文返回给攻击者这个模型在真实世界里很常见。很多服务会把“用户可控数据”和“签名/令牌/标志”拼在一起加密比如username role或者data hmac_secret。在 CTF 里它更是 ECB Oracle 题目的标准模板。2.2 攻击直觉把未知字节推到块的边缘我们已经知道ECB 加密时相同块产生相同密文。那么攻击者的核心目标就是构造两个明文它们除了目标字节之外某个块的内容完全相同。然后通过比较密文块是否一致来判断目标字节的取值。但问题是SECRET 的内容我们是不知道的它被拼接在 user_input 后面。我们怎么让“某个块的内容”可控呢答案是利用一个很巧妙的对齐技巧。假设我们要恢复 SECRET 的第一个字节SECRET[0]。我们发送user_input A * 15那么明文变成AAAAAAAAAAAAAAA S E C R E T { . . . 000000000000000 1 2 3 4 5 6 7 . . .第 0 个 16 字节块的内容是 15 个A加上SECRET[0]。这个块的前 15 个字节是我们自己控制的最后一个字节是未知的。接下来我们枚举所有可能的guess从 0 到 255或者只枚举可打印字符发送user_input A * 15 guess。此时明文变成AAAAAAAAAAAAAAA g u e s s . . .注意明文的前 16 个字节变成 15 个Aguess。如果guess SECRET[0]那么这一次加密的第 0 个块和刚才加密A * 15时得到的第 0 个块内容完全一致密文块也就完全一致。于是攻击者只需要做一件事比较两个密文的第 0 个块是否相等。相等就说明猜对了。2.3 逐字节推进恢复完整 SECRET第一个字节恢复之后第二个字节怎么办还是同样的思路只是让目标字节出现在块的最后一个位置。假设我们已经知道了前 1 个字节known SECRET[0]。要恢复SECRET[1]我们发送user_input A * 14。明文变成AAAAAAAAAAAAAA S E C R E T { . . .第 0 个块是 14 个ASECRET[0]SECRET[1]。前 15 个字节都是已知的了14 个 A 加已知的 SECRET[0]最后一个字节是 SECRET[1]。枚举时发送user_input A * 14 known guess也就是 14 个 A 加已知的 SECRET[0] 加猜测字节。如果 guess 正确那么这次明文的第 0 个块就和目标块完全一致。以此类推。恢复第 i 个字节时发送A * (15 - (i % 16))得到目标密文块枚举guess发送A * (15 - (i % 16)) known_prefix guess比较密文对应块是否相等当 i 跨过一个 16 字节边界时目标块会从第 0 块变成第 1 块、第 2 块……但这不影响原理只需要把比较的块索引相应移动即可。3. 全流程实战拆解从探测到完整 Exploit3.1 环境准备与假设为了让你能够直接复现我用 Python 写一个模拟的服务器加密函数然后再写攻击脚本。这里用pycryptodome库安装方式pip install pycryptodome注意核对一下库名老版本叫Crypto新版本统一用pycryptodome。模拟的服务端逻辑如下from Crypto.Cipher import AES from Crypto.Util.Padding import pad import os # 固定密钥真实场景中攻击者不知道 KEY os.urandom(16) SECRET bflag{ecb_oracle_byte_by_byte} def oracle_encrypt(user_input: bytes) - bytes: 模拟服务端接口 输入可控数据返回 AES-ECB 加密结果。 明文 user_input SECRET plaintext user_input SECRET cipher AES.new(KEY, AES.MODE_ECB) return cipher.encrypt(pad(plaintext, AES.block_size))这里把 SECRET 直接写死在代码里是为了演示。真实的攻击中你拿不到这段代码只能通过调用oracle_encrypt的返回值来推断。3.2 第一步确认漏洞存在拿到一个 ECB Oracle 接口第一件事不是直接开始逐字节爆破而是先确认几件事块大小block size是多少是否真的是 ECB 模式块大小可以通过一个很简单的办法探测不断加大user_input的长度观察密文长度什么时候发生变化。由于 PKCS#7 填充的存在明文长度达到 16 的倍数时不会额外填充超过后密文长度会跳变 16 字节。第一次跳变的增量通常就是块大小。def detect_block_size(): base_len len(oracle_encrypt(b)) for i in range(1, 48): cur_len len(oracle_encrypt(bA * i)) if cur_len ! base_len: return cur_len - base_len raise Exception(block size not detected)确认 ECB 模式则更简单发送至少 3 个块长度的相同输入看密文里有没有重复的块。ECB 模式下相同明文块必然产生相同密文块所以会出现明显的重复。def detect_ecb(block_size: int) - bool: # 发送 3 个块长度的相同字符ECB 模式下必然出现重复块 ct oracle_encrypt(bA * (block_size * 3)) blocks [ct[i:i block_size] for i in range(0, len(ct), block_size)] return len(blocks) ! len(set(blocks))如果返回 False说明大概率不是简单的 ECB需要换思路。对于本篇的模型我们假设确认结果是 True。3.3 第二步逐字节恢复的主循环确认漏洞后就可以写主攻击脚本了。核心逻辑就是前面讲的让目标未知字节恰好处于块的最后一位枚举猜测比较密文块。def recover_secret(block_size: int) - bytes: recovered b # 通过空输入和 pad 长度估算 SECRET 最大长度避免死循环 max_secret_len len(oracle_encrypt(b)) - block_size # 减去至少一个填充块 if max_secret_len 0: max_secret_len len(oracle_encrypt(b)) for idx in range(max_secret_len): # 填充长度让 SECRET[idx] 成为某个块的最后一个字节 pad_len (block_size - 1 - (idx % block_size)) % block_size filler bA * pad_len # 目标块在 oracle(filler) 的密文中SECRET[idx] 所在的块 target_ct oracle_encrypt(filler) target_block_index idx // block_size target_block target_ct[target_block_index * block_size: (target_block_index 1) * block_size] matched False for guess in range(256): # 构造候选明文filler 已恢复前缀 猜测字节 candidate filler recovered bytes([guess]) candidate_ct oracle_encrypt(candidate) # 候选明文长度正好是 (idx//block_size 1) 个块的场景下 # 与目标块对应的是第 idx//block_size 块 if candidate_ct[target_block_index * block_size: (target_block_index 1) * block_size] target_block: recovered bytes([guess]) matched True break if not matched: # 没有匹配说明 SECRET 已经结束或进入填充区域 break return recovered这里面有一个值得仔细琢磨的细节为什么候选明文的目标块索引同样是idx // block_size我们分两种情况看。当idx还比较小比如前 16 个字节内filler长度是15 - idxrecovered长度是idx再加上 1 个猜测字节候选明文的长度正好是15 - idx idx 1 16。这时候加密结果只有一个块所以它必然就是我们要比较的那一个块。更一般地说当idx q*16 r时filler长度 15 - rrecovered长度 q*16 r候选明文总长度 (15 - r) (q*16 r) 1 (q1)*16正好是q1个整数块。其中最后一个块的内容就是“15 个已知字节 guess”。而目标密文中的目标块是前q1个块里的第q块从 0 开始数。两者对应上了。这也解释了为什么在构造 candidate 时不需要额外再补填充它的长度天然就是 16 的倍数guess 恰好落在块尾后面没有其他数据干扰。3.4 完整攻击代码与实测结果把上面的检测和恢复合并起来就是一个完整的 exploitfrom Crypto.Cipher import AES from Crypto.Util.Padding import pad import os # ---------- 模拟服务端 ---------- KEY os.urandom(16) SECRET bflag{ecb_oracle_byte_by_byte} def oracle_encrypt(user_input: bytes) - bytes: plaintext user_input SECRET cipher AES.new(KEY, AES.MODE_ECB) return cipher.encrypt(pad(plaintext, AES.block_size)) # ---------- 攻击脚本 ---------- def detect_block_size(): base_len len(oracle_encrypt(b)) for i in range(1, 48): cur_len len(oracle_encrypt(bA * i)) if cur_len ! base_len: return cur_len - base_len raise Exception(block size not detected) def detect_ecb(block_size: int) - bool: ct oracle_encrypt(bA * (block_size * 3)) blocks [ct[i:i block_size] for i in range(0, len(ct), block_size)] return len(blocks) ! len(set(blocks)) def recover_secret(block_size: int) - bytes: recovered b max_secret_len len(oracle_encrypt(b)) - block_size if max_secret_len 0: max_secret_len len(oracle_encrypt(b)) for idx in range(max_secret_len): pad_len (block_size - 1 - (idx % block_size)) % block_size filler bA * pad_len target_ct oracle_encrypt(filler) target_block_index idx // block_size target_block target_ct[target_block_index * block_size: (target_block_index 1) * block_size] matched False for guess in range(256): candidate filler recovered bytes([guess]) candidate_ct oracle_encrypt(candidate) if candidate_ct[target_block_index * block_size: (target_block_index 1) * block_size] target_block: recovered bytes([guess]) matched True break if not matched: break return recovered if __name__ __main__: bs detect_block_size() print([*] block size:, bs) print([*] is ECB?, detect_ecb(bs)) secret recover_secret(bs) print([*] recovered:, secret)我在本地跑这段代码输出是这样的[*] block size: 16 [*] is ECB? True [*] recovered: bflag{ecb_oracle_byte_by_byte}整个过程大概需要256 * SECRET长度次加密请求。对于 32 字节的 SECRET就是 8192 次请求在本地模拟下几乎是瞬间完成。真实网络环境下如果每次请求有 100ms 延迟大约需要十几分钟依然是一个完全可行的攻击窗口。3.5 容易踩的坑第一个坑是枚举范围。如果只枚举可见 ASCII 字符遇到 SECRET 包含不可见字符或非 ASCII 内容时会失败。所以我上面的示例直接跑了 0-255 的全范围。如果确定目标是 ASCII flag可以缩小范围来提速但不要一开始就依赖这个假设。第二个坑是停止条件。我的脚本用max_secret_len len(oracle_encrypt(b)) - block_size来估算 SECRET 长度上限但这是基于空输入时明文恰好是 SECRET padding 的假设。如果 SECRET 长度正好是 16 的倍数空输入加密后多出的一个块其实是完整填充块此时上限会偏大一个块但没关系多跑的循环会在“没有匹配”时自动 break不会影响结果。第三个坑是块索引。很多初学者在写候选密文比较时喜欢用“最后一个块”或者“固定第 0 块”这会在 SECRET 长度超过 16 字节后失效。正确的做法是像我这样用idx // block_size来动态定位目标块。这个索引在user_input SECRET模型下是精确的。4. 容易混淆的邻近攻击ECB oracle 和 CBC padding oracle 到底差在哪4.1 另一个同样带 Oracle 的著名攻击安全圈里提到 Oracle attack很多人第一时间想到的是 padding oracle attack。它确实非常有名曾经攻破过大量使用 CBC 模式且泄露填充错误信息的应用。但必须强调经典的 padding oracle attack 主要针对 CBC 模式而不是 ECB 模式。padding oracle attack 的场景通常是这样的。服务端在解密一段 CBC 密文后会检查 PKCS#7 填充是否合法并且把检查结果通过不同的报错信息、响应时间或 HTTP 状态码反馈给攻击者。攻击者利用这个“填充是否合法”的二元回答通过修改密文的前一块来逐字节控制解密中间值最终恢复出明文。关键点在于CBC 模式下解密当前块明文时有这样一个性质P[i] D(C[i]) XOR C[i-1]攻击者固定住目标密文块C[i]篡改前一块C[i-1]就可以直接控制P[i]的字节。而D(C[i])是固定的未知中间值。当篡改后的C[i-1]让P[i]的最后一个字节恰好变成合法的0x01时填充校验通过攻击者就能反推出中间值的最后一个字节。4.2 为什么 ECB 模式套用不了同样的方法对比之下ECB 模式解密时P[i] D(C[i])没有前一块参与。攻击者如果单独修改某个密文块解密得到的明文块变化是完全不可控的因为D()是一个强伪随机置换密文上的任何一个比特翻转都会让解密结果像雪花一样散开无法以可预测的方式控制填充字节。换句话说ECB 模式下攻击者没有“前一块”这个杠杆可以用来精确拨动明文字节。所以在纯 ECB 的解密场景里经典的 padding oracle attack 并不成立。ECB 的问题是块与块之间的独立性和确定性而不是填充校验的错误反馈。4.3 两种攻击的共同点都是利用“反馈”当情报虽然 ECB oracle attack 和 CBC padding oracle attack 在机制上完全不同但它们在更高层面上共享同一个哲学不要把任何形式的判断结果轻易暴露给调用方。ECB oracle attack 利用的是“密文比较结果”——攻击者自己就能看到密文不需要服务器报错。CBC padding oracle attack 利用的是“填充校验结果”——服务器必须把成功与否反馈出来哪怕只是一个 500 错误。这两种攻击都提醒我们加密算法本身可能没有漏洞但模式选择、错误处理、接口设计上的疏忽会让本来“安全”的算法变成攻击者的玩具。5. 防御视角为什么 AEAD 是正解哪些“加固”只是安慰剂5.1 不要试图给 ECB 打补丁有人可能会想那我在 ECB 前面加个随机 IV 行不行没用。ECB 根本没有 IV 的概念。有人想那我给每个块加不同的随机偏移那其实就变成 CTR 模式或者 CBC 了已经不是 ECB。还有人想我不返回完整密文只返回哈希那业务逻辑可能就不成立了而且哈希同样可能被离线爆破。问题的根源在于 ECB 模式本身就不适合加密长度超过一个块的数据。它没有扩散性块与块之间孤立既不能掩盖模式也不能抵抗重排。任何试图通过外层补丁来挽救 ECB 的做法都是在跟密码学的基本原理较劲不如直接换模式。5.2 现代方案AEAD 或者 Encrypt-then-MAC对于新系统最稳妥的选择是使用认证加密AEAD比如 AES-GCM 或 ChaCha20-Poly1305。AEAD 同时提供机密性和完整性保护密文稍有篡改解密时就会校验失败而且不会把“是填充错误还是 MAC 错误”这种细节暴露给调用方。如果你的系统仍然依赖 CBC 这类老模式那就必须遵循 Encrypt-then-MAC 的铁律先对密文计算 MAC解密前先验证 MAC验证失败返回统一的“解密失败”完全不要进入填充校验逻辑。这样既能防 padding oracle也能在相当程度上阻断对密文的主动篡改。5.3 接口层的三个硬性要求从更落地的角度我在做安全评审时通常会检查三件事解密失败的错误信息是否统一。不要出现“Padding is invalid”和“MAC mismatch”这种区分度极高的报错更不要把堆栈信息直接返回给前端。加密接口是否允许攻击者自由控制输入长度和位置。如果业务确实需要拼接用户数据尽量把用户数据放在最后并且限制长度至少提高攻击成本。是否使用经过审计的密码学库封装好的高层 API。比如直接用cryptography库里的AESGCM而不是自己拼Crypto.Cipher加手动填充。这三条做不到即使换了 GCM也可能在其他地方重新开一个口子。安全不是一个算法的事而是整个数据通路的设计问题。6. 实战感悟与扩展思路最后分享一点我自己的体会。当年第一次完整跑通 ECB oracle attack 的时候我心里其实是很震惊的。震惊的点不在于“爆破”本身而在于这个攻击完全不依赖任何数学上的困难问题它纯粹是模式设计和接口设计组合出来的漏洞。AES 本身没有被攻破密钥也没有泄漏但攻击者照样拿到了完整明文。这件事给我留下了很深的印象写加密代码的时候一定要想清楚“攻击者能拿到什么反馈”。加密接口返回密文这本身就是一种反馈解密接口返回错误又是一种反馈。只要反馈里有哪怕一比特的信息就可能被攻击者当预言机用。如果你还想继续深入我建议从这几个方向扩展把攻击模型从user_input SECRET改成PREFIX SECRET user_input。这种模型在真实 Web 题目里更常见攻击思路相同但需要先探测 PREFIX 的长度多一个对齐步骤。研究同样是 ECB 但方向相反的“剪贴攻击”cut-and-paste attack。它不恢复秘密而是通过移动密文块来伪造一个合法的明文结构比如把普通用户的 role 字段替换成 admin。把脚本改成通过requests打真实 HTTP 接口你会发现网络延迟对爆破耗时有巨大影响优化请求并发就成了实际工程问题。ECB oracle attack 看起来像是一个 CTF 里的小把戏但它背后涉及的“预言机思维”在真实的安全研究里无处不在。希望这篇文章能帮你把这个思维模型真正建立起来。

相关新闻

从images_xmls到yolov5:三轮车违规停放数据集转换与训练实战

从images_xmls到yolov5:三轮车违规停放数据集转换与训练实战

简介:面向YOLOv5机器视觉识别与非机动车违规停放场景的三轮车标注数据集分包,当前压缩包收录的是三轮车类别中tricycle1子类的全部数据,共957张JPEG原图与953个XML标注文件,文件总数1910个,压缩包大小82.19MB。图片与标…

2026/10/5 9:11:49 阅读更多 →
AI大模型知识管理落地指南:从RAG到本地部署避坑实践

AI大模型知识管理落地指南:从RAG到本地部署避坑实践

简介:这份PPT是一份面向企业知识管理负责人、IT架构师及AI应用团队的解决方案演示文稿,聚焦AI大模型与知识图谱协同,解决知识推理生成、语义理解、多模态数据处理及企业级知识服务等核心问题。整份PPT为1个pptx文件,压缩包仅426KB…

2026/10/5 9:10:49 阅读更多 →
Browser Use:AI大模型驱动的浏览器自动化框架,自然语言操控浏览器

Browser Use:AI大模型驱动的浏览器自动化框架,自然语言操控浏览器

1. 浏览器自动化这个老问题,终于等来了一个像样的解法 做Web自动化的人都有一个共同的痛:写爬虫要跟反爬机制斗智斗勇,用Selenium要跟元素定位和等待时间反复拉扯,上Playwright虽然好了不少,但遇到动态渲染、多步骤交互…

2026/10/5 9:10:49 阅读更多 →

最新新闻

安卓逆向学习路线:从应用层分析到Native层对抗

安卓逆向学习路线:从应用层分析到Native层对抗

这几年时不时就有人跑来问我:安卓逆向怎么学?是不是得会汇编?要不要先学破解?也有人直接在搜索框里敲“android 逆向学习路线”“安卓逆向教程”,然后被一堆零散的资料劝退。作为常年在这行折腾的人,我太清…

2026/10/5 9:45:38 阅读更多 →
STC8H硬件IIC驱动OLED屏:主从关系、初始化与实战排错指南

STC8H硬件IIC驱动OLED屏:主从关系、初始化与实战排错指南

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

2026/10/5 9:45:38 阅读更多 →
如何读懂芯片时序图并写出可靠驱动代码?从时序图到嵌入式驱动开发实战

如何读懂芯片时序图并写出可靠驱动代码?从时序图到嵌入式驱动开发实战

1. 为什么时序图是驱动开发的“翻译蓝本”干了这么多年嵌入式驱动,我见过太多人拿到芯片手册直接翻寄存器表,抄一段网上的例程就跑,跑不通就抓瞎。说句实在话,芯片手册里最值得反复琢磨的既不是引脚定义,也不是寄存器位…

2026/10/5 9:45:38 阅读更多 →
从Q-Learning到DQN:深度强化学习实战解析与代码实现

从Q-Learning到DQN:深度强化学习实战解析与代码实现

1. 为什么深度学习能在决策问题上发力:从Q-Learning到DQN的认知跃迁先纠正一个常见的误区:DQN不是"用神经网络替换Q表"这么简单。如果你只把它理解成查表方式的升级版,后面遇到的收敛困难、训练震荡、奖励炸掉这些问题,…

2026/10/5 9:45:38 阅读更多 →
AgentKit模型网关实战:统一多模型接入、路由与治理

AgentKit模型网关实战:统一多模型接入、路由与治理

我最早接触模型网关这个概念,不是因为赶时髦,而是被真实的混乱逼的。当时手头一个项目要同时接三家模型服务——对话用一家,轻量任务用另一家,偶尔还要切到第三家做对比评测。结果就是代码里堆满了分支判断,每个模型一…

2026/10/5 9:45:38 阅读更多 →
OpenRig 开放式机架主机,从选材到组装的完整 DIY 指南

OpenRig 开放式机架主机,从选材到组装的完整 DIY 指南

组装过几台 OpenRig 之后,我发现这个项目比想象中成熟得多。OpenRig 不是什么新概念,它是一套开源的开放式机架主机方案,简单说就是把传统机箱的侧板、前面板和顶盖全部去掉,用铝型材搭出一个开放测试平台,让主板、显卡…

2026/10/5 9:44:38 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

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

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

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

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 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/4 11:40:45 阅读更多 →
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/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练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/4 20:14:29 阅读更多 →