Impact with F12

Published 2 years ago13-04-2022 - 13:05


On impactmetjecode.nl there is a mini programming game made by the Dutch Railways (NS). This game lets you solve problems using code and logical thinking.

Impact With Your Code F12!

Let's take a look at the requests this game makes using the Network tab of the Chrome Developer Tools:

Lots of images and sprites

JSON files with a lot of information (And answers, yikes)

Leaderboard? Leaderboard!

When you are out of lives and the game ends, Miranda will ask you if you want to upload your score to the leaderboard... We definitely want that! But actually not with the embarrassing score of 235 points... We're about to fix that!

Spoiler: Score 2 is mine :)

After loading the leaderboard, we take a look at the requests that have been made by the game in the meantime. After all, the high score must have been sent.

Yep! There is a request to post the highscore:

Besides the query parameter, no data is sent. So the name and score must be included in this. The value might be Base64... Worth a try:

Hmm, an encrypted message that we probably can't do much with in this way. If we find out which script sent the highscore, we might be able to figure out how it's encrypted.

The script bundle.min.js seems to be the source!

Unfortunately, this is a minified JS file which is hard to read. We have a solution for that: JS Formatters!

Much better!

The search!

We're looking for the code that sends a request to post-highscore- Oh there it is!

We see that the code uses the createEncryptedQuery() function... Let's see!

ah! That's where the encryption happens...

And there's the key! d2Vya2VuYmlqbnMubmw=... Is this Base64 again?
Absolutely! And this is a beautiful encryption key: (Translates to 'WorkAtNS.nl')

Now we have a choice on how to proceed:

  1. Investigate how the encryption works, replicate it ourselves with your own values ​​(Effort)
  2. Be lazy and use a proxy to replace bundle.min.js with our own version and immediately inject a highscore. (Sounds like more work, but is actually easier)

Lazy Efficient!

Let's go for the 'Efficient' way...

By creating an autoresponder in a program like Fiddler, we can make the game use our own code instead of the real one:

Now the game uses my own file instead of the server's. Let's tweak the code a bit!

If we look, we see that r contains the username of the highscore, and a converts this to a query and directly takes the points as an argument...

We can both adjust this quite easily:

Now we are basically ready to inject our own high score. If I understand the code correctly, this piece should be triggered the moment we finish the game and our highscore is sent in.

Put simply: Now if we refresh the page, start a game, purposely wait for my lives to run out, it sends a new highscore!


We've officially wasted 2 hours faking a highscore of "69696969" on a game's leaderboard to ruin the fun of others.......... Oops....

[ And looks like I wasn't the only one ;) ]