February 4, 2008 7:25 PM
Ted Patrick had posted about the distinction between loader.load() and loader.loadBytes() where he also mentions that the latter can be used to load an obfuscated / encrypted SWF. I've implemented exactly that in an AIR application using AS3 Crypto Framework to handle the encryption / decryption just to figure out how easy it would be to do it and what it's security implications might be. There's also a companion Flex application that uses loadBytes() but only uses a simple substitution cipher to hide the actual SWF data.

The concept is pretty straightforward: Your SWF is encrypted or obfuscated so that someone else cannot just grab the SWF and decompile it. Your application loads the SWF in it's memory, performs some computation on it's contents to get back the actual SWF1 and then load it using loader.loadBytes().

However, the whole thing will crumble if the key to decrypting the SWF is embedded in your un-encrypted SWF (which anybody can decompile).

Flex Example for loadBytes

This is a lightweight example highlighting the capability of loadBytes(). If you hit any of the "Get" buttons, it performs a URLLoader request to get a SWF. Each byte of the SWF has been incremented by 13 (ROT13) to fool SWF decompilers. Only the "Get SWF and Decrypt" button will reverse the substitution cipher to get the proper SWF data. This SWF is then injected into the current application and it's content becomes visible below the buttons.

View Flex loadBytes Example (View Source Enabled)

Hitting the first button will throw an error because the SWF data is not proper. The second button should load the SWF content below the buttons.

Note: Simple substitution cipher techniques such as ROT 13 can be easily broken.

AIR Version using AS3 Crypto Framework

The following AIR application uses the AS3 Crypto Framework to perform AES 256 bit encryption and decryption. The password string supplied during encryption is the key for decryption. Without the correct password string, the output SWF will never match the actual SWF. The application also has a "Load SWF" button that injects an SWF using loadBytes(). This injected SWF will be running with full privileges and access to all AIR APIs (i.e, it is in the AIR application security context).

AirEncryptSWF: AIR Application that encrypts, decrypts and injects SWF code.

AIREncryptSWF for AIR Beta 3 (View Source Enabled) - Download

Note: When you hit encrypt or decrypt in the AIR application, the UI may not update2 for some time. Please wait patiently till the application becomes responsive again.

Ideally, you could also do a MD5 or SHA-1 hash on the contents of the actual SWF and compare this hash with the hash obtained after decrypting the SWF. Only if the hashes match should you call loadBytes().

The existence of loadBytes() gives us an option to introduce a level of difficulty for some random dude while trying to grab your SWF and view it's code. However, the security of the system depends upon even the smallest aspect of it's implementation and like in all client-side technologies, complete security may be impossible to achieve. Ideally, such techniques should be thought of only as a precautionary measure and not as a complete fool proof solution.

CategoryAIR Comment(s)

[1] We're assuming it's not very easy to get the contents of the decrypted SWF from flash player's memory.
[2] Sadly, distribution of calls to the crypto framework is not supported via callLater() or by listening to an enter frame event.

Copyright © 2004-2011 Anirudh Sasikumar. All rights reserved.
Last Updated: February 4, 2008 8:32 PM