Skip to content

Flash Player Security Advanced Walkthrough

December 11, 2009

Using the techniques I’m going to explain, it’s possible to do about anything in any flash application.

If you have ideas or solutions for some of the techniques, please make a comment!

Stating the obvious:

  • SWF are easy to decompile to get the ActionScript code.

Application like “Sothink SWF decompiler” can do that in no time. Next…

  • Browser can cache downloaded SWF to run faster on future access

IE cache its file under “C:\Documents and Settings\USER\Local Settings\Temporary Internet    Files\Content.IE5  (Windows hide this folder even when you turn everything to be visible. just type it in the address bar).  Next…

  • There is no way of knowing if a SWF as been tampered.

No signature… No checksum… Next!

  • Client application can never be trusted

Well, that’s just a fact. Next?

  • File can’t be encrypted (or almost)

Flash Player must be able to read your files and since it has no idea of what encryption you use, you must “load” a encrypted file, and the algorithm of your encrypted file is in the loader. But what do you do with the loader itself then?

Things you should be aware of:

  • There is a feature in flash call “ApplicationDomain”.

The ApplicationDomain class is a container for discrete groups of class definitions. Application domains are used to partition classes that are in the same security domain. They allow multiple definitions of the same class to exist and allow children to reuse parent definitions.

  • Often, the only thing triggering a reload of a SWF from the browser cache is its size. (If the size is not exactly the same, download it again)
  • Flash Player has no way of knowing if a SWF is authentic or not.
  • Browsers have no way of knowing if a SWF is authentic or not.
  • Flash Player doesn’t care if a SWF is filled with null character at the end of the file.

The SWF contains its size and will be loaded accordingly to that size, but what follows it don’t matter.

Let’s proceed to a series of iterative “how to” attack and “how to” respond from both attacker and developper side

Case 1

Difficulty: do we need to do this case?

Let’s take some software like CheatEngine, find some interesting number you want change (see your score?) search for your number and change it. It worked. Good job buddy!

The app as been hacked but it won’t happen again!

I added some kind of encryption (AES / XOR) on the value in memory

Case 2:

Difficulty: Dev knew basic stuff about memory cheat

So it didn’t work…  (You were unable to find anything interesting)

Download packet injection software (ex: Packet Forge or any other). Trap some packet with the data you would like to change…change it… then send it back to the server. Or do not change it and send the same a lot of times to increase action frequency.

The app as been hacked but it won’t happen again!

I added some kind of encryption (AES / XOR) on the packets with incremental packet number incremental ID to detect injection.

Case 3:

Difficulty: Dev knew basic stuff about network packet injection

So it didn’t work…  (You have no idea of what is transferred in all theses packets, and duplicating them seems have no effect)

Description: The app is made of two SWF (a preloader and the main application)

Go in your browser cache, find “Main.swf” and copy it somewhere.

Run it in Sothink… decompile… Rebuild the FLA file, modify it as you which (change the score to be x10 or completely remove protection from case 1 and 2), ensure that it’s the exact same size with the original file (by adding NUL padding at the end of the file and removing some assets if needed to make it smaller), put it back in the cache, reload the file.

You’ve got it!

The app as been hacked but it won’t happen again!

I encrypted the Main file with *something* so that it could not be decompiled

Case 4:

Difficulty: So the Dev knew about decompilers too?

