3

I've been trying to pick this honeypot contract apart, but I haven't figured out exactly how it works.

overview

The premise is pretty simple, the contract is set up to look like a "new year's gift" where the ETH is retrievable if someone (probably the gift receipient) puts in the correct password.

However the contract author has made a fatal "flaw". If a certain field named passHasBeenSet is false, anyone can send the contract >1 ETH and become the contract's owner! Once you're the owner, you can call the revoce function to pull out all of the funds in the contract.

What's the problem? I found this contract suspect because it was 1) created by the creator of another honeypot contract described on reddit and 2) generally strange - why post the source to Etherscan? Why allow someone else to become the owner if they pay more into the contract? The contract is designed with if statements/doesn't throw errors and looks like it was written by a beginner.

However, I couldn't initially spot anything wrong with the contract. Additionally, it seemed like it only had two transactions, a contract creation and a call to setPass. This should still leave passHasBeenSet set to false.

pen testing

I figured I might as well see if the contract was a Honeypot or not. I knew I could design the "attack" contract so I couldn't lose, but I was still curious.

I put together a contract that would call setPass and then revoce. If the contract's balance decreased, it would revert. This construction meant I couldn't lose any money.

The honeypot contract (& attacking contract) worked as expected on Ropsten. Any balance in the contract was extracted and could then be withdrawn from then attacking contract. However, the attacking contract failed on the mainnet. The balance was successfully sent to the target contract, but the revoce failed so the contract's revert failsafe was triggered. Debugging the transaction showed that passHasBeenSet was true.

So, how did the "vulnerable" contract manage to set passHasBeenSet? I must be missing something pretty obvious.

1
  • Sorry, I don't have enough reputation to put a comment. > The balance was successfully sent to the target contract If passHasBeenSet was true, how did your contract's call to SetPass() succeed in the first place?
    – alena
    Commented Feb 15, 2018 at 12:48

1 Answer 1

3

PassHasBeenSet was called in this transaction:

https://etherscan.io/vmtrace?txhash=0x17c44511bcb28a34eac5653fc6cdd8367a978265e7528a0660f7e8aa9c8b55e7&type=parity

Look for 0x31fd725a in the trace. (That's the function selector for PassHasBeenSet(bytes32).)

This trick takes advantage of the fact that Etherscan doesn't show all the calls to a contract. (I believe it skips messages from another contract when no ether is attached.) Etherchain does better: https://www.etherchain.org/account/13c547Ff0888A0A876E6F1304eaeFE9E6E06FC4B#transactions.

1
  • Well, that solves it. That's a really interesting way to take advantage of Etherscan specifically.
    – K. Fichter
    Commented Feb 15, 2018 at 5:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.