My current Perl Ironman Challenge status is: My Ironman Badge

Wednesday, March 10, 2010

Of Exquisite Nerd Hackery

DISCLAIMER: The following post is for educational purposes only. This post details circumvention of a registration function in a popular flash game. The author does not condone copyright infringement. The author paid for the game and encourages others to support independent developers.

And so our journey begins. Robokill is an awesome game. It is like Legend of Zelda with guns. I sunk some time into it last night. Just ask my wife, I was cursing up a storm because one of the levels was being a bitch to finish. In other words, I ♥ Robokill.

But then came to the end of the demo. Up popped the REGISTER ME screen in the game asking for an email address. Hrm. Odd. So I plunk down "" just to see what would happen. It failed obviously, but Firebug happened to be on and I saw just exactly what kind of request was being sent and the response it was getting. It was just a dumb HTTP GET with the email and a salt in the URL like so:

And the response as just plain text: is not a registered email address! caccabad

Wait. What? That's all? The gears started turning at this point.

What if I could somehow subvert that request and return a valid result? And what does a valid result even look like? First thing is first, I need to make sure DNS points to somewhere I control.

I logged into the local fileserver. Here at home, I am running dnsmasq which is an awesome little utility that provides DHCP services, and local DNS + forwarding. I added an address for and point it back to this machine.

Next step was to actually respond to the request. This is when I thought of mst's wonderful Web::Simple. So my first attempt at returning a result was this:

So how did I run this? I mean it looks like a dumb CGI script. Easy. Plack. I simply said:
sudo plackup -p 80 hacks.psgi

(I know running on port 80 while sudo is fail, but remember this is a quick hack. A better solution would have been for me to write some iptables rules to send the traffic to a non-privileged port)

As you can see, I naively thought that perhaps the server was simply hashing the result and returning it. It would need to be something the client can do too. That failed. So I tried other combinations of things and ultimately wasn't able to make any headway.

Then another bright idea came to mind, what if I decompiled the .swf and peered inside the action script to see what it doing? So I downloaded a couple of flash decompilers and installed them in a windows vm. The first one was lame and wouldn't let me see the action script at all without paying (har har). The second one was much more generous though. It let me look but not copy the code. WIN.

So take a peak inside and what do I see? Something like this:

Nuh-uh. Really? That dumb?

So I adjust my code like so:

And like magic it works.

The last step in the process for me is to be able to play the game offline. So I try to load the .swf directly in the browser. So far so good. Even the register check still works. But when I go to press "Start" it wants to popup a window and take me back to their website. Well that is dumb. I want to play it offline.

So back into the decompiler I go and I find another tidbit that is explicitly checking the URL for their domain name. Huh. So I adjust my Web::Simple app one last time to search up the file directly:

Now it works whenever I want. But was it really worth my time and effort? No. All in all, it took me about 1.5 hours from start to finish (knowing nothing about Web::Simple, Plack, and futzing with flash decompilers). It would have been much easier to just go get the credit card from the wallet in the other room and pay them the ten bucks first instead of showing off my 1337 skillz. That said, this morning, I did pay them for their wonderful game:

No comments:

Post a Comment