From 379e9b58ae1d20511d2db218a41041ee1e64a922 Mon Sep 17 00:00:00 2001 From: luksgrin Date: Sat, 21 May 2022 21:39:04 +0200 Subject: [PATCH] Added challenge 5 --- contracts/N5-BecomeMaster-medium.sol | 50 +++++++++++++++++++++++++ contracts/hacks/N5-BecomeMasterhack.sol | 14 +++++++ scripts/N5-BecomeMasterExploit.js | 36 ++++++++++++++++++ test/N5-BecomeMaster-medium.js | 17 +++++++++ 4 files changed, 117 insertions(+) create mode 100644 contracts/N5-BecomeMaster-medium.sol create mode 100644 contracts/hacks/N5-BecomeMasterhack.sol create mode 100644 scripts/N5-BecomeMasterExploit.js create mode 100644 test/N5-BecomeMaster-medium.js diff --git a/contracts/N5-BecomeMaster-medium.sol b/contracts/N5-BecomeMaster-medium.sol new file mode 100644 index 0000000..7277a36 --- /dev/null +++ b/contracts/N5-BecomeMaster-medium.sol @@ -0,0 +1,50 @@ +// Props to band0x for this amazing CTF +// I think we could upload this one as is, unless someone thinks otherwise +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.11; + +contract N5BecomeMaster { + mapping(address => uint256) allocations; + address public admin; + address public master; + address caller; + + constructor() payable { + master = msg.sender; + } + + modifier onlyMaster() { + require(master == tx.origin, "caller is not the master"); + _; + } + modifier onlyContract() { + require(msg.sender != tx.origin, "caller is not the master"); + _; + } + modifier onlyAdmin() { + require(admin == tx.origin, "caller is not the Admin"); + _; + } + + function allocate() public payable { + allocations[caller] = allocations[caller] += (msg.value); + admin = tx.origin; + } + + function sendAllocation(address payable allocator) public { + require(allocations[allocator] > 0); + allocator.transfer(allocations[allocator]); + } + + function takeMasterRole() public onlyAdmin onlyContract { + master = admin; + } + + function collectAllocations() public onlyMaster onlyContract { + payable(msg.sender).transfer(address(this).balance); + } + + function allocatorBalance(address allocator) public view returns (uint256) { + return allocations[allocator]; + } +} diff --git a/contracts/hacks/N5-BecomeMasterhack.sol b/contracts/hacks/N5-BecomeMasterhack.sol new file mode 100644 index 0000000..d643146 --- /dev/null +++ b/contracts/hacks/N5-BecomeMasterhack.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.11; + +import "../N5-BecomeMaster-medium.sol"; + +contract N5ExploitHack { + constructor(N5BecomeMaster instance) payable { + // Complete with your own code + } + + function finalize() external { + // can be used to finalize the exploit patten + } +} diff --git a/scripts/N5-BecomeMasterExploit.js b/scripts/N5-BecomeMasterExploit.js new file mode 100644 index 0000000..52441fd --- /dev/null +++ b/scripts/N5-BecomeMasterExploit.js @@ -0,0 +1,36 @@ +const hre = require("hardhat"); +const ethers = hre.ethers; +const CHALLENGES = require("../challenge-addresses.js") + +const challengeAddress = CHALLENGES.N5BecomeMaster; +const ETH_UNIT = ethers.utils.parseEther("0.0001"); + +async function main() { + // command to run against fork + // npx hardhat run scripts/N5-BecomeMasterExploit.js + + // command to run against real network + // npx hardhat run scripts/N5-BecomeMasterExploit.js --network mumbai + + /*let challengeInstance = await ethers.getContractFactory("N5BecomeMaster"); + challengeInstance = await challengeInstance.deploy({ value: ETH_UNIT }); + await challengeInstance.deployed();*/ + const challengeInstance = await ethers.getContractAt( + "N5BecomeMaster", + challengeAddress + ); + + /* ------> user solution code starts here */ + + /* ------> user solution code ends here */ + + console.log(`Challenge balance `, await ethers.provider.getBalance(challengeInstance.address)); + +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/test/N5-BecomeMaster-medium.js b/test/N5-BecomeMaster-medium.js new file mode 100644 index 0000000..80cfda6 --- /dev/null +++ b/test/N5-BecomeMaster-medium.js @@ -0,0 +1,17 @@ +const { expect } = require("chai"); + +const CHALLENGES = require("../challenge-addresses.js") +const challengeAddress = CHALLENGES.N5BecomeMaster; + + +// run the test +// npx hardhat test ./test/N5-BecomeMaster-medium.js --network mumbai +describe("CTF #5 BecomeMaster", function () { + it("Should recover all funds", async function () { + const challengeInstance = await ethers.getContractAt( + "N5BecomeMaster", + challengeAddress + ); + expect(await ethers.provider.getBalance(challengeInstance.address)).to.equal("0"); + }); +});