Upcoming Events
Southwest Gaming Expo
11/20 - 11/22 @ Dallas, TX

Workshop on Network and Systems Support for Games (NetGames 2009)
11/23 - 11/25 @ Paris, France

ICIDS 2009 Interactive Storytelling
12/9 - 12/11 @ Guimarães, Portugal

Global Game Jam
1/29 - 1/31  

More events...


Quick Stats
6557 people currently visiting GDNet.
2341 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!



Link to us

Link to us

Home » Features » Product Reviews » SWF Encrypt
  Intel sponsors gamedev.net search:   

Product Reviews
Jump to:
Software
All product reviews

Product: SWF Encrypt
Developer: Amayeta
Reviewer: John Hattan
Posted: August 12, 2005
Rating:
Discuss this review

SWF Encrypt
by John Hattan

Ever since Macromedia made the .SWF format public, the market for Flash decompilers has opened up, and the results have been mixed. While it's opened a new market for SWF-generating tools, and it's nice to be able to recover your source code if your original Flash project is lost, it's also a boon for crooked webmasters who want to make a few bucks off your hard work by decompiling, changing, and re-deploying your game as their own. I've also heard a couple of horror-stories of consultants who have "mocked up" Flash-based websites for clients, only to have the clients decompile their projects and finish them cheaper elsewhere.

And this, unfortunately, is the fate of the developer working with an open file format.

To combat this problem, a few efforts have been made to make SWF encryptors. Script obfuscation has been popular in the Java community for a while and has become commonplace with J2ME (baby Java for cellphones), as the tools not only make the code unreadable but also shrink the classes by compressing function and variable names down to one or two-letter equivalents.

While Java encryptors are commonplace, SWF encryptors are just getting started. For at least a year I'd seen heard promising news and seen a couple of half-written tools that I could never get working, but I'd never seen an actual working first-class SWF protector until SWF Encrypt (formerly Flashincrypt).

To test it out, I first built a simple game in the style of the immortal Click The Yellow Rhombus. I made sure that this game was simple but contained graphics, sound, and ActionScript code. It's compiled for the Flash 6 player.


(fish.swf size = 17,873 bytes)

Here's the original commented ActionScript code for the game.

stop();
// set up the initial conditions for our game
fish._xdelta = Math.random()*3+3;
fish._ydelta = Math.random()*3+3;
fish._rotdelta = Math.random()*3;
score = 0;
function onMouseUp()
{
  // check to see if the user clicked on the fish
  if(fish.hitTest(_root._xmouse, _root._ymouse, true))
  {
    // if so, change his color
    var fishColorizer = new Color(fish);
    fishColorizer.setTransform({ ra: 100, rb: Math.random()*512-256,
                                 ga: 100, gb: Math.random()*512-256,
                                 ba: 100, bb: Math.random()*512-256, aa: 100, ab: 0});
    // and play the sound
    var fishSound = new Sound();
    fishSound.attachSound("bird");
    fishSound.start(0,1);
    fish._rotdelta *= -1;
    score += 1;
    scoreText = "Score = "+score;
  }
}
function onEnterFrame()
{
  // called 24 times a second, this updates the fish's position and rotation
  fish._x += fish._xdelta; fish._y += fish._ydelta;
  if ((fish._x < 20) || (fish._x > 380)) fish._xdelta *= -1;
  if ((fish._y < 20) || (fish._y > 380)) fish._ydelta *= -1;
  fish._rotation += fish._rotdelta;
}

I then compiled the code to an SWF file, and the fact that you got this far confirms that you got bored playing it already.

I then ran the compiled un-encrypted SWF through a popular Flash decompiler, Sothink SWF Decompiler (build 50318, the latest I had). In addition to allowing me to save out the fish graphic and the sound, it was able to decompile the Flash bytecode into the following script. . .

// Action script...
// [Action in Frame 1]
function onMouseUp()
{
  if (fish.hitTest(_root._xmouse, _root._ymouse, true))
  {
    var _l2 = new Color(fish);
    _l2.setTransform({ra: 100, rb: Math.random() * 512 - 256,
                      ga: 100, gb: Math.random() * 512 - 256,
                      ba: 100, bb: Math.random() * 512 - 256, aa: 100, ab: 0});
    var _l1 = new Sound();
    _l1.attachSound("bird");
    _l1.start(0, 1);
    fish._rotdelta = fish._rotdelta * -1;
    score = score + 1;
    scoreText = "Score = " + score;
  } // end if
} // End of the function
function onEnterFrame()
{
  fish._x = fish._x + fish._xdelta;
  fish._y = fish._y + fish._ydelta;
  if (fish._x < 20 || fish._x > 380)
  {
    fish._xdelta = fish._xdelta * -1;
  } // end if
  if (fish._y < 20 || fish._y > 380)
  {
    fish._ydelta = fish._ydelta * -1;
  } // end if
  fish._rotation = fish._rotation + fish._rotdelta;
} // End of the function
stop ();
fish._xdelta = Math.random() * 3 + 3;
fish._ydelta = Math.random() * 3 + 3;
fish._rotdelta = Math.random() * 3;
score = 0;

As you can see, ActionScript bytecode as compiled by Flash itself isn't all that secure. Apart from the comments and the names of a couple of local variables, the decompiler was able to make some very readable code. If you were a sneaky hacker who wanted to pull out the credits and remove any server-based protection, you'd have a rather easy time doing it.

