posted by | on , , , , | 16 comments

burglarDisclaimer – Simplified Logic respects intellectual property rights and in no way supports using hacked or cracked software. What follows is simply an educational exercise with the intent of highlighting the security dangers of releasing unprotected software in virtual machine environments such as the Adobe Flash Player.

It’s fairly common for me to see comments on blogs and forums playing down the security risk from decompiling software. They say things like “Source code isn’t intellectual property”, or “Nothing is 100% secure, so why bother with protection?”. While it’s true that in virtual machine environments NOTHING is 100% secure, there can be great value in taking some measures to protect your software. Many company’s approaches to software security are akin to the Jeff Foxworthy comedy bit about putting the house keys under the mat with a sign on the front door saying “The key is under the mat…” Your only hope is a blind burglar (listen at 20:25 into the clip).

James, one of our salesmen, keeps his pulse on the Flex/AIR community and every so often will reach out to someone with a software product he finds really impressive or cool. He recently got a “blind burglar hopeful” e-mail back from one of these companies who are doing some really neat and innovative stuff. The name has been changed to protect the innocent.

Hi James,

thank you for contacting us again. We are currently not worried enough to invest, but the two comments to the post you send me were really interesting.

I am sure you would welcome us as your customers if you could make us worry a little more. Feel free to have a go at decompiling our app and making some changes to it. We would also be interested to know how we could make our future webapp less vulnerable with your technology.

Kind off sounds like we invite you to break into our shop, to then pay you for it – nice scenario ;-) But I guess it makes sense.

All the best,

“Steve”

James had sent “Steve” a link to this InsideRIA blog post having comments where someone wasn’t concerned about protecting source code. Again, another example of “blind burglar syndrome”.

Normally, we don’t make it a habit of cracking potential customer’s software, but since we were basically invited to do so I decided to take a look under the hood. My other hope is that this blog post will wake people up to the real dangers of not protecting your source code.

The first thing I noticed after launching Steve’s AIR app was the initial dialog box. It had options to enter a license key, a button to pay, and a “Try” button saying I had 14 days left on my trial. The first thing to note is that when a hacker (or burglar) tries to break in, they rarely go in through the front door like you’d expect them to. I could have attempted to figure out the license key algorithm, but instead, I decided to try giving myself an unlimited trial period. The first thing I tried was back-dating my PC. I set my computer’s clock to the first of the month and was delightfully surprised to find that I now had 35 days left on my trial instead of 14. After getting past the initial dialog box, I could reset my computer date back to the current date, or even into the future (where my trial would have normally expired) and everything still ran fine. This is the equivalent of locking the front door, but having nothing but an unlocked screen door in back.

The next thing I tried was using a decompiler to look inside the main SWF file. I found a class called TrialManager that was used to determine whether we’re running in a trial mode or not.

attackpoint

I realize that if I can attack the equation for number of days remaining in the trial, I can give myself a lot more days. If I make the numbers in the equation small, then the number of days remaining will become large. If was going to hack this “for real”, I’d also modify the equation so that it could never return 0 in the event that firstRunDate was set. For demonstration purposes (and so I don’t get sued or taken to court), this hack as described will only work on the single day that the app is installed and cracked.

Now that I’ve found the weakness I want to exploit, I need to be able to modify the ABS bytecode directly. To do this, I need to work with the uncompressed version of the SWF file. Here is the little Java app I created that is capable of decompressing/recompressing a SWF file. I found information on the SWF file format and its compression algorithm in Adobe’s SWF Spec for version 10. SWF files have their headers in the clear, with the remaining bytecode compressed with the ZLIB algorithm.

package com.westberg.swfcompress;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterInputStream;
import java.util.zip.InflaterInputStream;

public class SWFCompress
{

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		if(args.length < 2)
		{
			usage();
		}

