Today I learnt that my sister’s house had gotten burglarized (laptop, camera and my two original gameboys with 30ish cartridges gone), who the hell would rob a student’s house?), so I needed a distraction to get my mind off it. Since I like playing 7 Cities on the iPhone, I started a game, and the online high score submission intrigued me, so I thought if I could somehow hack it to put myself in the first spot.
I figured that they probably used a simple HTTP request to post it, and if I could intercept it I could change the parameters accordingly and send a counterfeit one. I fired up tcpdump and captured the outgoing packets. Loading them in Wireshark, I came upon this:
“Great”, I thought. “This should be pretty simple”. Changing the parameters should be trivial, and then my name will be featured in the illustrious High Score board. Looking more closely at the parameters, though, I noticed this:
It needs a key to submit. These developers are smarter than I gave them credit for. It looks like an md5 hash, probably of the submission parameters and a secret key (if they know what’s good for them, anyway). This utterly foils my plans, since it is impossible to get a correct hash without the secret key. I was about to give up, but I was too lazy to do anything else, so I fired up IDA and disassembled the 7 Cities binary. This is what I came across:
My ARM assembly might suck, but that’s the submission URL, and “%@%@%@%@%@%@%@%@%@” looks like something I’d use to generate a hash. Wait a minute, though, what’s “rey%q134as!%0”, just above these strings? It looks like a secret key.
Not knowing how the parameters are passed to the function that concatenates them, I decided to write a little Python script to generate all permutations of the URL parameters, hash them and see if they match the hash I got:
import psyco import md5 psyco.full() def all_perms(str): if len(str) <=1: yield str else: for perm in all_perms(str[1:]): for i in range(len(perm)+1): yield perm[:i] + str[0:1] + perm[i:] target_digest = "cd208d4171f68a2c58a24a64604dcb24" data = ['Stavros', '29950', 'Hard', 'Map2', 'c0d7db9bf4fb1788ebe27653e5f4d34f', 'rey%q134as!%0', '1', '7', '527'] for perm in all_perms(data): if md5.new("".join(perm)).hexdigest() == target_digest: print repr(perm) break
A second later, I get a collision. I look at the order of the parameters, change some numbers around and have my script generate a new hash. I post that URL to the 7 Cities HTTP server and visit the online scores, and what do you know:
(That’s me in the top spot, in case you can’t see). I was, for one brief moment, the best 7 Cities player in the world, even if I didn’t actually have the patience to sit through a 7 hour game.
So that’s how I got to be king for a day.