代码改变世界

藏码

2009-10-14 23:30  宝宝合凤凰  阅读(364)  评论(2)    收藏  举报

[AS3] Hiding Assets And Code By Embedding SWF Within Another SWF

Published by sunny at 3:11 am under Flash, Tips

The technique discussed below is fairly easy to implement and will cost nothing other than a few minutes of your time. You can use this method in conjunction with code obfuscation, encryption or whatever other protection methods – this just adds another layer of protection. While this isn’t going to be a 100% foolproof protection, it is nevertheless better than no protection at all, and should help to deter most if not all casual decompiling.

As indicated in the title of this post, the basic idea here is simply to embed your actual SWF within another “shell” SWF. It is this “shell” SWF that you will then deploy/distribute.


MainShell Class
To embed a SWF within another SWF, you can use a document class like the one below:

package 
{
	import flash.display.Loader;
	import flash.display.Sprite;
 
	public class MainShell extends Sprite 
	{		
		[Embed(source="ActualSWF.swf", mimeType="application/octet-stream")]
		private static const bytes:Class;
 
		public function MainShell()
		{
			Loader(addChild(new Loader())).loadBytes(new bytes());
		}
	}
}

When this “shell” SWF is run, it will
(i) create an instance of flash.display.Loader;
(ii) add that Loader instance to the display list;
(iii) instantiate an instance of the embedded SWF as a ByteArray; and
(iv) load that ByteArray into the Loader instance.

This will work in the same way as loading an external module SWF into a host SWF, but in this case the module SWF is embedded inside the host SWF. This is different from loading external SWFs because any external SWF can still be easily obtained from the browser’s cache and decompiled separately.

This set up will be completely transparent to the end-users – it will look as if the actual SWF has been run.


How This Works Against Decompilers
This protection method assumes that decompilers cannot automatically identify, extract and decompile the embedded binary object as a SWF. Therefore, the assets (classes and symbols) in the “ActualSWF.swf” will no longer be directly accessible by decompilers.

I tried this embedding technique against the trial versions of a couple of decompilers (Sothink and Trillix) and the assets of the embedded SWF (ActionScript classes, artwork, movieclip symbols, etc.) are safely hidden from view.

Since this cost nothing and is so easy to implement, I would suggest you try it out and decide on your own the effectiveness of this. Wrap one of your SWFs in a “shell” SWF as described above, and try to decompile it using one of the decompilers out there. Perhaps the non-trial versions and/or other decompilers I have not tried may be able to defeat this simple layer of protection, but even if they do…


Taking Things Further
While it is possible that makers of decompilers could eventually implement a feature to properly identify, extract and decompile embedded SWFs, you can take things further and make the protection more difficult to overcome.

Instead of embedding the SWF directly, you could run it through some encryption and embed the encrypted SWF – it is mime type “application/octet-stream”, so you can really embed any binary file (even invalid file types). Subsequently, the “shell” SWF will decrypt the ByteArray before feeding it to the loadBytes() method of the Loader instance.

To be very clear though, the intention here is not exactly encryption. The real objective here is to intentionally “corrupt” the embedded SWF, so that even if extracted, decompilers cannot easily identify and run/decompile it as a SWF standalone.

For the purpose of corrupting the SWF, there are countless ways – using simple encryption, bytes transpositions, append/prepend useless bytes, etc. well, you get the idea… basically anything that make the SWF file invalid, no longer executable as a SWF. You can even split the SWF into two or more binary blobs and join them back during run-time.

Since there are so many different possible algorithms to corrupt the SWF, it is then practically impossible for decompilers to automatically identify the way to reconstruct the corrupted embedded SWF.


Disclaimer
Needless to say, if you decide to corrupt/encrypt the SWF, you must be able to reconstruct, in the “shell” SWF, the embedded binary object into a working SWF. As a result, while we may be able to prevent automated decryption (primary objective here), do take note that this provides no protection against determined hacking (decompiling the “shell” SWF, getting the decryption logic, extracting the embedded SWF manually, decrypting it and then running the reconstructed SWF through the decompiler).


FlashDevelop
For users of the FlashDevelop IDE, you are probably aware of its SWF assets browser (unlike decompilers, SWF sniffing is used here ethically, and beautifully, for the purpose of implementing code completion, etc.). If you attempt to browse the “shell” SWF within the FlashDevelop’s Project Manager panel, you will not see the assets (classes and symbols) in the embedded SWF. This can be used as a way to quickly verify if a SWF is protected using the “embedding technique” discussed above.