Disclaimer – 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.
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.
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.
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.
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
Trackback e pingback
-
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[...]...




Amazing example of how unprotected our stuff can be and how important it is to be paranoid about security. Thanks!
Thanks JP. It was nice getting to know you at the 360|flex show.
Valid Point.
Just wondering about 0.05% who can do this.
Yes its cool that its really difficult, but do you guys have any idea how your system can be hacked too?
As we stated, no system is perfect. But, Nitro-LM’s fundamental design difference from other systems is that there is a physical separation from the end user and the licenses you are granting them to use until licenses are needed and/or are required to be updated by your software. When you put the licensing logic and keys in the application (as in the example in this article) you have – NO CONTROL – and CUSTOMERS CAN (will) STEAL. With Nitro-LM there is a ‘cloud’ service that is the global-master control over licenses, their terms of use, qty, etc.- keeping you in control and in the ‘know’.
We did -NOT- design Nitro-LM to be ‘static’ like other systems or home-grown key-generation utilities. IF that 0.05% does figure out some way to compromise the system (very slim possibility) we can always push out a changed formulation very quickly to combat that (forcing the 0.05% to completely restart their efforts from ground zero). Being cloud-based, our customers could force old software to be upgraded to the new formulation immediately or let old software continue for as long as they want. The flexibility Nitro-LM provides is unparalleled with respect to this, and this goes for ANY software application (java, C/C++, .NET etc), not just Flex/AIR Apps.
To give you a bit of comfort. At this point, Nitro-LM has been running for 6+ years without issue.
Thanks David.
That does help and the rationale is sound. There is no absolute non-hackable system anyway.
You can only run faster than the hackers and be a step ahead. The cloud helps. Good stuff!
Interesting. What happens if the NitroLM servers are not available ?
Tom,
Nitro-LM servers are geographically isolated and fully redundant. If one server is unavailable due to network or taken down for maintenance, etc…, the client code will fail over to the next one on its list. If you’re completely offline, you will not be able to get a license. You have to be online and have Internet connectivity to at least one of the servers in order to grab a license. The checkout license type allows you to grab a license and then use it for a period of time in either online or offline modes. Demo licenses as described in the above post work similarly to checkout type of licenses and will run for a period of days you set or for a certain execution limit you set. When you sign up for Nitro-LM (free program included), we give you 10x the number of demos as standard licenses. So if you were to sign up for the free program /w 100 licenses, we give you 1000 demos along with that to play with. This program is mainly geared for startup companies or micro-isv who have an application and a dream, but not much money to pay for a quality licensing solution before they have a successful product and revenue stream.
hi, I need to remove a connection from a swf file to a remote server. can you tell me how to do this?
email me on office@littlebitsoft.com to send you the file.
thanks.
Hello! Awesome display of security vulnerability. I have stressed this at the company I work for with less then satisfactory results. I am currently attempting to “hack” the swf’s from my company’s apps. This is something I have never done before, so it’s a bit daunting. However I found your article a great reason to double my efforts.
-James B
(Any general pointers for a novice at this sort of thing?)
Im having a problem here where when I save the hex changes
and recompile it, NEMO says error cannot open file.. so I
double checked that it re compressed right by starting
from fresh by decompressing and re compressing and it worked..
so it seems to be that the hex editor is killing the format
the SWF expects or something when I save it?
Im using MAC hexfiend.. not sure how you were able to re-compress the
swf after hex editing and ideas would be great ive been at it for 4 hours already
Thanks man!
Oh and one more thing if I may add
Once I decompressed the SWF with your script.. i could not find any byte code sequenced for instance nemo showed the sequence of
getproperty result getproperty success pushstring “yes” ifne L1
So I came out with hex
66 72 65 73 75 6C 74 66 73 75 63 63 65 73 73 44 22 79 65 73 22 14 4C 31
Which is that exact sequence all in HEX where
66 == getproperty
44 == pushstring
14 == ifne
As per the document at adobe, but I could not find this sequence
at all..
Thanks for your help in advance!
Joey,
Unfortunately, I can’t help you. This hack was done with permission from the software authors. The post was written to show what’s possible so people will recognize that code security with flash is an issue. Working for nitro-lm, I can’t in good conscience help people with their various hacks.
Hey
Thanks for your reply and I do understand, but im doing this
for a school java project showing how SWF files can be hacked
all I really wanted to know is why does the hex editor wrangle
the SWF file.. that where Im stuck.. anyway thanks for your time
Andrew, I really need your help. There is an Adobe air application I would like you to hack. Could you please contact me so we can discuss the details of the project. Don’t worry though the program has not been copyrighted, I just need to make a few changes to it.
An excellent little reminder of just how easy it is to pirate vm software. Thanks for taking the time to go beyond just writing an article, and actually showing step by step just how easy it is.