Skip to content

Snowball Fight⚓︎

Elf: Tangle Coalbox
Direct link: snowball2 website
Objective: Naughty/Nice List with Blockchain Investigation Part 1 and Part 2

Request⚓︎

Tangle Coalbox

Howdy gumshoe. I'm Tangle Coalbox, resident sleuth in the North Pole.
If you're up for a challenge, I'd ask you to look at this here Snowball Game.
We tested an earlier version this summer, but that one had web socket vulnerabilities.
This version seems simple enough on the Easy level, but the Impossible level is, well...
I'd call it impossible, but I just saw someone beat it! I'm sure something's off here.
Could it be that the name a player provides has some connection to how the forts are laid out?
Knowing that, I can see how an elf might feed their Hard name into an Easy game to cheat a bit.
But on Impossible, the best you get are rejected player names in the page comments. Can you use those somehow?
Check out Tom Liston's talk for more info, if you need it.

Hints⚓︎

Mersenne Twister

Python uses the venerable Mersenne Twister algorithm to generate PRNG values after seed. Given enough data, an attacker might predict upcoming values.

PRNG Seeding

While system time is probably most common, developers have the option to seed pseudo-random number generators with other values.

Extra Instances

Need extra Snowball Game instances? Pop them up in a new tab from https://snowball2.kringlecastle.com.

Twisted Talk

Tom Liston is giving two talks at once - amazing! One is about the Mersenne Twister.

Solution⚓︎

Easy, medium, and hard

The board layout for both players is defined by the player name. The same player generates the same layout, allowing us to replay easy and medium difficulty games over and over until we win. To win a game on hard difficulty, copy the randomly generated player name into an additional easy game instance. Then use this second instance to locate all forts and help you win the hard game.

Winning a hard game

Impossible

Impossible difficulty also generates a random player name but doesn't display the name anymore. To win the game we first need to predict the player name by cloning the state of the game's pseudo random number generator (PRNG) and using the cloned PRNG to generate the same random player name as the impossible game did.

The predict_name.py script helps with all the heavy lifting. It uses the sample code mentioned in Tom Liston's KringleCon talk to create a 32-bit MT19937 (line 8), clone the game's PRNG internal state to it by feeding the 624 rejected numbers through the untemper() function (lines 11-12), and generate the next random value (line 15).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
if __name__ == "__main__":
    # Read discarded numbers from random.txt
    file = open('random.txt', 'r') 
    numbers = file.readlines() 
    numbers = [(int)(x.strip()) for x in numbers]

    # create an MT19937 PRNG
    myprng = mt19937(0)

    # clone the Snowball Fight PRNG
    for i in range(len(numbers)):
        myprng.MT[i] = untemper(numbers[i])

    # predict the player name
    print(f'Your name is: {myprng.extract_number()}')

Start an impossible game, copy the 624 rejected values from the game's HTML to random.txt, and run predict_name.py.

Player name predicted

Similar to winning a hard game, use this predicted player name to generate an identical board layout on easy mode. Use this second game instance to help determine the locations of all the forts. Be careful not to make any mistakes when copying the locations to the impossible game though as the computer doesn't make any mistakes at this difficulty setting!

Impossible game won

Response⚓︎

Tangle Coalbox

Crikey - that's it! You've done the Impossible! You've impressed this old elf today.
Great work identifying and abusing the pseudo-random sequence.
Now, the REAL question is, how else can this be abused? Do you think someone could try and cheat the Naughty/Nice Blockchain with this?
If you have control over to bytes in a file, it's easy to create MD5 hash collisions.
Problem is: there's that nonce that he would have to know ahead of time.
A blockchain works by "chaining" blocks together - so there's no way that Jack could change it without it messing up the chain...
Maybe if you look at the block that seems like it got changed, it might help.
If Jack was able to change the block AND the document without changing the hash... that would require a very UNIque hash COLLision.
Apparently Jack was able to change just 4 bytes in the block to completely change everything about it. It's like some sort of evil game to him.