So it didn’t work…  (Main file is not a SWF and could not be decompiled.

But Flash Player was able to run the app… Of course it was! The loader is downloading the main file, decrypt the file, then load it from memory using “Loader.loadBytes()”. So the algorithm is in the loader? Yes! Decompile… Change the code to output the “decrypted file” ByteArray in a file that you save on your desktop using the “flash.net.FileReference” code.

You now have the Main.swf ready to be decompiled in Sothink. (See Case 2)

You’ve got it!

The app as been hacked but it won’t happen again!

I did Code Obfuscation on the whole project. They won’t understand what’s going on!

Case 5:

Difficulty: Dev knew about decompilers and used some logic

So it didn’t work…  (It was not possible to rebuild anything because the obfuscator has done Control Flow obfuscation / Dynamic Code wrapping / Statement-Level Randomization etc. Nothing could be rebuilt from the sources.)

So what do we have? We still have the obfuscated code. It’s a bit harder to find classes like “MemoryEncryption” or “PacketEncryption” classes but feasible because almost no one’s use full obfuscation on code (It would slow down the app, and when working with big project, it’s hard to obfuscate everything in on pass without breaking the app).

So you’ve find them? (The class name is now J39Ft1). But you can’t rebuild the whole thing… It just won’t build and it would take too much time to correct / adapt / rename things.

Now some magic.

Using ApplicationDomain, you can define a class in a parent SWF, and the child’s SWF will use that instead of using its own definition.

Create a new AS3 project, name it after exactly like the loader SWF, and define the class “J39Ft1” with whatever you want in it (if it’s the MemoryManager my guess is that you will do empty getter / setter) .

Now place the original loader on another server (a free web host), put a cross domain allow * on that server, and load the original loader from your newly created one.  Add original loader to the stage (as if it was loaded directly and pass the flash param to it). Again set your SWF size to the original loader size, and replace it in browser cache.

Your SWF is going to load first. Then, the original loader, and it will do what it’s supposed to do: load the Main SWF. But the Main SWF will use the definition you forged instead of its own.

Case 1 and 2 open again! Plus any other change you want to do by overriding classes.

The class links to other classes and you don’t want to override everything that links together? Refactor the class! Everything as “Object”, new class instances use “getDataDefinition(classname)” and there you go! Object dynamic calls will take care of the rest.

You’ve got it!

The app as been hacked but it won’t  happen again!

I removed the obfuscation on the Main SWF and encrypted it instead. The obfuscation was slowing the app and they were able to see some code. But I increased the obfuscation level to the maximum for the loader. I also loaded the Main SWF in a new ApplicationDomain so that it could not be overridden that easily. I also added “hasDefinition” of all critical classes in the loader to prevent class overriding.

Case 6:

Difficulty: you have some time ahead of you

So it didn’t work…  (The only thing you see is a fully obfuscated loader)

Well at this point your best guess is to try to reverse-engineer the loader’s code and re-create it from scratch. Change the loading settings so that’s it load’s the Main SWF in the currentDomain. Run the decrypt algorithm on the main file and then use the overriding class trick again. (Case 5)

If you are motivated enough (you want money and don’t care about scores) theirs is no doubt that you will find the time to do that.

The app as been hacked AND IT WILL happen again!

Okay I give up.  I’m just going to make sure all transactions are well managed server side.

Solutions (or things you should try):

There is no solution for client side hacking.

Make it harder:

  • encryption (AES / XOR / …) on the value in memory
  • encryption (AES / XOR / …) on the packets
  • Encrypted Files in conjunction with super high code obfuscation of preloader
  • Using New ApplicationDomain and checking for existing definition
  • Always force a fresh download of preloaders

Track down attacker:

What you can do is user behavior/pattern identification. Find the people trying to hack you as soon as you can.

  • The Main SWF is not supposed to be run? Use a constructor with a default param that the Loader use when instantiating it. And if the param is not there, the app as been run as stand alone. You can call a server specifying that there is someone (IP + all info possible) trying to hack your SWF.
  • You can flag people whenever they send multiple times the same packet, or send data that is not well formed.
  • When a user is identified as a hacker, you should not give them any immediate feedback. You should always wait a bit and insert feedback in other pipeline because giving the attackers feedback that he has been identified helps him find your protection mechanism

Validate data:

  • Validate all transaction server-side.
  • Validate scores with replay-data.
  • Save value snapshots at random time interval.
  • Use statistics (point cloud, graphs, threshold, etc.) and compare with « the others »

Can take more?

That’s about it for security.

add to del.icio.usAdd to Blinkslistadd to furlDigg itadd to ma.gnoliaStumble It!add to simpyseed the vineTailRankpost to facebook

From → general, security

12 Comments
  1. That was a really great article! It concretely hammers home that the client absolutely cannot be trusted. I’ve heard almost all of the excuses you pointed out in the progression. Maybe now I’ll start pointing people to this article. Thanks!

  2. Very interesting article ! Thank you for sharing those infos.

  3. Just landed on this post via Google search. I love it. This situation change my percept and I am acquiring the RSS feeds. Cheers Up.

  4. John Orange permalink

    Mmm nice article! We’ve tried to do it also by hand in the beginning, but it was almost impossible to maintain.

    We currently use secureSWF Professional for all our online Flash projects. It is the only one that really works and is easy to use. We’ve tried all the other software (SWF Protector & SWF Encrypt) before and it didn’t do the job, these were easily defeated by decompilers. We weren’t able to decompile files processed by secureSWF 🙂

  5. Thanks, excellent article!
    Could you write more details about soft using for obfuscation?

  6. Bob permalink

    Just wondering, what do you think about the protection described in the following article? Is it good enough? How can we “crack” swf protected using the method described there?

    http://active.tutsplus.com/tutorials/workflow/protect-your-flash-files-from-decompilers-by-using-encryption/

    Thanks

    • I already answered that tutorial in their comments. It is a very interesting technique. But it changes nothing! You can either override class definition by inserting a fake launcher first. Or you can use the “PreloadSWF” feature of mm.cfg to get the actual “decrypted” SWF that is being loaded with the “all Complete” event.

      It is still a good tutorial to understand how things work.

  7. Hotfusion permalink

    The current implementation of the Flash Player ApplicationDomain with regards to override class definition seems like a giant security flaw to me.

    A parent SWF has complete control over what child SWF they want to load and add to its ApplicationDomain. It stands to reason that if the parent trust the child SWF enough to load the file, it should also trust the class definition defined by the child SWF and use those definitions.

    In contrast, a child SWF has no control over where it is being loaded into, or if it want to be loaded into another SWF at all. Therefore, there is no reason for the child SWF to trust the class definitions defined by the parent SWF.

    I recommend changing the current implementation of the ApplicationDomain and allowing a child SWF to override any conflicting class definition in the parent’s ApplicationDomain.

  8. Wolfgang permalink

    long time ago (so it was AS1/AS2) I built a setup where some kind of encryption (swapping a few bytes, xor-ing them with constants, like that) was dynamically added to a non-cachable movie as code – so every single swf loaded from the server was different

Trackbacks & Pingbacks

  1. AS3 hidden treasure in the mm.cfg file. Revealing and documenting many Flash secrets! « jpauclair
  2. One SWF to rule them all : The Almighty PreloadSWF « jpauclair
  3. 防止Flash游戏被破解的N种做法 | Wesleysong the Game Developer

Comments are closed.