Hacking a freemium iOS app: Contract Killer … or unlimited play without spending a dime (or any other currency)

Let me start this post with a little rant. The iPad is a great product but it’s full of “spyware” and that sucks big time. One might argue that it’s not spyware, it’s just sending bits of information. Well, for me it’s damn spyware because I’m not authorizing the apps to send any information, much less unique pieces of information that can identify you forever. I can’t even conceive why the enterprise world will adopt the iPad with these kind of problems. If I was the CSO or CIO I would fight against this, and I mean real hard fighting. It sucks, seriously! It sucks so much, that I tried to firewall one of the ad networks and it starts connecting to different Amazon EC instances, more or less like a botnet client (this should be an interesting reversing project). The argument of high-availability for such behavior is weak – there are many HA solutions. If I want to firewall your shitty ad-network, let me, don’t try to fight it.
All this spyware crap is one of the reasons why I’m not fully using the iPad for web browsing and other more personal tasks. Apple should allow a Little Snitch like app, so users can have some control about what is going out of their devices. I really like Apple in some points, but this one pisses me off!

Back to the interesting juice… I was reading today some articles and I saw the announcement of this game, Contract Killer, based on a freemium business model, in app purchases. I decided to give it a try. After a while you need to buy energy credits so you can proceed in the game. Of course I was already more interested in exploring a way to remove that limitation than playing (I played a few rounds, it gets boring). A reversing brain is a dangerous brain 😉.

The credits information is written into a save game file. This can be found at the Documents/default folder, with the name savebh.dat (by the way, the app has the name BountyHunter.app). These are binary and seem packed/crypted (by the way, if you want to have fun with virtual fishes and don’t want to wait, you can use the same trick with iQuarium – edit the plist file with the properties, it’s not encrypted nor packed – BBEdit can handle it fine). Checking around the disassembly (don’t forget you need to decrypt the binary, use Crackulous for example) you find two interesting methods: CBH_XorCrypt::Decypher and CBH_XorCrypt::Cipher (CSaveManager class is also interesting, it calls the encryption method). If you breakpoint on the Cipher method and try to buy some bullets, debugger will break. Prototype is CBH_XorCrypt::Cipher(char *, int), meaning that R0 holds the unencrypted data and R1 its size. Do a x/30s $r0 and you can see the plaintext XML file 😃.

So my idea was to modify memory before it’s encrypted. I tried to modify one byte from the money, by computing the offset from R0 where it’s located and modifying its value – for example, from 500 to 900. This doesn’t work for some reason, probably some additional checks. While doing this, I reversed the crypt routine (it’s a simple XOR with a table) so I could write a small decryptor.

But before this, I was trying to breakpoint and modify the decryption. It happens when the game is loaded. Since you can’t load it from GDB (it’s not launched into the screen, so you can’t interact with the app), the only solution is to attach GDB. My dirty method is to launch _GDB with the following command:

gdb –pid=`ps ax | grep Bounty | grep mobile | awk ‘{print $1}’`

Open the game in iPad and quickly launch this command, so we can attach GDB as soon as possible, hopefully before decryption. Voila, it works. Now the trick is to let the program decrypt the save game, and then modify memory as in the crypt method. Well, it works. And the new save game will use the new value so it means credits, experience, points, hits, guns, etc etc etc. Now you just need to code a decryptor/encryptor and customize the whole XML file! Beware that the first 4 bytes in save game are a CRC32 and the next byte is the initial XOR key. I will not publish code on this to avoid any legal trouble (although these guys really deserve something like this due to the amount of spyware crap they use).

The security model applied here is weak because I have control of the data and I can manipulate it at my own pleasure. One of my ideas about the failure to modify at crypt stage was online storage of information regarding each player. I started sniffing traffic and that’s how I saw the amount of spyware 😉.
Probably a large majority of freemium games suffer from this kind of problems if there’s no data synchronization between the app and somewhere I don’t control (as it happens in online games, where only registered keys are allowed to play in servers).

Back to on track to what I was doing before this, damn curiosity!

Have fun, and fuck spyware (yeah I’m really annoyed)

I know how metrics are important to business, I’m a firm supporter of that. But how does sending my iPad name, referral cookies and other stuff qualifies as useful and benign metrics? It doesn’t! Developers should record useful metrics such as software versions and other anonymous info that allows them to know their customer base and improve their work but that’s it. Stop there, don’t be fucking greedy and stupid.

Just finished my little cryptor/decryptor. Everything works fine although the game crashes if some fields are abused (trial & error). It’s easier to reverse and rip the program CRC32 implementation – it’s easier and fast. Unfortunately, the game is boring and too repetitive. I’m addicted to Doodle Jump instead.