HeroCTF 2022
HeroCTF 2022 was an important CTF for our team, Th3Os, as we finally got into the top 10! Congrats to everyone who participated in that result, especially sAsPeCt for going mad into the last day (even finding an unintended in a chall 👀) and Rikoss for solving just as many challenges in one CTF as he has in the last 2 years (also with an unintended solution 👀). Personally I contributed in a crypto chall, but mostly played the blockchain category. Unfortunately instance is down so I can’t add info on how to setup the network or the first challenge, so I’ll just talk about the 2nd challenge.
Blockchain | Ready to hack
Initial Analysis
Let’s analyze the smart contract we are given
|
|
The contract implements three functions, deposit
, withdraw
, and getBalance
. Let’s analyze them one by one
deposit
indexes the listbalances[]
using themsg.sender
address, and incrementsmsg.value
to itgetBalance
returns the balance of the smart contractwithdraw
takes the balance of the sender, requires it be more than 0, and then sends it the the sender address. Then it sets the balance of that address to 0 Out of the above,withdraw
seems the most interesting, simply because we have transference between contracts. What if for example, we could infinitely execute the first 3 lines of thewithdraw
function? Then couldn’t we, as an attacker, infinitely ask for a balance from the contract, and take it until it has nothing left? Yes we could, and this is the basis of the reentrancy attack. To get a better understanding of the attack, watch the video. So as it shows, let’s go write our attacker smart contract in Remix.
Exploiting Our Target
For starters we’ll create a test environment with the source and attack contract, and after we’re sure the attack works we’ll add setup connection to the network from within Remix. In the video the creator writes both the contract in the same Solidity file. Personally I’ll add them in two files and just import the source to the attack. Following the video this is the attacker contract we end up with
|
|
The constructor
takes the supplied address of the victim contract, attack
and fallback
execute the attack, and getBalance
is just for emotional support. Let’s compile them both in Remix, and first deploy the victim contract so we can get it’s address and pass it to the attacker contract. Now if we choose an address from the ones that Remix provides and pass 1 ether to it so we can exeute the attack, we can see that it works! (sorry I can’t provide any screenshots but I’m writing this after the CTF and the network is down 🥺)
Now let’s setup interaction with the MEL network and the address we created on it. To do that, we select the Injected Web3
ENVIRONMENT on the top left of the Remix platform, and we connect our address. Then we select our account, and then execute our attack again. We can check it worked by seeing the balance of our contract with getBalance
Now we just press verify on the challenge platform, and get the flag (this time I can provide a screenshot)!
flag:
Hero{@M_A_m3l_sT34l3r_Am_v3rY_AngR}
Conclusion
Not gonna lie it wasn’t all that smooth sailing to solve the challenge. At first I tried the implementation from this video but I couldn’t get it to work (probably because of the older solidity version) and I was stuck for almost a day. But I was able to solve it at the end which is what matters for me :). Also if you want to test the attack just take the two contracts and run them on Remix