In this workshop we'll practice hacking & exploitation of Solidity/EVM smart contracts. During the workshop we'll solve challenges from CaptureTheEther and OpenZeppelin Ethernaut usign Mythril and Scrooge McEtherface and do a little frontrunning exercise. The flattened source code for all challenges is available in the code directory.
Check out the DEF CON 27 writeup for some background.
Here's how to get set up for the workshop. It should be super easy except if you're using Windows (you need Node.js and a Python 3 environment).
If you run into insurmountable problems ask the instructors for help. There's also a dedicated Discord channel that we created exclusively for you, the valued workshop participant.
Ganache is a local Ethereum development server. Install it with npm:
$ npm i -g ganache-cli
Install Mythril from Pypi:
$ pip3 install mythril
Make sure you have Mythril v0.21.15 or higher installed.
$ myth version
Mythril version v0.21.15
If you can't get this to work you can use the Docker image instead (see docs, note however that the below tools won't work then.
Mythril uses solc to compile Solidity files, so you'll need to install that as well.
To install Scrooge, clone the Github repo to install the required packages into a Python 3 environment:
$ git clone https://github.com/b-mueller/scrooge-mcetherface
$ cd scrooge-mcetherface
$ pip3 install -r requirements.txt
Setup config.ini
for Ganache:
[settings]
rpc = http://localhost:7545
sender = 0xf4a60CbD6C43418c71389d8a0D98a9A356609761
symbolic_tx_count = 3
timeout = 300
gasprice = 3000000000
Theo has a PyPI package:
$ pip install --user theo --upgrade
Or you can just clone the repo and install it:
$ git clone https://github.com/cleanunicorn/theo
$ cd theo
$ pip install -e .
In the first example we'll focus on killing smart contracts as well as draining Ether from them. Here are a few hints:
$ myth analyze <codefile.sol>
For analysis of on-chain contracts use the --rpc
and -a
options.
$ myth analyze --rpc localhost:8545 -a <address>
$ myth analyze --rpc infura-ropsten -a <address>
To run Scrooge McEtherface, set up Scrooge's config.ini
, then run:
$ ./scrooge <address>
Target Contracts:
- Guess the Random Number - Challenge on CTE
- Ethernaut Fallout - Challenge on Ethernaut
- Ethernaut Fallback - Challenge on Ethernaut
In the second example we'll again steal tokens and Ether, but this time with an integer arithmetics flavor.
This time, we'll set up a honeypot for others to tap into (VulnerableTwoStep).
To run Theo, start it with available arguments:
$ theo
The account's private key (input hidden)
>
Contract to interact with
> 0x1df62f291b2e969fb0849d99d9ce41e2f137006e
Scanning for exploits in contract: 0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e
Received an empty response from eth_getCode. Check the contract address and verify that you are on the correct chain.
No exploits found. You're going to need to load some exploits.
Tools available in the console:
- `exploits` is an array of loaded exploits found by Mythril or read from a file
- `w3` an initialized instance of web3py for the provided HTTP RPC endpoint
- `dump()` writing a json representation of an object to a local file
Check the readme for more info:
https://github.com/cleanunicorn/theo
Theo version v0.8.1.
>>>
Protip:
To be safe from frontrunning and errors, wrap your exploit into a wrapper that reverts the transaction if the attack fails:
contract Wrapper {
_target = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa
constructor(bytes memory _data) public payable {
address proxy = address(this);
uint256 start_balance = msg.sender.balance + proxy.balance;
address(_target).call.value(msg.value)(_data);
assert(msg.sender.balance + proxy.balance > start_balance);
selfdestruct(msg.sender);
}
function() external payable {}
}
Mainnet addresses will be announced at the workshop.
Most of the examples work with Infura, but if you want to use Scrooge McEtherface and do things in a block-chainy way you should run your own node. Syncing a full node can take a couple of days but you can set up a light client instead. Install go-ethereum and run:
geth --testnet --syncmode light --rpc
This should sync with the Ropsten network pretty quickly. You can now point Metamask and Scrooge to Localhost 8545
.
First, you need a web3 capable browser and some testnet ETH. You probably also have both, but if not, get Metamask and grab some ETH from the Ropsten faucets:
If you get this error, you need the libssl source libraries:
scrypt-1.2.1/libcperciva/crypto/crypto_aes.c:6:10: fatal error: openssl/aes.h: No such file or directory
#include <openssl/aes.h>
^~~~~~~~~~~~~~~
compilation terminated.
error: command 'x86_64-linux-gnu-gcc' failed with exit status 1
----------------------------------------
Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-5rl4ep94/scrypt/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-mnbzx9qe-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-5rl4ep94/scrypt/
On Ubuntu you can install them with:
$ sudo apt install libssl-dev
This error may occur if the solidity compiler solc
installed in path is incompatible with the provided source code (e.g. installed version is 0.5.x
but smart contract requires <=0.4.x
)
$ myth analyze <contract_0_4_x.sol>
mythril.interfaces.cli [ERROR]: Solc has experienced a fatal error (code 1).
code/RandomNumber.sol:8:1: Error: Source file requires different compiler version (current compiler is 0.5.3+commit.10d17f24.Darwin.appleclang - note that nightly builds are considered to be strictly less than the released version
contract GuessTheRandomNumberChallenge {
^------^
SolidityVersionMismatch: Try adding the option "--solv <version_number>"
There's a few options how to resolve this:
- Either try using
--solv <solidity_version>
as suggested by mythrils error message - Or force mythril to use a user-provide
solc
binary to comiple the code as follows:
$ export SOLC=/usr/local/bin/solc-0.4.26
$ myth analyze <contract_0_4_x.sol>
A great way to continue learning is playing challenges like Capture the Ether, Security Innovation CTF and Ethernaut.
Created by ConsenSys Diligence and the Mythril team. Special thanks to Mick Ayzenberg (Security Innovation), Trail of Bits, Steve Marx of CaptureTheEther and ConsenSys fame and Zeppelin Solutions for vulnerable contract samples and challenges. Also, kudos to the Truffle and Guardrails teams for working with us on Mythril Platform integration.