Skip to content

Flash security: Protecting against PreloadSWF (SWF Hijacking)

September 30, 2010

Finally! here is a half-answer.

If you have read my last posts, you now know the power of Flash hijacking via preloadSWF.
I never given a lot of feedback about how to block this attack because I didn’t know any.

I’ll skip some step on how preloasSWF work, if you want to know please read my previous articles: One SWF to rule them all! and FlashPreloadProfiler
And for those who didn’t knew yet, the last version of FlashDevlelop now support PreloadSWF easy integration for profiling your application with FlashPreloadProfiler!

Case study

The only thing happening before a SWF loaded (allComplete) callback is the constructor of that loaded SWF.
This means it’s the only moment you have to “do something”

Let’s suppose you have a project you want to keep the code from being: viewed, modified, copied.
And let’s suppose you have some kind of classic setup:
A obfuscated launcher, embedding an encrypted SWF containing the whole code base.
In its constructor, the launcher create a key, that decrypt the embedded SWF and use loadBytes to instantiate it before adding it to the stage.

The Basics

The whole protection reside around one very simple flash behavior.
When a SWF gets loaded, FP give a (incremental) name to the root object.
The first one being loaded is called “root1” and then “root2” etc.
This also applies to the preloaded SWF which is loaded first, hence is being named “root1”

The one who identified this behavior was one of my new friend Josh
We also exchanged a lot recently on what could be done to prevent preloadSWF hacking. In fact, he challenged me!

Knowing the root1 trick help a lot because it is a native behavior on a read-only property.
So when you start an app you can always detect if there is some other app spying on it by adding this to your code:

if (root.name != "root1") { while(true) { /* do nothing*/ } }

and it will freeze the whole app indefinitely.

No more app hijacking using PreloadSWF!

The fight still goes on

You only solved half the problem. Now an attacker could not run your app with a preloader, but it would still be able to retrieve your decrypted codebase because you have a nice feature in flash preventing the process to hold the CPU for too long (15 sec.). After a few secs, the player is going to throw an error. If you choose to cancel, or continue, it won’t change a thing. The preloadSWF is going to be called anyway.

You MUST not start processing (decryption, loadBytes, etc) the main file before bugging the process with root.name!=”root1″ and here is why:
If you have started loading your main SWF in the constructor or the init function, you’re about to get hacked.
When the preloadSWF is hooked, it can access the loader used to download the main SWF and read the whole unencrypted SWF by using the loader.loaderInfo property “bytes”. When the attacker have access to the unencrypted files data. He still have to save that data somewhere from the preloader in order to reverse engineer it. Using clipboard copy of bytes would not work because it would required a mouseEvent (which you don’t have).
Still, a simple encoding before outputting it in flash traces would do the trick:

trace(Base64.encode(loaderinfo.bytes)) 

You can now post-process the file. easy!

ping-pong

One might think “I’ll hide the loader in a private var, or lose the pointer until the loading is done so that the preloader would not have access to it.
Retrieving the loader pointer is simple enought: Use SamplerAPI object instantiation to get that object pointer without even searching for it in the code.
So if you want to protect against samplerAPI object discovery attack, make sure you call clearSampling() and stopSampling() at the end of your constructor or initialization function.

PreloadSWF user Identification

you don’t have access to a lot of thing in flash that might help you identify who’s profiling your app. You have access to the IP and a few params, but not much!
Here is how to get “the local path” of the preloader SWF of the client machine:
First, in your application constructor, add a “allComplete” event listener just like the preloadSWF does.
Also in the constructor, use the samplerAPI and start cumulating samples using startSampling();
Then when you receive the allComplete callback, read all samples, there will be some undefined
object in there due to SecurityDomain mismatch, but you’ll have the actual StackTrace of the activation-object created. It looks like this:

new undefined [activation-object](),root1/allCompleteHandler()[C:\Dev\jpauclair\FlashPreloadProfiler\trunk\src;;root1.as:73],[all-complete]()

As you can see, the root1 is being used in the preloadSWF. And … here is my name!

ping-pong again

The preloader only have to clearSampling manually to counter this technique. Preloader win again…

Loading a SWF in “stealth mode”

As soon as you use loader.load or loader.loadBytes, a allComplete event will be dispatched giving the bytearray data to the preloader.
I found only one way to “merge” a main file or a library into the current applicationDomain code without having the preloader “seeing it”. Sadly, it’s not a good technique for production.
The trick is to add a parameter in you SWF main class constructor. This is going to throw an error as soon as the SWF is loaded and the allComplete event will not be dispatched at all!
Still, the loaded code is already merged with the current applicationDomain and you can use “hasDefinition” and “getDefinition” to instantiate the classes you want.

Summarizing

