How to Exploit Ethereum in a Virtual Environment

January 04, 2019 by Daniel Luca

This is going to be a series about some of the techniques I implemented when designing Karl, a free tool that finds exploitable code in live smart contracts.

When I monitor the Ethereum blockchain for vulnerable contracts, I need a way to determine if the vulnerabilities I find are the real thing, or merely a scattering of false positives and honeypots. I’ve been able to mitigate this possibility by testing for vulnerabilities in a virtual copy of the blockchain.

Virtual environment

A blockchain clone is useful because we could break the contract arbitrarily sending transactions to it. Remember “I accidentally killed it”?

Another great reason to use a virtual environment is that once you send transactions to the blockchain, any other person watching it will know how to exploit it, and they may not be as diligent as you about responsibly disclosing the vulnerability to the creators of the application.

Even if you wanted to exploit the contract, you would still need to make sure the exploit works by testing it before carrying out the attack.

How to setup the virtual environment

You may know about ganache, the whipped filling of chocolate and cream, used in desserts such as cakes and truffles. Mmmmhhm yeah! But there’s another ganache that works really well with truffles.

Being part of the Truffle Framework, a smart contract development environment, Ganache is your on-demand personal Ethereum blockchain, perfect for local development… and hacking!

Compared to Geth or Parity, Ganache is easier to setup and it’s not as resource intensive.

You can install and run Ganache in just 2 commands (if you have Node.js installed)

$ npm install -g ganache-cli
$ ganache-cli

And you have your own personal blockchain.

Forking the mainnnet

A little-known feature of Ganache is forking another blockchain. You can think about this as cloningan existing blockchain, but don’t worry, you won’t need to download the entire blockchain! Ganache will start instantly and will only query the real blockchain when it needs to, for example to read the contract’s code and state.

$ ganache-cli -f https://mainnet.infura.io

And you can fork the chain at a specific block if that’s what you need, for example forking at block 100.

$ ganache-cli -f https://mainnet.infura.io@100

This will provide a blockchain clone that is safe to play with. It will create a local instance and you can send transactions and deploy new contracts, run your exploit and check its validity. All of this without touching the real blockchain, without anyone else knowing what you’re doing and without self-destructing libraries by mistake.

Exploiting in a virtual environment walk-through

This is where we start to go into details. You need a few things installed.

In the following example you will:

Run Karl and monitor for vulnerable contracts

Fork the chain after we find a vulnerable contract

Test the exploit and see if we stole some ether

Karl

If you don’t know about Karl, go to the GitHub page and star the project. It helps you find vulnerable contracts on Ethereum.

If you find any bugs or have any problems running Karl, please report an issue.

Karl is available as a PyPI package, so you can just install it by running:

$ pip install --user karl

Typically you would point Karl at the main Ethereum network and monitor the contracts that get deployed there. For demonstration purposes, we’re going to monitor a local test chain instead. We’ll use Ganache for this test chain too.

We start a private Ganache instance.

$ ganache-cli -d

Start Karl and monitor for new contracts.

$ karl --rpc localhost:8545

In the Ganache console you will see Karl polling for new blocks, waiting for a new contract to be deployed.

Forking the chain

The original chain is located at http://localhost:8545, because we’re running this on the same machine we can start Ganache with fork functionality and start it on a different port.

$ ganache-cli -f http://localhost:8545 -d -p 9545

Each flag explained:

-f http://localhost:8545 tells Ganache what chain to fork

-d runs Ganache in deterministic mode, the same wallets are generated every time; this is important because you can copy paste the curl commands and you don’t need to update the address that deploys the contract

-p 9545 sets a different port to run on (the default 8545 is already used by our test chain)

Once the fork is up and running, we can send the transaction that Karl reported and see if we successfully stole the contract’s ether.

First check the initial balance of the address that will exploit the vulnerable contract 0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e.