		if(args[0].equalsIgnoreCase("c"))
		{
			//compress
			try
			{
				DataInputStream dis = new DataInputStream(new FileInputStream(args[1]));
				byte[] header = new byte[8];
				dis.read(header);
				if(header[0] != 0x46) //'F'
				{
					System.out.println("Un-Compressed header not found.  cannot compress");
				}
				else
				{
					//yay, we have an un-compressed file.  compress it and write it out
					DataOutputStream dos = new DataOutputStream(new FileOutputStream("c_"+args[1]));
					header[0] = 0x43; //'F';

					dos.write(header);

					byte[] chunk = new byte[2048];
					int bytesRead = 0;

					DeflaterInputStream compressor = new DeflaterInputStream(dis);

					while((bytesRead = compressor.read(chunk)) > -1)
					{
						dos.write(chunk, 0, bytesRead);
					}

					dos.close();

					System.out.println("Compressed to file: c_" +args[1]);
				}
			}
			catch (FileNotFoundException e)
			{
				e.printStackTrace();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else if(args[0].equalsIgnoreCase("d"))
		{
			//decompress
			try
			{
				DataInputStream dis = new DataInputStream(new FileInputStream(args[1]));
				byte[] header = new byte[8];
				dis.read(header);
				if(header[0] != 0x43) //'C'
				{
					System.out.println("Compressed header not found.  cannot decompress");
				}
				else
				{
					//yay, we have a compressed file.  decompress it and write it out
					DataOutputStream dos = new DataOutputStream(new FileOutputStream("d_"+args[1]));
					header[0] = 0x46; //'F';

					dos.write(header);

					byte[] chunk = new byte[2048];
					int bytesRead = 0;

					InflaterInputStream decompressor = new InflaterInputStream(dis);

					while((bytesRead = decompressor.read(chunk)) > -1)
					{
						dos.write(chunk, 0, bytesRead);
					}

					dos.close();

					System.out.println("Decompressed to file: d_" +args[1]);
				}
			}
			catch (FileNotFoundException e)
			{
				e.printStackTrace();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		else
		{
			usage();
		}
	}

	private static void usage()
	{
		System.out.println("Usage: java -jar SWFCompress.jar [c|d] Movie.swf");
		System.out.println("\tc - compress a swf file");
		System.out.println("\td - decompress a swf file");
	}

}

Now that I have a decompressed SWF, I need a bit more information about the equation so I can find the right location in the bytecode to modify. To do this, I use an AIR application called Nemo440. Nemo400 is a disassembler, so it will show me the bytecode commands in a readable p-code format.

nemo

I used the Actionscript Virtual Machine 2 Overview Document from Adobe to look up the hex code values for pushshort, pushbyte, and multiply. After figuring out that the number 1000 represented as a U30 integer in hex bytecode is “E8 07″, I was able to run a hex search for “25 E8 07 24 3C A2 24 3C A2 24 18 A2″. This is equivalent to the equation from the Nemo screenshot above. For my purposes, it was simplest to replace all of the 3C (60) and 18 (24) numbers with 01. That will give me a very large number for days remaining when this equation runs.

hxd_hacked

I then re-compress the SWF using my Java program and run it through the decompiler again to make sure my equation was changed correctly.

after_attack

The final step was to use the ADT command that ships with the Flex SDK to repackage and re-sign an AIR bundle with my own self-signed certificate. I also made sure to include the various images and other assets/modules that came with the original AIR app. After installing, I was able to run the application and it showed that I had a trial with 72771 days remaining (almost 200 years). When I ran the trial the next day, the trial did correctly show up as expired (as expected since I didn’t remove the inline-if statement from bytecode that would have allowed the equation run all the time).

An Ounce of Prevention goes a Long Way..

For those developing commercial applications on virtual machine environments, I hope this little academic exercise opens your eyes as to what is possible from the other side of the piracy fence. Nitro-LM isn’t a 100% perfect solution when it comes to product licensing and/or code protection. However, Nitro-LM was designed to stop 99.95% of people out there, and make it excruciatingly difficult or exceedingly time-consuming for the other 0.05%.  We do this via a ‘paranoid’ encryption and security model coupled with a ‘cloud’-base authentication/authorization model for your on/off-line application(s).

For this example, Nitro-LM’s ‘cloud’ services would have provided a ‘single’ time zone and a ‘single’ point of accountability for the end-user.  This means that the terms of use for the software would have been managed on Nitro-LM’s servers, so even if the SWF got hacked to somehow request a 200 year license from Nitro-LM, Nitro-LM’s servers will only return them what they are allowed to have – e.g. a 14-day demo license or a license to the terms which have been purchased. The source-code could also have been encrypted with Nitro-LM so that an attacker would have had to go through Nitro-LM before getting to anything of value.

16 comments

  1. JP Bader
  2. valentin
  3. James B
  4. Joey
  5. Joey
      • Joey

Trackback e pingback

  1. Avr Code Examples,Avr Code,atmega128 code,source code Avr ,
    Avr Code Examples,Avr Code,atmega128 code,source code Avr ,... [...]How to Hack an AIR App SWF @ Nitro-LM Blog[...]...

Leave a Reply

Powered by Sweet Captcha
Verify your real existence,
Drag some popcorn to the box
  • captcha
  • captcha
  • captcha
  • captcha