Yael's Achtung, Die Kurve!
When my S.O and I started dating we always teased each other about who’s better at ‘Achtung, Die Kurve!’. It’s a 2D local co-op flash game in which you draw a line behind you and mustn’t collide with the lines or the walls. There are also some power-ups that add spice to the game. It’s as fun as it is simple. Anyway, flash reached its end of life on January 1st, 2021, mostly due to security risks, so we couldn’t play and prove who’s better.
Several months ago a friend of a friend informed me of BlueMaxima’s Flashpoint, a webgame preservation project. It contains over 100,000 games. I needed only one.
Since then we have been playing regularly. Sometimes I win, sometimes she does.
Recently I was looking for a little gift for her when an idea arose - what if she had a version of Achtung in which she always wins?
In BlueMaxima’s Flashpoint local directory I found Achtungs
.swf file [Adobe Flash file format]. I opened it up in a hex editor to edit the names to something funny and get a quick win, but I couldn’t find any strings from the game.
To get the original files from the
.swf I used an online SWF Decompiler. The results were peculiar:
MochiCrypt is used to protect Flash games from decompilation. It is a
.swf itself, and when it loads it decrypts the original game file and loads it. I could probably dump the original
.swf from memory, but there was no need for that. MochiCryptUnpacker decrypts and dumps the original game file for you ^_^
The online SWF Decompiler didn’t dump the scripts from the game file so I moved to JPEXS, and it’s great. It even has a “Search SWFs in memory” that could dump the original game file from the encrypted one instead of MochiCryptUnpacker.
The scripts directory contains all the ActionScript files. When opening a script two windows appear - the ActionScript code on the left and an intermediate representation called P-Code on the right.
After quickly changing the player names I finally got to the fun part. A reminder: my goal is to make Yael’s character invincible. I settled for an elegant way to do so - find the code that handles losing and don’t call it if you are the right player. This means wrapping that piece of code with an
if statement checking the player’s name. To find this part I dumped the scripts and searched through them with VSCode.
When a new player is added he is assigned an event listener that calls
handleMove every time he moves.
handleMove checks if the player is not in a “hole” state [in which he doesn’t have a presence on the canvas for a short period]. If so, he draws him on the canvas with
field.addBody. If there is another player or wall in that location this function returns
handleHit is called. This is the function I don’t want to call when the player is Yael.
Instead of configuring whatever that was so I could edit the ActionScript I decided to edit the P-Code directly. This is the first time I came across any of these languages, but luckily JPEXS’s interface has parallel highlighting and some explanation of every P-Code instruction. Here is the code after the edit:
Lines 36-39 are the
if statement presented on the left.
local2 is the player who moved. If it’s Yael she will continue without getting hit.
It worked （￣︶￣）↓
Her player is still fully functional, powerups work all the same. There is one side effect. Her player can go freely off the game borders and even travel next to the scoreboard (¬‿¬)