The end of the Advent of CTF is here. A last battle remains for the honor of Santa.
What you will learn today:
- The basics of a blockchain
The challenge starts out just like challenge 20, with a small difference. In the footer it now says
In the source of the index page there are some development notes that will help in solving this challenge. They basically explain the way the board is hashed for use in the blockchain.
Using the same technique as used in the challenge 20 the stored game state can be read.
The game state is now significantly larger then before. Most of it is due to the key
chain, which is the blockchain.
A blockchain works by taking a known value, a
hash that has been previously computed, then taking a computation over the thing that is in the
block, generally also a hash, and then combining these 2 values to compute a new hash. So, if we start with the hash
A and then compute a hash for our block
B the resulting hash will be that of
A+B, which will then be passed on to the next block. The block,
C, will then take its own hash and combine it with the previous hash to form a new one
A+B+C. The chain is only valid if all hashes are correct, meaning it is impossible to change a single block, without recomputing all hashes.
Luckily we have the computation logic from the index page:
def hash_string(string): return hashlib.md5(string.encode('utf-8')).hexdigest() def hash_row(row): conv = lambda i : i or ' ' res = [conv(i) for i in row] return hash_string(' '.join(res)) def hash_board(board): acc = "" for row in board: acc += hash_row(row) return acc 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
From the function
verify_chain it is clear that the last entry of the chain has to be the current board state for it to pass inspection. From there the length of the chain is iterated to calculate and compare the hashes. Note that the
verify_chain function does not check to see how many entries should be on the chain itself.
So, from this logic it is clear that a new game state can be created that only has 1 entry in the blockchain, the winning board, and that only that entry will require a new hash calculation. Luckily all the elements needed to do the calculation were given.
Working from the previous solution the following script will create a new payload.
After you grab the flag also be sure to grab the badge!
Go back to the homepage.