0xPOLAND — Adventure Awaits

Last month, ETHworks put together a really fun smart contract contest where players competed to solve all the clues and unlock a 7 ETH reward. While I did not win, I had an absolute blast participating in it and wanted to share my notes in case you want to learn about password cracking and smart contract hacking techniques. If that sounds interesting to you, let’s dive right in.

#0xPOLAND

On November 17th, 2020, while preparing for the next edition of the Blockchain Threat Intelligence newsletter, I ran across an interesting tweet advertising some kind of a smart contract contest:

https://twitter.com/0xPoland/status/1328616243562156032

The address contained a simple smart contract which challenged anyone to guess a plaintext for a stored hash which was hashed twice with KECCAK-256:

The hash was initialized at contract deployment time and could be easily looked up in Etherscan:

https://etherscan.io/address/0x46ca2bf8188303887d6af76ddd316afa233b2ec9#readContract

The contract itself was interesting in the way it protected players against front-running attacks by first requiring a commit() transaction with a solution hashed once using KECCAK-256, followed by the actual reveal() after a 10 block delay.

On-Chain Cracking

My initial approach to solving the puzzle was to load a slightly modified version of the contract on Remix in order to save on gas fees and to keep attempts private:

The modification, simply disables the commit step so I could freely experiment with different solutions. Next, I have initialized the contract with the same hash value as the original:

0x5746fe8ae2bf9fb24bcdf4972ea78c0211211e23c376461956d46d8d8a6519ba

Trying a few iterations manually, it quickly became clear that a more automated approach will be needed:

Manual cracking attempts on Remix

Industrial Cracking

KECCAK-256 hash function has readily available implementations in many languages. Instead of trying to crack the hash inside EVM, I rewrote just the relevant portion in Go. Below is a basic implementation of the algorithm which achieves about ~400K hashes per second on my MacBook Air:

A successful hash cracking job requires not only speed, but also the ability to continuously come up with good wordlists. In my failed attempts, I went through popular wordlists such as RockYou, CrackStation, and others. To further increase my chances, I rewrote the above implementation to include multi-threading and even the ability to mutate passwords using Hashcat’s rules engine:

% ./crack hashcat --stdout -r rules/passphrase-rule1.rule -r rules/passphrase-rule2.rule passphrases.txtgee point lake2017
GEEPOINTLAKE2015
geepointlake2017
Gee point lake2017
GEE POINT LAKE2017
gEE POINT LAKE2017
Geepointlake2017
gEEPOINTLAKE2017
...

With the laptop fan screaming in the middle of the night, it was clear that the puzzle solution is more likely to be a complex passphrase as opposed to a simple password. To crack that, I would need to go way down into the rabbit hole and analyze all the hints.

Down the Rabbit Hole

The 0xPOLAND twitter account served as the main source of announcements and clues for the challenge. The first tweet appeared on November 9th with a simple white rabbit 🐇 emoji. The next few tweets all featured amazing graphics each with a single line clue such as the one below:

Image for post
Image for post

Below is a list of tweets before November 17th and my notes on their meaning:

  • November 12th: “Adventure AwAits”
  • November 13th: “Only in the darkness can you see the stars”
    Note:
    A quote from Martin Luther King Jr.
  • November 14th: “the future is already here — it is just unevenly distributed”
    Note:
    A quote from William Gibson.
  • November 15th: https://etherscan.io/block/11287961
    Note: A countdown timer to November 19th when the block will be mined.
  • November 16th: “Smart contract address: 52.217609, 21.014687”
    Note: Location of a subway station in Warsaw where the billboard with the smart contract address was initially posted.

The presence of two quotes from William Gibson and Martin Luther King Jr. gave me an idea that the solution is a famous quote. The best collection of quotes that I could find on the internet was on Goodreads.com. Conveniently, someone already wrote a scraper to pull quotes from the site, so with a bit of tweaking I started generating large wordlists of quotes from famous cyberpunk authors, politicians, and freedom fighters. After cleaning up the quotes and mutating different punctuation marks, I generated a list of close to 1,000,000 passphrases which unfortunately did not yield a result.

Pedal to the Metal

This was the point where things started getting strange. On November 19th, just as the Ethereum block 11287961 was mined, 0xPOLAND Twitter account made another post:

Image for post
Image for post

Followed by a post the next day with another hash:

0x01ccfbfc07b041fb180400af9f610ceeaea21d513e743daf648344b56ac68bf4

