This is my writeup for the last blockchain challenge in the Cairo ICT CTF qualifications this year.
Hello hackers, this isn’t my first time to try to solve blockchain challenges. I got some basic
understanding of how it works in terms of smart contracts and the cryptography involved, but this time I
was lucky to give it a big try even after the qualification round.
Smart CrackMe
The challenge was given a public deployed contract with address 0x31678C496E63BcEbd1398D25C9B21cDcb3cc5e23 on Etherscan
along with its ABI. It has only one transaction and nothing else but the contract bytecode.
And the contract ABI:
First thing noticed that the contract section has a button to decompile the bytecode and after
decompiling, it gives us the following code:
The website uses Panoramix python decompiler and as we
see there’re only 3 functions owner, withdraw, and the last one check_flag that had been decompiled into this weird
name unknown08c5dc7f.
owner: Returns only the address of the
contract owner.
withdraw: Checks if the method caller
address same as the contract owner address. If so withdraw the ballance, if not it aborts.
check_flag: It takes 8-bit integer value,
does some calculations on the defined array of size 2 and lastly it checks if the final array value has
the correct flag format.
I was stuck at the decompiled line inside the loop. It has weird syntax and didn’t know how represent the
first part. Actualy, I’ve tried to assume that some parts are useless and tweak the others but nothing
worked. So, I decided to look at the decompiler repo and see if there’s any options that I could use to
help me decompile the bytecode correctly, but unfortunately still nothing.
I asked one of my teammates if he knows any smart contract decompiler and he told me I could use JEB. I started off and loaded the bytecode into JEB, it
shows me the opcode instructions and when I tried to decompile to the source code it gives a decompilation
error. I’ve tried to read the instructions and map it to what I’ve in the code above, but still no luck.
On the next day, I asked our reverse mate to take another look on the decompiled weird instructions, but
he couldn’t understand a thing from it. He decided to decompile it using his own JEB version and this time
the source code showed up on his screen.
First, we know that storage variable has size 2
from the previous decompiled code and now the code has flatten out the iterations one by one. He tried to
run the 48 lines above and the result wasn’t usefull, we tried to play with it, but still empty hand. The
competition has ended and we still couldn’t figure it out. After a day I decided to give it another try
and this time look a bit closer on the last decompiled code. I ran it and did a bruteforce xoring over the
result and I noticed the reversed flag appeared with byte 0x99 🙂.