JayPeggers 攻击分析

UTU 2022 年 12 月 29 日 5 时(北京时间 13 时),以太坊主网上的 JayPeggers 协议遭到重入攻击,损失约 15 ETH。随后攻击者通过 Tornado.CashAztec 转移被盗资金。

分析

首先,攻击合约从 Vault(0xba12222222228d8ba445958a75a0704d566bf2c8) 获得借出 72.5 WETH 的代币余额,然后从 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 利用 withdraw 函数取出。至此,攻击者通过闪电贷获得了起始资金。

接着调用了 buyJay,关键在于计算铸币数量的 ETHtoJAY 函数,它是用 代币总量/ETH 总量,计算代币价格的。这次只是通过 22 WETH 购买了 13584899853779845952188 Jay 代币。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function buyJay(
        address[] calldata erc721TokenAddress,
        uint256[] calldata erc721Ids,
        address[] calldata erc1155TokenAddress,
        uint256[] calldata erc1155Ids,
        uint256[] calldata erc1155Amounts
    ) public payable {
        require(start, "Not started!");
        uint256 total = erc721TokenAddress.length;
        if (total != 0) buyJayWithERC721(erc721TokenAddress, erc721Ids);

        if (erc1155TokenAddress.length != 0)
            total = total.add(
                buyJayWithERC1155(
                    erc1155TokenAddress,
                    erc1155Ids,
                    erc1155Amounts
                )
            );

        if (total >= 100)
            require(
                msg.value >= (total).mul(sellNftFeeEth).div(2),
                "You need to pay ETH more"
            );
        else
            require(
                msg.value >= (total).mul(sellNftFeeEth),
                "You need to pay ETH more"
            );

        _mint(msg.sender, ETHtoJAY(msg.value).mul(97).div(100));

        (bool success, ) = dev.call{value: msg.value.div(34)}("");
        require(success, "ETH Transfer failed.");

        nftsSold += total;

        emit Price(block.timestamp, JAYtoETH(1 * 10**18));
    }

1
2
3
function ETHtoJAY(uint256 value) public view returns (uint256) {
    return value.mul(totalSupply()).div(address(this).balance.sub(value));
}

攻击者第二次调用 ETHtoJAY 函数,这次用 50.5 ETH 铸造了 4313025058290613910965927 Jay 代币。

1
2
3
4
5
6
7
8
9
10
11
{
  "erc721TokenAddress": [
    "0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340"
  ],
  "erc721Ids": [
    "0"
  ],
  "erc1155TokenAddress": [],
  "erc1155Ids": [],
  "erc1155Amounts": []
}

可以知道,售卖的 NFT 是一个攻击者自定义的 ERC721 合约,实际上没有任何价值,只是用来通过第 10 行的 buyJayWithERC721 重入的。

JayPeggers 攻击分析

sell 函数中,计算 eth 的逻辑如下:

1
2
3
function JAYtoETH(uint256 value) public view returns (uint256) {
    return (value * address(this).balance).div(totalSupply());
}

这时 address(this).balance 已经因为传入了 50.5 WETH 而增大了,但是buyJay 中的 _mint 函数中的 _totalSupply 还没变化,因此造成了价格操控。

 

原文始发于learner L:JayPeggers 攻击分析

版权声明:admin 发表于 2022年12月30日 上午9:23。
转载请注明:JayPeggers 攻击分析 | CTF导航

相关文章

暂无评论

暂无评论...