I’ve recently been looking at Adobe Air applications and seeing if it was possible break them. Turns out it is – and it’s super easy. Here’s a run-down of how I managed to unlock the full version of an application.
But first, I’ll give a short introduction to Adobe Air Apps. They’re simply packages for Adobe Flash, Actionscript, and other files. Adobe Air and Flash is comparable to Java jars and class files. After installing the AIR application, there are usually SWF flash files stored in the installation directory. These SWF files are usually the core component of the program.
In this demo, I’ll breaking a tool that requires you to buy “credits.” If you have no credits, the program runs in evaluation mode.
After installing the application, I went into the installation directory and found an SWF file, which I assumed was the core file.
The first thing I did was run it through SWF decompresser (a decompressor, not decompiler). The program I used is called swfdecomp, which can be downloaded here (mirror). Running through the decompressor should yield a slightly larger file.
Next, I opened the new SWF file with a decompiler. I used Sothink SWF Decompiler, which has a free 30-day trial.
From the right sidebar, I navigated to the “Action” resources, which are, I presumed, the Actionscript files for the SWF file.
As you can see, there’s a function called “GetCredits” that returns an int. Looking more into the function, I saw there were three return statements. Two conditionals return 0 and another return calls the parseInt function.
And if you look at the function below the GetCredits, the IsActivated function just checks if GetCredits returns a positive integer. So all I had to do is make GetCredits return positive every time.
There are three return statements, so you may think that you can just trace the program, find out which return is being called, and modify that return. Instead, I decided to just change all three return statements.
I copied the decompiled source code into notepad and then hit the “Raw Data” button on Sothink, which gives the bytecode.
Next, I opened the SWF file in a hex editor. You can use any, but I used HxD.
Now to find the bytecode that needs to be modified. It’s not hard to follow the bytecode when you have the source code next to it. The highlighted code on both windows correspond to the same thing.
The green comments above each line in Sothink is the hex representation of the corresponding bytecode. So I am dealing with three different “forms” of the same code – the decompiled source code, the bytecode, and the hex. As you can see in the picture above, “return 0;” is represented by pushing 0 to the stack (_as3_pushbyte 0) and returning the stack (_as3_returnvalue). The hex representation of this is 24 00 48. From this, I can infer that 24 means pushbyte, 00 is the value to be pushed, and 48 represents a return. So now I know that I need to change 24 00 48 to change the return statement (Important).
Since I don’t want the program to return 0 credits, I can go into the hex editor and change values. And because there’s likely a lot of 24 00 48’s, I looked for an “uncommon”/identifying line to search. In the hex editor, I searched for “2c fb 2c”, or push “Credits”, which was a few lines above the return statement.
Now I know the next occurrence of 24 00 48, or return 0, will be the right one. Since (from above) I know that the 00 represents the value pushed onto the stack, I can change this. I changed it to 0A (10 in hex), so now, instead of returning 0, it returns 10.
Going back to Sothink, I scrolled down and found the next return statement.
I did the same thing in my hex editor and changed the 24 00 to 24 0A.
Now to deal with the return parseInt part. The bytecode for this is considerably larger than the simple return 0; from before.
Luckily, in this program, it’s fairly simple. You can see that there’s a pushbyte 10 already in there. You may be wondering why the program does that. When the application calls parseInt, the default radix (base) is 10, so naturally, the bytecode pushes int 10 onto the stack to be used in the parseInt function. What I did was force a return call right after the 10 was pushed onto the stack, causing the parseInt to be unreachable. To do this, I replaced the 46 after the 24 0A with a 48, which represents a return.
As you can see, I over-wrote the return into the parseInt function. This may break the parseInt function, but since it’ll never reach that part, it doesn’t matter.
Now it’s just a matter of saving the modified SWF file and replacing the original copy from the installation directory.
When I run the program now, it says I have 10 credits left.
And that’s it! This is a pretty simple program, but I’ve still yet to find an AIR application that’s actually well protected. If you have any questions, feel free to email me or comment below.