My friend has created his own hashing service and has given it to me to crack it, can you help me with it. He has promised me a burger for this as I like McDonald’s so much , can you help me get some? please :) :)
defmain(): print("Welcome to the Token Verification Challenge!") print("============================================") print("Rules:") print("1. Submit message-token pairs") print("2. Each token must be valid for its message") print("3. You cannot reuse tokens") print("4. Get 64 valid tokens accepted to win!") print("\nFormat: <hex-encoded-message> <hex-encoded-token>") print("Example: 48656c6c6f 1234567890abcdef") manager = TokenManager() successes = 0 for i inrange(128): try: print(f"\nAttempt {i+1}/128") print("Enter your message and token: ", end='') user_input = input().strip().split() iflen(user_input) != 2: print("Invalid input format!") continue message = bytes.fromhex(user_input[0]) token = bytes.fromhex(user_input[1]) if manager.verify_and_store(message, token): successes += 1 print(f"Success! {successes}/64 valid tokens verified") if successes >= 64: print("\nCongratulations! You beat the challenge!") withopen("flag.txt", "r") as f: print(f.read().strip()) break except Exception as e: print(f"Error: {str(e)}") continue if successes < 64: print("\nChallenge failed! Not enough valid tokens.")
if __name__ == "__main__": main()
The key vulnerability lies in the verify_and_store() function.
There are a few characteristics of this function that make it vulnerable.
self._mac is reinitialized every iteration, so the hash will always be computed on the concatenation of key.txt with the message m
If the token is invalid, then the token is never added to self._seen_tokens.
If the token is invalid, then the correct token is given to the user.
Properties #2 and #3 mean that we can send a (message, invalid token) pair, and receive the correct token for that message. And due to property #1, that means that sending the new pair of (message, received token) will actually be correct!
Therefore, since we’re given 128 message attempts, it’s as simple as sending 64 (message, invalid token) pairs, with all messages being distinct from each other, and then sending the corresponding 64 (message, received token) pairs. Here’s the implementation of that:
a = [] for i in trange(64): a.append(send_bad("{:02d}".format(i).encode(), b'00')) assertlen(set(a)) == len(a), len(set(a)) for i in trange(64): send_good("{:02d}".format(i).encode(), a[i])