The quote above comes from a song by a metal band Elffor called “Into the dark forest”. Looking at the regex hint ^[A-Z].*\., the solution was supposed to start with a capital letter and end with a period. After some time, I found that the hash above corresponds to a single KECCAK-256 iteration of the song title:

Into the dark forest.

Could the solution be a song title? Would the song be in the same genre as Elffor? There was only one way to find out! I put together a song scraper for a metal band database and went to sleep.

The next morning I woke up to a nice collection of ~400K metal song titles with amazing names like “Rites of the Pentagram”, “Suicide Salvation”, and my favorite “Septic Oral Sex”. Next, I ran these through my cracker with different hashcat rules to try different letter cases and making sure there is a period at the end:

poland1.rule:
:
u
T0
E
e
lT0
poland2.rule:
:
$.

I ran the above two rules against the song wordlist as follows:

./crack hashcat -r rules/poland1.rule -r rules/poland2.rule  --stdout metalstorm.txt

Unfortunately there were no hits. I dug in to wait for more clues.

The Ultimate Question

The next clue came on November 23rd:

Answer to the Ultimate Question of Life, the Universe, and Everything6e 99 a1 98 4a 9e 92 8f 4a 9c 8b 8c 8c 93 9e 4a 92 99 96 8f 58

This one was easier to solve. The first line referred to the book “The Hitchhiker’s Guide to the Galaxy” and the answer to that is 42. After playing with a few different encodings, I was able to solve this mini-puzzle with a simple Python one-liner:

In [10]: print(''.join([chr(int(b,16)-42) for b in "6e 99 a1 98 4a 9e 92 8f 4a 9c 8b 8c 8c 93 9e 4a 92 99 96 8f 58".split()]))Down the rabbit hole.

Still no dice. A few days later a new countdown was posted waiting for the block 11332799 which was supposed to be mined on November 26th at around midnight in my timezone.

Call me

Just as expected, the next clue was posted on November 26th, 12:03 AM:

Image for post
Image for post

Half-asleep, I sat in the darkness trying to figure out the cryptic numbers and who I was supposed to call. The first set of numbers corresponded to ISSN number for Gazeta Wyborcza published in Warsaw, Poland. Suddenly a new commit() transaction has appeared on the blockchain:

https://etherscan.io/tx/0xf9fb51e6f9fe3e2440804c85fcf9abfb394b19d5730dbf7515a59334ea723848Function: commit(bytes32 _hash)MethodID: 0xf14fcbc8
ca3329acfbcf202b83bc3d7c7e46a72be43b475d0f2334ffccfbe7d1186d0200

It was not the first time that folks attempted to send answers to the contract; however, it quickly became clear that someone did in fact solve it after the reveal() transaction was successfully submitted without a revert:

https://etherscan.io/tx/0x30da280465e7972afbf45287608a7bd15ccec53a1832f138b468c39d46a95de5Function: reveal(string _solution)MethodID: 0x4c261247
0000000000000000000000000000000000000000000000000000000000000020
0000000000000000000000000000000000000000000000000000000000000052
57697468203078506f6c616e642e20496e746f20746865206461726b20666f72
6573742e20446f776e207468652072616262697420686f6c652e205768657265
20616476656e74757265206177616974732e0000000000000000000000000000
With 0xPoland. Into the dark forest. Down the rabbit hole. Where adventure awaits.

It was only later that folks from Warsaw have shared a screenshot from that day’s newspaper edition which contained the last clue:

I could not resist calling the number and got the following recording on the other end:

The message essentially provided the template for the puzzle’s passphrase:

You've come a long way. Congratulations. Here is your solution. With 0xPoland. Into **BEEP**. Down the **BEEP**. Where adventure awaits.

Filling in “the dark forest” and “rabbit hole” into the above produced the correct double KECCAK-256 hash in the puzzle!

Conclusion

During the week of playing the contest, I have learned how to write multi-threaded password crackers and page scrapers, build targeted wordlists and picked up a few smart contract tricks. Most of all I had a ton of fun while revisiting some of my favorite metal bands from the 80s. Sorry Metal Kingdom for knocking down your site a few times, it was for a good cause. While it was a bit disappointing that only someone living in Warsaw could have won the contest, it makes sense what folks at ETHworks were trying to achieve with the local community. And with that, thanks for a great challenge and a nice distraction from this crazy year.

References

Blockchain Security, Malware Analysis, Incident Response, Pentesting, BlockThreat.net

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store