I then popped up SWF Encrypt. The user-interface is quite simple, and there are only a few encryption options relating to what you want to encrypt (main scene and/or button event and/or component and/or symbol movieclip) and how strong you want the encryption to be.


(click the picture for a full-size view)

Once you've got your file and options picked, press the "Encrypt File(s)" button and it'll make a "protected" SWF file. I chose to add the "_secure" to my original game (which the tool recognizes as being protected, so you can't protect your SWF twice) rather than overwriting the original. The newly-protected version of the game is below.


(fish_secure.swf size = 18,006 bytes)

Apart from growing by 133 bytes, the protection step doesn't appear to have changed the game a bit. SWF Encrypt's help warns that setting the encryption to the "most aggressive" setting can cause compatibility problems and that you target the Flash 7 player, but the file still seems to work fine under the Flash 6 player, which is available on about 99% of machines out there.

Putting on my "sneaky game thief" hat, I then tried to load up my newly-protected game with the aforementioned Sothink decompiler. I was expecting to see some uglier code, but it went further than that. I ended up with this.

// Action script...

// [Action in Frame 1]
var \x1 = 430;
while (\x1 == 430)
{
    \x1 = \x1 + 250;
    break;
} // end while
if (\x1 == 680)
{
    \x1 = \x1 - 406;
}
else
{
    
} // end if

Not only is this pretty unreadable, but it's not even the complete source. In fact, I'm not sure what it is, but it's a far cry from the output from the unprotected SWF.

Hoping to dig a little deeper, I grabbed the demo version of the just-released Eltima Flash Decompiler. It didn't crash, but produced the following code.

// Frame 1 actions...
// Error. This tag contains erroneously written ActionScript, which cannot be decompiled.

Which isn't all that useful to a potential game-thief such as myself. I then tried ASV 4.086 (another decompiler) and got this.

    var \x01 = 119;
    // swfAction0x03  // Unknown action
    while (\x01 == 119) {
        Set("\x01", \x01 + 550);
        // unexpected jump
    }
    if (\x01 == 669) {
        Set("\x01", \x01 - 306);
    }
    // unexpected jump

Rats. It looks like I'm never gonna be able to hack this game.

Finally, I got out the big guns. I got FLASM, which is a command-line assembler-disassembler for SWF files. It gets around the whole ActionScript thing by working only with Flash bytecode (a pseudo-assembly language interpreted by the Flash player). If anything, I should be able to get a dump of some hard-to-understand but still hack-able and compile-able pseudo-assembly. Here's what I got.

  frame 0
    push '.'
    push 430
    varEquals
   label1:
    push '.'
   label2: // Wild label in the middle of an action, now placed before next action
    getVariable
    push 430
    oldEquals
    not
    branchIfTrue label3
    push '.'
    push '.'
    getVariable
    push 250
    oldAdd
    setVariable
    branch -1206 // branch target not found
    branch label1
   label3:
    push '.'
    getVariable
    push 680
    oldEquals
    not
    branchIfTrue label4
    push '.'
    push '.'
    getVariable
    push 406
    subtract
    setVariable
    branch label5
   label4:
    branch label2
   label5:
  end // of frame 0
  
  exportAssets
    3 as 'fish'
  end // of exportAssets
end

Wow, that's not all that helpful either. In addition to making the some of the variables into unprintable characters, the code's clearly not all there.

Note that SWF Encrypt only obfuscates your SWF's ActionScript code. The graphics and sound (i.e. the fish clipart and chirping noise) in the protected SWF were still quite readable, and all of the decompilers had an easy time exporting the graphics and sound into files that I could edit with a graphics/sound editor. While having obfuscated ActionScript did prevent me from changing and recompiling the game, I still had the opportunity to "borrow" the graphic and sound for a new game of my own. Maybe someday there'll be a tool that can similarly obfuscate the graphics and sound in a SWF, but until then SWF Encrypt will keep your ActionScript reasonably safe and will prevent folks from modifying and recompiling your game easily.

SWF Encrypt does the job. It takes your existing SWF, which is currently a wide-open door for code-thieves, and produces an SWF with ActionScript that no existing decompiler (or even disassembler) I could find could figure out. The tool is downright simple to use. Far as I can tell, the tool will only target Flash 6 or 7 players. Honestly this isn't much of a problem unless you've got a lot of OS/2 or WebTV viewers. Flash Lite 1.1 (which is based on the Flash 4 player) also probably won't be happy with SWF Encrypt-ed files, but it's a poorly-kept secret that a new cellphone player based on Flash 7 is on the horizon.

My only complaint of substance is that the online help and support section of the website could use some more technical know-how. SWF Encrypt's help file says that there are other techniques you can use to prevent decompiling that are available on the support section of the website. Going to the support section of the website, though, I find that there are other techniques you can use to prevent decompiling that are available on the support section of the website. If there are techniques available, I can't find them. After talking to the tech support guys, they assured me that technical info would be appearing on the site presently. Hopefully by the time you read this, the site will have the promised technical tips.

If you're in a position where you're releasing SWF files, and you don't want your hard work taken apart and re-released as someone else's game, you might want to take a hard look at SWF Encrypt. Thus far, it's the first and best solution I've found for protecting your ActionScript investment.