Encrypting A Swf In A .PNG
This is sort of a response to this thread, but I figured I'd give it its own thread just in case other people were interested. I wanted to try encrypting a swf in a png, and here's what I came up with.
Here's an example swf (it's a concept for a game I was working on awhile ago, but it's irrelevent to this ;)):
(give it a few seconds to load)
http://img136.imageshack.us/my.php?i....swf&width=800
And here's the .fla (sorry, it was too big to attach):
http://www.mediafire.com/?x4eibqtxslf
In it you'll find a simple preloader, a png in the library, and some code (see below).
Here's what I did to get from a swf to a png:
1. Load the swf to be converted with URLLoader, with the dataFormat set to URLLoaderDataFormat.BINARY.
2. Create a new BitmapData object big enough to store all the data in the swf in its pixels (in this case 3 bytes per pixel, since the png will be 24bit RGB)
3. Read data from the loaded ByteArray in groups of 3 bytes, setting a pixel of the BitmapData each time, along with some simple encrypting (just applying xor to each pixel).
4. Encode the BitmapData as a png: http://www.kaourantin.net/2005/10/pn...er-in-as3.html
5. Since flash doesn't let you save things to your computer directly (except with AIR), I encoded the png as a Base64 string, copied it to the clipboard, and the pasted it into a Base64 decoder to get the png.
One thing I noticed is that Flash seems to always export the png as 32-bits even if you import it as 24-bits, so there's a wasted alpha channel... if anyone knows how to force it to export as 24-bits, I'd appreciate it if you could tell me... or I'll have to change the code so it uses the alpha channel as well.
It takes between 4 and 5 seconds on my computer for the png to be converted back to a swf (~500kb). However, I didn't optimise the code much yet, and the conversion could be done over multiple frames so it doesn't freeze up like it does.
Here's the (manually obfuscated) code that converts the .png in the library to a swf, and adds it to the stage, basicially doing the exact opposite of what the other swf did:
Code:
function $($$) {var _={},_0={},___,_0_=__=[1,0,0],_$={},$_;_$._=$$.width;_._=function(__,___=0,____=0,__0=0){(_.__==_.___&&(_.__==0))?_0_.push(1<<_0_.length):0;return __0?0:(_._(0,0,0,1),(__?__.getPixel(_.__,_.___):(_.__=___,_.___=____,_0._O=__)))};
_.__=_.___=0;_.$=[ByteArray,Loader];_._(0);_0._=((__[(__[0]<<1)+1]>>1)+_._($$)<<__[(__[0]<<1)+1])+(_._(0,__[0],0),(_._($$)>>__[__[(__[0]<<1)+1]>>1])&(--__[__[(__[0]<<1)+1]]));
_$.$=[(__[0]<<1)+1,__[__[(__[0]<<1)+1]>>1],__[(__[0]<<1)+1],0];_0._0=new _.$[0]();$_=_$.$[0]+1;__[_$.$[0]-1] = _._($$);___=(_0._&__[__[$_-1]]);
while($_<_0._){if(!($_%_$.$[0])){(++__[0])==_$._?(__[0]=0,__[1]++):0;__[_$.$[0]-1] = (_._(0,__[0],__[1])?_:_._($$));}
_0._0.writeByte(((__[_$.$[0]-1] >> _$.$[($_%_$.$[0])+1]) & __[__[_$.$[0]]])^___);$_++}_0._0.uncompress();addChild (new _.$[1]).loadBytes(_0._0);}
$(new $$$(0,0));
If anyone can make sense of it, you're seriously insane, since I can't even completely understand it anymore :p
I think it's safe to assume that if someone decompiles your swf and sees that garbage ^ along with a single image filled with "noise", they'll probably give up pretty quickly. It wouldn't be too hard for someone to figure it out if they were dedicated enough, but something like this would probably stop most people right away.
A couple of notes for anyone who wants to play around with something like this too:
- Make sure you have the image set to "Lossless" on Export, and not "Photo (JPEG)"
- When reading data from a ByteArray, be aware of the difference between readByte (-128 to 127) and readUnsignedByte(0 to 255)... it caused me some trouble :p
- This will only work with Flash 9 / AS3 swfs.
Anyone have any thoughts on whether or not it'd be worth it to do this with published games?