Note: I reported this technique to the company behind the game back at august 2015. Never got a reply.
I like videogames, so when I read about some "clickers" genre, I wanted to check how they played. Setting aside the mechanics themselves and my personal feelings regarding this kind of games, one title that caught my attention for being better than the average was Clicker Heroes. After playing a while it looked to me as if the difficulty curve was quite exponential, requiring either lots of patience or spending money at in-app purchases, so I wanted to confirm my suspicions.
Checking the game binaries I saw that there was a
HeroClicker.swf, so it was a Flash game. I've already peeked inside and even dissasembled SWFs with Sothink SWF Decompiler, so was my chosen tool.
I started peeking at the insides, and by mere luck I ended peeking the
ImportScreen class. It had a constant called
SALT just below the variable
_userData, so it caught my eye. I ran the game and saw that in the options you can export your data to an apparently encrypted TXT file, and then import it back... hacking my data was way more appealing, and by chance I had a possible attack vector with the import logic.
There was another constant with a maybe too descriptive name,
TEXT_SPLITTER, and scrolling down I found
fromAntiCheatFormat methods, performing MD5 hashes with the salt of contents retrieved from
The sprinkling or scattering algorithm was not hard to read:
- Get user data json and base64 encode it
- Prepare a new array twice the original size of the base64 encoded string
- Place one by one all base64 encoded characters at even positions
- Randomly put an alphanumeric character at odd positions
And then when writing the content of the "encrypted" data to the file:
- Write the new sprinkled array
- Write the
TEXT_SPLITTERconstant as it is
- Generate an MD5 of the original JSON data with the
SALTconstant and write it
And of course, the inverse process to import the data.
I built a small tool to apply this algorithm using Ruby, and after saving/exporting my character, it did work and I had access to shiny data like the following:
"soulsSpent": "0", "primalSouls": "34152", "mercenaryCount": 5, "gold": "1.244277239155236e135", "baseClickDamage": 15, "transcendent": false, "epicHeroReceivedUpTo": 1660, "rubies": 7165,
Writing the inverse was easy, and confirmed me that everything worked fine.
This is how the end of an original encrypted file looks:
And this is how a (valid) file encrypted with my tool/script looks. As you can see instead of randoms I just enter blank spaces at odd positions:
The truth is that even cheating, the game gets to some insane levels that you have to either wait a lot or do level grinding (by restarting via "trascending"), so I got bored too quickly. As often happens, tweaking or hacking a game becomes more fun than playing the game itself.
You can get the tool (needs Ruby) from my GitHub and easily see a simplified version of the algorithm.
Even if the code were didn't had so obvious names, as the text splitter fragment can be easily spotted at the end of the file (Look for
Fe12NAfA3R6z4k0z at both screenshots), just doing a classic saved game deltas diff would have raised awareness (whole content of the file would have changed except for that fragment) and made me search the SWF for that splitter string.