The final battle! The elves want revenge for their lost game! They have enhanced the tic-tac-toe game with blockchain technology. Cyber Security on the Blockchain will revolutionize everything, but most importantly ensure they will win this time. No cheating Santa!
Visit <https://24.adventofctf.com> to start the challenge.
## Recon
When opening the page, we're greeted with what looks like the same screen as we had on [challenge 20]({{< ref "challenge_20.md" >}}). The only noticeable difference is the addition of `blockchain? True` in the footer.
If we take a look at the source, we also find a comment with the following python code:
Using the same method as in challenge 20, we can take a look at the board:
```py
In [1]: import pickle
In [2]: import base64
In [3]: pickle.loads(base64.b64decode("gAN9cQAoWAUAAABib2FyZHEBXXECKF1xAyhYAQAAAE9xBGgETmVdcQUoaARYAQAAAFhxBmgGZV1xByhoBGgGaAZlZVgEAAAAdHVybnEIaAZYCAAAAGZpbmlzaGVkcQmJWAYAAAB3aW5uZXJxClgAAAAAcQtYBAAAAHNhbmVxDIhYCgAAAGJsb2NrY2hhaW5xDYhYBQAAAGNoYWlucQ5dcQ8ofXEQKGgBXXERKF1xEihOTk5lXXETKE5OTmVdcRQoTk5oBmVlWAQAAABwcmV2cRVYIAAAAGNlZjIxNWM1YmU4Y2Y2M2ZjZjNkNDNlY2YyNTEwYjMzcRZYBAAAAGhhc2hxF1ggAAAAZTdkYzhlMWY3YTY3ODhiYzBjYjY4NDE1MzhiMjE2ZThxGHV9cRkoaAFdcRooXXEbKGgETk5lXXEcKE5OTmVdcR0oTk5oBmVlaBVoGGgXWCAAAABmYzkzMjM2YjVlZWE1ZjFkNTVlMmI1YjMwOGQ2NzM5MHEedX1xHyhoAV1xIChdcSEoaAROTmVdcSIoTmgGTmVdcSMoTk5oBmVlaBVoHmgXWCAAAABhOGRjMGQzZGEyOTBkMWU4OTRlYWFmZmNiOTgzOThjOXEkdX1xJShoAV1xJihdcScoaARoBE5lXXEoKE5oBk5lXXEpKE5OaAZlZWgVaCRoF1ggAAAAZTc0ZjViMjJmNTIxM2JhNGMyNDQ5NzU5Y2U5MWMyYWFxKnV9cSsoaAFdcSwoXXEtKGgEaAROZV1xLihOaAZoBmVdcS8oTk5oBmVlaBVoKmgXWCAAAABlZjI1NTE0ZGZmYmY4MjQ3Y2ZmNjA2M2JlOTBmMmQ1NHEwdX1xMShoAV1xMihdcTMoaARoBE5lXXE0KGgEaAZoBmVdcTUoTk5oBmVlaBVoMGgXWCAAAABlM2E0YzAzN2JkZjE1NGIzNDRlZDliZDE2NDNhNjI5ZHE2dX1xNyhoAV1xOChdcTkoaARoBE5lXXE6KGgEaAZoBmVdcTsoTmgGaAZlZWgVaDZoF1ggAAAAYzI0MGZhMTYxNzM3Yzk2N2VjZTVmZDk0NjcyYWIwZjhxPHV9cT0oaAFdcT4oXXE/KGgEaAROZV1xQChoBGgGaAZlXXFBKGgEaAZoBmVlaBVoPGgXWCAAAAAyNGJhNzE1ZGMwNTY4M2NlNDViOWUxOTFlZDE4OGI5Y3FCdWV1Lg=="))
```
This time our board is quite a bit larger:
{{<codelanguage="py"title="Board">}}
```py
{
"blockchain": True,
"board": [
["O", "O", None],
["O", "X", "X"],
[None, "X", "X"]
],
"chain": [
{
"board": [
[None, None, None],
[None, None, None],
[None, None, "X"]
],
"hash": "e7dc8e1f7a6788bc0cb6841538b216e8",
"prev": "cef215c5be8cf63fcf3d43ecf2510b33"
},
{
"board": [
["O", None, None],
[None, None, None],
[None, None, "X"]
],
"hash": "fc93236b5eea5f1d55e2b5b308d67390",
"prev": "e7dc8e1f7a6788bc0cb6841538b216e8"
},
{
"board": [
["O", None, None],
[None, "X", None],
[None, None, "X"]
],
"hash": "a8dc0d3da290d1e894eaaffcb98398c9",
"prev": "fc93236b5eea5f1d55e2b5b308d67390"
},
{
"board": [
["O", "O", None],
[None, "X", None],
[None, None, "X"]
],
"hash": "e74f5b22f5213ba4c2449759ce91c2aa",
"prev": "a8dc0d3da290d1e894eaaffcb98398c9"
},
{
"board": [
["O", "O", None],
[None, "X", "X"],
[None, None, "X"]
],
"hash": "ef25514dffbf8247cff6063be90f2d54",
"prev": "e74f5b22f5213ba4c2449759ce91c2aa"
},
{
"board": [
["O", "O", None],
["O", "X", "X"],
[None, None, "X"]
],
"hash": "e3a4c037bdf154b344ed9bd1643a629d",
"prev": "ef25514dffbf8247cff6063be90f2d54"
},
{
"board": [
["O", "O", None],
["O", "X", "X"],
[None, "X", "X"]
],
"hash": "c240fa161737c967ece5fd94672ab0f8",
"prev": "e3a4c037bdf154b344ed9bd1643a629d"
}
],
"finished": False,
"sane": True,
"turn": "O",
"winner": ""
}
```
{{</code>}}
We can see that a `chain` value has been added. From the title of this challenge, we can say that this is the blockchain that we likely have to bypass.
## Exploit
Cracking this shouldn't be too hard. Let's start by copying our script from challenge 20 and resetting the chain:
Sadly, just submitting the result of this script doesn't work. We have to fill the chain.
To find out how the chain works, let's take another look at the `verify_chain()` function:
```py
def verify_chain(game):
board=game["board"]
chain = game["chain"]
if len(chain) > 0:
if board != chain[-1]["board"]:
return False
for i in range(len(chain)):
block=chain[i]
h = hash_board(block["board"])
h = hash_string(h + block["prev"])
if h != block["hash"]:
return False
return True
```
We can see that, to verify the game, the function loops through all the blocks in the chain. It then calculates a hash based on the board, and the previous hash and compares that to the actual hash in the block (the user provided one).
To crack this, we can simply reverse this algorithm. To do this, I grabbed the script from the HTML source, and added a crack method like so:
game = load_base64("gAN9cQAoWAUAAABib2FyZHEBXXECKF1xAyhYAQAAAE9xBGgETmVdcQUoaARYAQAAAFhxBmgGZV1xByhOaAZoBmVlWAQAAAB0dXJucQhoBFgIAAAAZmluaXNoZWRxCYlYBgAAAHdpbm5lcnEKWAAAAABxC1gEAAAAc2FuZXEMiFgKAAAAYmxvY2tjaGFpbnENiFgFAAAAY2hhaW5xDl1xDyh9cRAoaAFdcREoXXESKE5OTmVdcRMoTk5OZV1xFChOTmgGZWVYBAAAAHByZXZxFVggAAAAY2VmMjE1YzViZThjZjYzZmNmM2Q0M2VjZjI1MTBiMzNxFlgEAAAAaGFzaHEXWCAAAABlN2RjOGUxZjdhNjc4OGJjMGNiNjg0MTUzOGIyMTZlOHEYdX1xGShoAV1xGihdcRsoaAROTmVdcRwoTk5OZV1xHShOTmgGZWVoFWgYaBdYIAAAAGZjOTMyMzZiNWVlYTVmMWQ1NWUyYjViMzA4ZDY3MzkwcR51fXEfKGgBXXEgKF1xIShoBE5OZV1xIihOaAZOZV1xIyhOTmgGZWVoFWgeaBdYIAAAAGE4ZGMwZDNkYTI5MGQxZTg5NGVhYWZmY2I5ODM5OGM5cSR1fXElKGgBXXEmKF1xJyhoBGgETmVdcSgoTmgGTmVdcSkoTk5oBmVlaBVoJGgXWCAAAABlNzRmNWIyMmY1MjEzYmE0YzI0NDk3NTljZTkxYzJhYXEqdX1xKyhoAV1xLChdcS0oaARoBE5lXXEuKE5oBmgGZV1xLyhOTmgGZWVoFWgqaBdYIAAAAGVmMjU1MTRkZmZiZjgyNDdjZmY2MDYzYmU5MGYyZDU0cTB1fXExKGgBXXEyKF1xMyhoBGgETmVdcTQoaARoBmgGZV1xNShOTmgGZWVoFWgwaBdYIAAAAGUzYTRjMDM3YmRmMTU0YjM0NGVkOWJkMTY0M2E2MjlkcTZ1fXE3KGgBXXE4KF1xOShoBGgETmVdcTooaARoBmgGZV1xOyhOaAZoBmVlaBVoNmgXWCAAAABjMjQwZmExNjE3MzdjOTY3ZWNlNWZkOTQ2NzJhYjBmOHE8dWV1Lg==")
crack(game)
print(export_base64(game))
```
{{</code>}}
After running this script, we get the following result:
When we set this and refresh the page, we get the following message: `"Game goes to: X NOVI{blockchain_cyb3r_security} Thank you for playing Advent of CTF! I hope you have a great christmas!"`.
## Solution
We got the flag! It is `NOVI{blockchain_cyb3r_security}`.