-PreloadSWF can hook on any SWF
-crash the app as soon as your app root.name != root1 (there was a preloadSWF loaded first)
-Do no start loading your main code base (engine, library, etc) before checking for preloader first.
-There are way to identify preloadSWF file path by using SamplerAPI

References

Josh
AS3 hidden treasure in the mm.cfg file. Revealing and documenting many Flash secrets!
FlashPreloadProfiler
One SWF to rule them all : The Almighty PreloadSWF
FlashDevelop 3.3.0 RTM supporting preloadSWF
AS3 – Hacking PreloadSwf for fun and profit

16 Comments
  1. Great article! PreloadSWF is very powerful and these are some excellent ways to defend against it.

  2. Interesting stuff about FP internals.
    But how similar this kind of code retrieval is to decompilation? I mean you can get swf code anyways, in worst case just obfuscated. Or in worse case encrypted but then you just attack part that decrypts it first.

    At least I always though so and humbled to fact that best thing you can do is obfuscate your code and probably add some extra trick like encryption at the beginning making it a two layer loading which will stop just the lazy ones.

  3. How does this sort of anti-decompilation stand up when you’re making a game for a flash game site? As far as I know, some of those sites make use of a preloader to load in your game. Doing something like

    if( root.name != “root1” ) while( true ) {}

    will break it for them as well, no?

  4. focus permalink

    All that tricks with embedding the swf into the loader swf can be easily avoided without reversing the encryption algorithm, just with dumping already loaded and decrypted swf from the memory (FP couldn’t play encrypted swf).

    • This is exactly what I’m saying in the article 😉

      • focus permalink

        Yes, but to be clear, I mean “bad guy” could dump the SWF from the original source, e.g. from the browser, without using any other SWFs. All he need is ability to look at the whole memory (OllyDbg, WinHEX, etc.) and search it for a SWF header. After the SWF header found, he could look at the size (some first bytes of the header, I forgot which ones) of the swf and dump whole swf from the memory in it’s original state and hack, patch it’s bytecode and do other bad things…

      • Nice post, JP.

        Focus, you can’t dump the SWF bytes if they haven’t loaded up yet. So you have your launcher check to make sure its root.name is “root1” before loading.

        Then the attacker has to actually recompile your launcher to get rid of that behavior. If it’s obfuscated enough that copy-paste from a decompiler isn’t easy, that can add a few hours. This behavior also detects and can crash a few decompilers as well (sothink, swfscan)…

        As JP points out, the preload always wins in the end. I believe there’s value in stopping the easy scanning of code.

      • focus permalink

        Josh Strike, I agree about checking the root.name, but it seems that you don’t understood the point of my comment.
        SWF _will_ load normally because you’re don’t use any loaders, you just run it in it’s native environment (e.g. at the browser, from the original site) so the root.name will be ‘root1’ as it should be.
        So, you could easily dump it after it loads.

      • Ah. Sorry, Focus, I misread your post. I didn’t realize you were talking about outputting the RAM contents.

  5. Still, securing SWF is almost impossible. Two possible attacks I’ve been thinking of :

    – external attack using process memory viewer : you can look for FWS or CWS in process memory and find the unencrypted SWF data. Entirely undetectable.

    – rootkit preloader : will actually modify the SWF before loading it, for instance by replacing calls to “new flash.display.Loader” by “new MyHackerLoader” that will override loadBytes and dump the actual loaded data somewhere.

    • Hey Nicolas!

      Well, both are possible.
      Getting the decrypted bytes is kinda easy.
      The only thing that could matter is protecting against modification.

      • focus permalink

        I think that the protecting against modification is not really reachable too, unfortunately(

  6. I think solution exists, we just haven’t found it yet. For example games on http://www.king.com somehow manage to bypass PreloadSWF and start normally. Maybe it has something to do with ActiveX Control. From their “How It Works” page: The first time you play you will be asked to install an Active-X control called “The King.com Secure Game Control”. This is necessary to play our games and is to ensure security.
    Any thoughts on how ActiveX can be used?
    And one more thing: can we subscribe to “allComplete” in the proteted SWF and call stopPropagation() once it’s fired?
    Thanks for the great article!

    • Overriding PreloadSWF didn’T work when I tried it, If you change how the ActiveX works, I gguess you can do anything, even not using flash! 🙂 There are way to BLOCK the application from running, it’S it’s not that clean too.

      Did you tried running FlashPOreloadProfiler on these games?

  7. Yes, I tried running FlashPreloaderProfiler on these games and the profiler doesn’t start. Profiler is set up properly and connects to any other SWFs.
    It seems that these games don’t flow through PreloadSWF. I wonder how they did this…

Trackbacks & Pingbacks

  1. Swf.hu 2.0 – flash és webfejlesztés » Heti linkajánló – 2010/40

Comments are closed.