`

Packed SWF. How to unpack?

阅读更多

from:http://blog.codestage.ru/2012/03/07/packed/

Packed SWF. How to unpack?

Hey, friends!
In this post I’d like to explain you what is a packed SWF, how it looks and show you some methods of dynamic and static unpacking.

So, what is packed SWF?

If you never saw it, please, feel free to download this classic example of packed SWF:
http://codestage.ru/files/flood/security/packed.swf
You can see single SWF showing a text. But you can’t reach a code showing it with a classic approach – through the decompilers.
I should mention you’ll not reach any resources (Bitmaps, Sounds, Fonts, etc) via decompilers if they will be there too, because target SWF is placed inside of SWF you have and usually it is encrypted.
Usually all you can get with decompilers from a such SWF is a decryptor/unpacker code (usually hardly obfuscated), and, probably, target encrypted SWF (if your decompiler is able to show you the DefineBinaryData tag)
This kind of packing could be achieved with simple Flex [Embed] tag.

Dynamic unpacking (dumping)

Dynamic means unpacking while target SWF is run in Flash Player (FP).
As FP can’t play packed SWF as is, it should be unpacked and decrypted into the memory before loading (as example, with Loader.loadBytes()).
More important, it will be in the memory all the time while it’s running to allow FP properly display end execute it.

That’s our chance to get it!
There are two common ways to do it.

1) Dynamic unpacking with tools
Using third-party or even own tools to automatically search SWF in FP process memory. It’s the fastest and easiest method. Doesn’t provide you a feeling you’re a true cracker ;)
There are several tools for it available both free and paid.
One of most advanced is a SWF Revealer, free tool for the ASV licence owners. It could bypass domain checks (which will prevent SWF to unpack and decrypt) in some cases and force SWF to load and decrypt target SWF.
Also you could found some free tools for dumping after googling for it a bit.

2) Dynamic unpacking with hands
Search for it “by hands”, looking for the CWS (compressed SWF) or FWS (uncompressed SWF) header signature which are the start of any SWF file. If you never tried it, you definitely should try! It could be useful to improve your skills with hex a bit and to provide you a feeling yourself a true cracker)
For search you could use any Hex editor supporting RAM editing\viewing.
If you’ll try to search for packed SWF in the sample file I linked before, you should start from searching the FWS signature (uncompressed SWF) – just search for the ‘FWS’ string in the Flash Player’s (or Flash Player plugin\browser with SWF running in it) process because FP decompresses SWF before executing if it was compressed.
If you’ll search in a browser, be careful and close all other tabs with SWFs to decrease amount of the false positives.

Usually, you’ll find not only one signature entry, because FP contains other internal SWFs as well, like SWF showing hint how to exit from the fullscreen mode.
So if you’re not sure, I recommend you to check all found entries.
Well, what to do with found signature you’ll ask? How to validate it, how to know, where is the end of the SWF?
Please, look at this screenshot:

This is a signature for the one of the SWFs found in the FP memory (accidentally it’s a signature of the target packed SWF =) ) by looking for FWS string.
So, what next? Next you should check the length of the found SWF. Length is placed at the 4 bytes starting from 4 byte:

How did I knew that? It’s simple, I just read the “SWF File Format Specification” http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf (“The SWF header” section)
Since it’s a hexadecimal number written in memory, you should know its bytes are written from right to left. So resulting number is:
00 00 04 DB in hexadecimal and 1243 in decimal.
Let’s measure this 1243 bytes starting from the FWS signature.
Because signature starts at 053DD020, SWF file end should be at 053DD4FB (053DD020 + 4DB):

Please, note that address where FWS is placed in memory is not the same on different OS and hardware.

Now we see our SWF in memory really ends at 053DD4FB and we can select all bytes from 053DD020 up to 053DD4FB and copy-paste them into the new SWF file.
After making this with all suitable FWS entries you’ll, you’ll have target unpacked SWF file in one of the saved SWFs!
Now you should be able to decompile it as usual and look into its sources or resources.

Some protections are trying to resist SWF dumping by generating many fake FWS headers, trashing a memory with them a bit. So you should double check if header has valid length and how it looks at all. Experienced in reversing people (like me :p) could say if header fake or not just looking on it and on several tens of bytes after the header.

Sometimes, packed SWF will not be decrypted and loaded into the memory because of different cases. As example, packer’s loader could check current domain or some kind of the license file before unpacking SWF. In this case you’ll need to patch that checks (as example, with bytecode disassemblers like Yogda or RABCDasm) or provide needed files (probably with crypto keys for decrypting) to make SWF run and unpack in memory.

Static unpacking

Static means we don’t need the SWF to be executed in FP to unpack.
Well, this kind of unpacking usually comes to help when you have no chance with unpacking your SWF dynamically (who knows why you can’t run SWF?)
Static unpacking could be very difficult because of many possible safety precautions of the packer developer. There are many ways of making static unpacking painful and very long.

So, how to start with static unpacking? First of all, you should have access to the two things inside the SWF to make this unpacking possible:
1 – DefineBinaryData tag(s).
2 – Decompiled AS or abc bytecode of packer loader.
And optionally, to the
3 – SymbolClass tag
Use available tools to achieve it (ASV, Adobe SWF Investigator, SWiX, etc).

How to find DefineBinaryData tag in the SWF?
Well, some tools, like ASV will point you to that tag with ease and allow you to save it as binary file.
Also it could be found by hands, with different tag-reading tools, like mentioned before Adobe SWF Investigator.
To get data from DefineBinaryData tag with Adobe SWF Investigator from the sample file I linked above, just open the file, go to the Tag Viewer tab, select DefineBinaryData tag and press Dump To File button.

Sometimes there could be numerous fake DefineBinaryData tags inside, just to make your life harder. To find the desired tag, you should look inside the packer’s loader code and track down where is the embedded SWF is created to be decrypted and loaded.
Usually it looks like this:

var someVar:ByteArray = new SomeClass();

Where SomeClass is type of Class extending the ByteArrayAsset class.

Let’s look at the sample SWF loader code and look for something like this.
Gotcha! here it is:

private var content:Class;
//...
var _local3:ByteArray = new this.content();

So, we should look for the class with name ending on “_content” and extending the ByteArrayAsset class.
We have one match here:

public class MainTimeline_focus_loader_content extends ByteArrayAsset

To get which DefineBinaryData tag is linked with this class, we should look into the SymbolClass tag and search there for a record with found class name “MainTimeline_focus_loader_content”.
And we got it (in Adobe SWF Investigator):

<Symbol idref='1' className='MainTimeline_focus_loader_content' />

Remember idref value. This is a desired DefineBinaryData tag id!
Now go and search the DefineBinaryData tag with id = 1 – that tag will be needed one, so we can just dump it in a file and continue unpacking.
Why I asked you to remember the idref value instead of class name? That’s because in case loader AS will be obfuscated, it could be really hard to work with class name.

Now your success depends on your free time, packer’s loader difficulty and your luck)
If you’ll be a lucky one, that data dumped from the DefineBinaryData tag will be the pure, not encrypted SWF, and unpacking will be finished.
But in most cases data is encrypted and you should reverse engineer the packer’s loader code and make own decryptor.

In our case the loader’s code is extremely easy and not obfuscated, so we can easily found the decryption function:

private function decryptFile(_arg1:ByteArray):void
{
    _arg1.position = 0;
    var _local2:int = -1;
    var _local3:uint = _arg1.length;
    var _local4:uint = uint("55");
    while (_local2++ < _local3)
    {
        _arg1[_local2] = (_arg1[_local2] ^ _local4);
    };
}

All we need to decrypt file from the DefineBinaryData tag is just xor each byte of it by 55.
That’s all. Now you could write decryptor, decrypt SWF and decompile it to see the desired source code. And pray this decrypted swf will be your target swf, not the another one with packed swf inside haha! Sometimes packers uses the Russian Matreshka doll approach to hide target swf and other techniques to make static unpacking harder. Anyway, dynamic unpacking will beat all of them.
Remember – in Flash world, nothing only variables names can be hided from the true professional with high motivation level.

Any questions, ideas, comments? Feel free to leave it below!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics