链上交易分析实战:从 MEV Bot(BNB48)攻击事件手写 POC——WTF-Solidity 合约安全专题
2026/9/15 19:59:08 网站建设 项目流程

链上交易分析实战:从 MEV Bot(BNB48)攻击事件手写 POC——WTF-Solidity 合约安全专题

【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程,供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity

导读

本文基于 WTF-Solidity 仓库中「链上交易调试」系列的第四讲,以 2022 年 9 月 13 日 BNB Chain 上一个 MEV Bot(BNB48 验证节点)被洗劫约 14 万美元的真实事件为案例,完整走一遍「收集情报 → 交易可视化分析 → 反编译未开源合约 → 定位漏洞根因 → 编写并复现 POC → Foundry 追踪/调试验证」的链上攻防闭环。读完本文,你将掌握如何对一个未开源、未验证的链上合约进行逆向分析,并具备独立编写攻击复现(Proof of Concept)合约、用 Foundry 在本地 fork 环境中回放真实攻击交易的能力。


一、事件前情:一场发生在 MEV Bot 上的攻击

1.1 事件回顾

2022 年 9 月 13 日(20220913),一个运行在 BNB Chain 上的MEV Bot(最大可提取价值机器人)被攻击者利用漏洞,将合约上的全部资产转走,总损失约14 万美元($140K)。MEV Bot 通常部署了自动套利/抢跑逻辑,合约中往往沉淀着多种代币资产,是链上攻击者的高价值目标。

1.2 关键点:攻击者如何隐藏交易

  • 攻击者通过BNB48 验证节点发送隐私交易(Private Transaction)
  • 这与 Flashbots 的思路类似——不把交易放入公开 mempool,从而避免被其他 MEV 机器人或套利者「抢跑(Front-running)」拦截。

关于抢跑攻击的原理,可参考 WTF-Solidity 的安全专题 S11 抢先交易;关于闪兑/闪电贷的回调机制,可参考 57 闪电贷。


二、第一步:用 Phalcon 还原攻击交易全貌

攻击者的交易 ID(TXID)为:

0xd48758ef48d113b78a09f7b8c7cd663ad79e9965852e872fdfc92234c3e598d2

关键事实:MEV Bot 合约未验证、未开源。那攻击者是怎么利用它的?我们从交易可视化工具入手。

2.1 资金流:6 种资产被转走

使用 BlockSec 的Phalcon交易分析工具查看这笔交易:

  • 金流(fund flow)部分可以看到:MEV Bot 在这笔交易中把6 种资产全部转移到了攻击者的钱包;
  • 进一步观察Function call 调用流程,发现pancakeCall函数恰好被调用了 6 次——与被转走的资产种类数一致,说明攻击是围绕 PancakeSwap 闪兑回调展开的。

2.2 三方地址速查

角色地址
交易发起方(From / msg.sender)0xee286554f8b315f0560a15b6f085ddad616d0601
攻击者合约0x5cb11ce550a2e6c24ebfc8df86c5757b596e69c1
MEV Bot 合约(受害者)0x64dd59d6c7f09dc05b472ce5cb961b6e10106e1d

2.3 展开一次pancakeCall回调

展开其中一次pancakeCall调用可以看到:

  1. 回调进入攻击者合约,攻击者合约读取了token0()的值,返回BSC-USD
  2. 紧接着执行了transfer,把BSC-USD 转到了攻击者的钱包

至此可以得出结论:攻击者要么拥有权限,要么利用了漏洞,把 MEV Bot 合约上的资产全部搬空。下一步的关键问题是——攻击者到底是怎么利用的?


三、第二步:反编译未开源合约,定位漏洞根因

由于 MEV Bot 合约未开源,我们使用「链上交易调试」系列第一课中介绍过的反编译工具Dedaub进行分析。

3.1 反编译流程

  1. 到 BscScan 上打开 MEV Bot 合约地址的#code页面,复制合约 Bytecode
  2. 把 Bytecode 粘贴到 Dedaub 反编译器中,点击 Decompile;
  3. 阅读反编译出的伪代码,寻找可疑逻辑。

反编译工具(Etherscan 内置反编译、Dedaub、heimdall-rs 等)的详细介绍,见 01_tools 链上分析工具清单。

3.2 反编译结果:公共回调 + 可疑内部函数

反编译结果揭示了两个关键事实:

  1. pancakeCall函数权限是public——任何人都可以调用它。在闪电贷(闪兑)场景中,回调函数公开本身是正常设计,通常不是问题;
  2. 但函数体里执行了一个内部函数0x10a(即 selector 为0x10a的内部逻辑块),这里就是需要继续追踪的可疑点。

3.3 追踪0x10a:漏洞的真正位置

继续追0x10a的逻辑,反编译代码显示:

  1. 先读取攻击者合约上的token0是什么代币
  2. 然后把该代币带入转账函数transfer
  3. transfer中,第一个参数接收者地址address(MEM[varg0.data])来源于pancakeCallvarg3(即_data参数),完全由调用者控制

漏洞根因就在这里:MEV Bot 的pancakeCall回调内部,使用「攻击者提供的_data中的地址」作为transfer的接收方,并配合「从攻击者合约读取的token0」作为代币地址——两个参数全部可控,等价于任何人都能指定任意代币、任意收款地址,从 Bot 合约转走资产。

3.4 回看攻击 payload:_data前 32 字节 = 收款地址

回头分析攻击者调用pancakeCall的输入数据(payload):

  • _data参数中,前 32 字节就是收款方的钱包地址
  • 后 32 字节通常为token0代币地址。

也就是说,攻击者只需要构造_data = abi.encode(收款地址, token0地址)再调用公开的pancakeCall,就能触发 MEV Bot 把自身合约里的 BSC-USD 等 6 种代币全部转给自己。


四、第三步:编写 POC 攻击复现合约

完成上述分析后,编写 POC 的逻辑就非常清晰了:

  1. 调用 MEV Bot 合约的pancakeCall
  2. 带入对应参数,关键是_data指定收款钱包地址
  3. 攻击合约自身必须提供token0()token1()函数,以满足 MEV Bot 合约内部读取 token0 的逻辑。

4.1 POC 核心骨架

// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; import "forge-std/Test.sol"; // 关键地址 address constant MEV_BOT = 0x64dd59d6c7f09dc05b472ce5cb961b6e10106e1d; // 受害者 MEV Bot address constant ATTACKER = 0x5cb11ce550a2e6c24ebfc8df86c5757b596e69c1; // 攻击者钱包 interface IMEVBot { // 注意:pancakeCall 为 public,任何人都可调用 function pancakeCall(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external; } contract Exploit { address public token0; // 满足 MEV Bot 读取 token0() 的逻辑 address public token1; // 满足 MEV Bot 读取 token1() 的逻辑 constructor(address _token0, address _token1) { token0 = _token0; // 例如 BSC-USD 地址 token1 = _token1; } function attack() external { // 构造 _data:前 32 字节是收款地址(即本攻击合约/指定钱包) bytes memory data = abi.encode(ATTACKER, token0); // 直接调用公开的 pancakeCall,无需经过任何闪兑 IMEVBot(MEV_BOT).pancakeCall(address(this), 0, 0, data); } }

4.2 POC 关键点总结

要素说明
调用对象MEV Bot 的pancakeCall(address, uint256, uint256, bytes)
关键参数_data前 32 字节 = 收款地址,完全可控
必备函数攻击合约需实现token0()token1()以通过 Bot 内部逻辑
攻击成本单笔交易,无抵押、无需闪电贷,直接公开调用即可

动手建议:自己先按上面的逻辑写一遍,再对照官方 POC 参考(DeFiHackLabs 仓库中的BNB48MEVBot_exp.sol)核对,效果最佳。


五、进阶:用 Foundry 追踪与调试真实攻击交易

除了编写 POC 外,还可以直接使用Foundry对链上真实交易进行函数级追踪与逐步调试。这是「链上交易调试」系列第二课中讲解的 Foundry 工作流的一部分。

5.1 安装与配置 Foundry

  • 按 Foundry Book 安装说明 安装forge/cast
  • WTF-Solidity 仓库根目录的 foundry.toml 已统一配置solc = "0.8.34"libsremappingsforge-std、OpenZeppelin),并说明「仅对根目录 test/ 运行测试」,子项目按各自配置编译。

5.2 Foundry 追踪函数调用(trace)

使用cast run直接重放攻击交易,并列出函数调用轨迹:

cast run 0xd48758ef48d113b78a09f7b8c7cd663ad79e9965852e872fdfc92234c3e598d2 --quick --rpc-url https://rpc.ankr.com/bsc
  • --quick:跳过部分校验、加速重放;
  • --rpc-url:指定 BSC 的 RPC 端点(示例使用 ankr 公共 RPC);
  • 输出为该交易内部完整的函数调用栈(traces),可直观看到 6 次pancakeCall的嵌套关系与参数。

5.3 Foundry 交互式调试(debug)

若需要逐条指令/逐函数地查看状态变化、存储读写,使用--debug模式:

cast run 0xd48758ef48d113b78a09f7b8c7cd663ad79e9965852e872fdfc92234c3e598d2 --quick --debug --rpc-url https://rpc.ankr.com/bsc

在 debug 交互界面中:

  • 按提示单步执行 EVM 指令;
  • 结合foundry.toml中配置的 RPC,核对每一步的存储(storage)、余额变化;
  • 使用labelcheatcode(在测试合约中调用cheat.label(addr, "name"))给地址打标签,提升可读性——这也是本系列前几课中推荐的实践。

需要注意:cast run回放依赖 RPC 提供历史区块状态,公共 RPC 可能限制历史数据;生产分析建议使用支持归档节点(archive node)的 RPC 端点。


六、本案例的经验教训与安全检查清单

  1. 闪电贷/闪兑回调中的任意参数传递是重灾区:回调函数即使是公开设计,其内部对_data的解析必须严格校验(如白名单代币、固定收款方);
  2. 未开源合约不等于安全:通过反编译工具(Dedaub 等)可以低成本还原关键逻辑;
  3. 「token 地址来自对方合约 + 收款地址来自 calldata」的组合等于把资产处置权交给调用者,属于典型的函数级访问控制缺失/参数注入漏洞;
  4. MEV Bot 资金集中的风险:合约中沉淀的多币种资产使其成为高价值攻击目标,应使用多签、限流、权限控制等机制。

七、相关资源与继续学习路径

  • 链上交易调试:01 工具篇(Phalcon / Tenderly / Dedaub / 签名数据库等)
  • 链上交易调试:02 热身篇(Foundry cheatcodes、闪兑模拟)
  • 链上交易调试:03 手写 POC——预言机价格操纵(闪贷 + 预言机操纵的完整 POC 流程)
  • 57 闪电贷(Uniswap V2/V3、AAVE V3 闪贷合约与 Foundry 测试)
  • S11 抢先交易(Front-running 原理与示例)

MEV 与订单流市场背景可参考:《Flashbots: Kings of The Mempool》《MEV Markets》系列(PoW / PoS / Payment for Order Flow)。

【免费下载链接】WTF-SolidityWTF Solidity 极简入门教程,供小白们使用。Now supports English! 官网: https://wtf.academy项目地址: https://gitcode.com/GitHub_Trending/wt/WTF-Solidity

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询