PDA

View Full Version : Creating UNEDITABLE packages with *.as files


DragonflyLuis
06-15-2010, 09:26 PM
Hello as3 friends! I don't know if the title is pretty clear so i'm going to explain.

I have a flash file that uses many classes i have done. Now, another person wants to modify that flash file, but for that i need to give him my classes too; if not, he will be unable to recompile the flash file.

The problem of this is that i want to protect my *.as files where my classes are written (yeah sounds pretty anti - open source, but i need to protect my work ;)). So, how can i make that? Is there a way to convert all those clases into a kind of uneditable package that can be read by the flash file for importing process but the user is unable to edit or view?

Thank you very much!

tadster
06-15-2010, 09:29 PM
The best way is to include a license with your work. So the other developer will be tied to the license and thereby not able to edit your code. In principle, and on his 'honor'.

But you can hide your code. Just do a search for where I have talked about this before.
It involves swc files and the ByteArrayAsset Class.

henke37
06-16-2010, 09:55 AM
I don't think there is any need for any ByteArrays. But yeah, a swc file would be an option. It's not particularly secure, but it keeps people that are unable to operate a zip archive extractor and a decompiler from messing with the code.

tadster
06-16-2010, 04:17 PM
no, no... ByteArrays? yeah stay away from them, there is no way to secure your code, that's just fantasy talk. It's ByteArrayAsset.

henke37
06-16-2010, 06:10 PM
ByteArrayAsset extends ByteArray. And it doesn't provide anything valuable what so ever.

tadster
06-16-2010, 08:26 PM
your absolutely right!!

DragonflyLuis
06-17-2010, 06:37 PM
But you can hide your code. Just do a search for where I have talked about this before.
It involves swc files and the ByteArrayAsset Class.

I read a post where you said about this technique but from what i have read about the embed instruction, you can get the classes exported from the library. Like i do a circle, then convert it to button and asing a class name like "CircleButton", then i do the embed technique and i can get that CircleButton class with symbol="CircleButton" (This is as2 reference, i need as3). But the problem is that my classes are not in the library, they are imported from a *.as file; so is there a way to get those clases too?
Maybe something like this:

[embed (source="myClases_In_AS_File.swf" Symbol="MyClassInASFile1")]
private var AssetClass:Class;

AssetClass = new MyClassInASFile1();

tadster
06-18-2010, 05:53 AM
ok, here we go, this is the last and first time i will show this fully.

Step 1.
Make your application. Your Main app.
You should have the basic setup of waiting for the stage to be available.

But other than that, this Main app swf will house all the code you want to 'hide', really you can just make your app as normal and then apply step 2 to it..
I guess if you want, it can house functions and just hold code to be used by the next step in this process, but when I say main app, I mean an app that may itself include things like Classes that just house functions, yada yada, let's continue...


Step 2:
Embed the Main app as an octet stream inside another swf.
if you don't do it as an octet stream it may not work.
This is the magic part.
The ByteArrayAsset part.


First thing to notice is that our Main app, is already compiled, we embed it as a swf.
That's part of what guards it, it's compiled already, and we are about to
embed it inside another swf.
Then, in order to reference the code inside of the Main App we need to bring it into the same Application Domain. That is another key. (and I believe that is the part you were asking about DragonflyLuis)
Next I'll show you the AssimilateSWF function, I store that in its own .as file, but its just a public function.

//AssimilateSWF.as
package
{


import flash.system.*;
import flash.utils.*;
import flash.display.*;
import flash.events.*;


public function AssimilateSWF(btL:Loader, thisBinaryData:ByteArray, giver:Function = null):void
{


if (btL.numChildren > 0) btL.unload();

var bArray:ByteArray = thisBinaryData;

if (giver != null) btL.contentLoaderInfo.addEventListener(Event.COMPL ETE, giver);

var btC:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
btL.loadBytes(bArray, btC);


}


ok, so that's step two, and really it could be the last step,
so let's stop here and see how this could be it right now.
The function called by AssimilateSWF (giver) will contain the contents of the Main App in e.target.content, ready to go. So when we add those contents to the stage..... you guessed it, the initialize function in our main app will fire.
Not only that, if we wanted we could cast e.target.content to whatever it is and then access properties and methods of it.

The Embed tag itself is not even seen by decompilers like Sothink and Trilix. No Meta Data tags get seen by any commercial decompiler. Although there are other tools besides decompilers.
When the Main app is decompiled, people won't even see this line:

[Embed(source="basicallySafe.swf", mimeType="application/octet-stream")]
private var basicEmbedded:Class;


All they will see instead is a private var named basicEmbedded, and basicEmbedded will just extend ByteArrayAsset, and your right henke37, it doesn't provide anything valuable what so ever. Just an empty Class extending ByteArrayAsset... and there you have it, basically hidden code.

Step 3:
As an added layer, you can compile your main app into a SWC file. And then have another class include the library and extend the Main class.

And now please be sure to read all the comments.

bowljoman
06-18-2010, 07:04 AM
Dont we just search you swf file for a binary data tag?

Then extract it and run it through a decompiler.

Still havn't seen any way to hide anything.

See page 253 of SWF file spec.



DefineBinaryData
Field Type Comment
Header RECORDHEADER Tag type = 87
Tag UI16 16-bit character ID
Reserved U32 Reserved space; must be 0
Data BINARY A blob of binary data, up to the
end of the tag

tadster
06-18-2010, 08:38 AM
true, the whole 'code' can be seen, quite simple:

/lib/ -abc myswf.swf -myswf.abc

But not re compiled, differently.
You can't store passwords (easily), but you can lock your file to a url,
and make such functionality reasonably unchangeable.

And it seems in this example, the go function would not even be seen in human- readbale abc code.
I was just on kirupa as well with this topic.

Can you tell me how to extract something from a swf (pm if you like) those are things beyond me.
This method I describe does work against standard decompile tools like Sothink and Trilix. With those what you get is just an empty Class extending ByteArrayAsset, surely one would need to be a little more than average as a developer to be able to see into it more, even nemo does not show the full code.
Yes on page 263 it starts talking about DefineBynaryData, but how do you get that out of the swf?
Even with the abc code one does not know the name of the embedded .swf.
And we're not using the SymbolClass tag, but octet-stream.

tadster
06-18-2010, 10:25 AM
ok... thank you Bowljoman for pointing me in that direction, yep, you can extract the binary data right out. (of all the random tools i installed on my pc, i should have used swftools first)
But even with that we still have some options. Keep embedding, one on top of the other, compile main app, embed main app, embed that, embed that...
The tools will only show the top Binary, so a hacker would have to keep on extracting until... If you needed something to be more than a little safe, you could even go the route of making a batch compiler script to compile 5,000 or more of such levels of embeddment. (they add little to no kbs, your just layering simple 20 line Classes)

Add to that, there can be multiple 'top level' embeds (so swfextract would show more than one) then they would have to guess which one holds the real bacon. Just those two methods together are decent.

But at the base level, some customer/client who's grabbed the Sothink demo trying to make your work his/her own (without paying) won't be able to do a thing.

bowljoman
06-18-2010, 02:49 PM
the extracted SWF file is parsed for binary data as well.

There is no where to hide.

Get you favorite file reader in java or c++ or anything really... Find the tag, and make a new file embed1.swf with the tag data.

An RSL might be better...

bowljoman
06-18-2010, 02:55 PM
And dont forget , the symbols will be in the dictionary, so the embedded 'Class' can be found in definition tags.

And since you embed the asset close to the first frame, the binary embed you use in the application will be one of the first tags in the swf file.

You seem to mistakenly assume that only swf decompilers will be used to hack your game.

Embeded binary data(swf file) inside an embeded swf will be found inside the embeded file under a binary data tag, and so on, and so on... Binary data is copied out and new swf file generated. The embeded data is a full fledged swf file itself.

tadster
06-19-2010, 12:33 AM
There is a small way... If the file you embed is small enough, it does not get seen as something that can be exported individually.... If you embed 30 different text files, each with the exact same low kb, like 1, 2, or 3 bytes ("a", "aa", "aaa") they all get grouped as just one Binary, thing. So the Binary count will be wrong in a tool like swfextract. And you can embed many things on the 'top', thousands...
And those "Classes", (really just up to 3 letters a piece) can be easily missed.

Here's what i've got so far:

package
{


import flash.display.*;
import flash.events.Event;
import flash.utils.*;
import com.tadSrc.tadsClasses.functions.*;


public class Cover extends Sprite
{



[Embed(source="com/tadSrc/smearf/blanks/unSeen (1).txt", mimeType="application/octet-stream")]
public var un1:Class;

[Embed(source="com/tadSrc/smearf/blanks/unSeen (2).txt", mimeType="application/octet-stream")]
public var un2:Class;

[Embed(source="com/tadSrc/smearf/blanks/unSeen (3).txt", mimeType="application/octet-stream")]
public var un3:Class;

//...there's one other swf , just a usless swf.. and the text files continue...

[Embed(source="com/tadSrc/smearf/blanks/unSeen (10).txt", mimeType="application/octet-stream")]
public var un10:Class;

[Embed(source="com/tadSrc/smearf/blanks/unSeen (11).txt", mimeType="application/octet-stream")]
public var un11:Class;

[Embed(source="middle.swf", mimeType="application/octet-stream")]
public var un12:Class;


[Embed(source="com/tadSrc/smearf/blanks/unSeen (13).txt", mimeType="application/octet-stream")]
public var un13:Class;

[Embed(source="com/tadSrc/smearf/blanks/unSeen (14).txt", mimeType="application/octet-stream")]
public var un14:Class;

//... to 33

//... but you could go to about 50,000 and be ok
//a hacker would then have to look through all 50,000
//one by one, and then figure out any algorithms

//I made a flash 10 swf that spits out new text files in sequence


private var ch:ByteArray;

private var load:Loader;

public function Cover() {
load = new Loader();
var geter:* = new un33().toString();
//"aaa32" is the content of unSeen (33).txt

//if all the files followed just a one a# or aa# pattern (3 or less bytes)
//The total Binary count for this file would be 3 (IDs 1-3)
//AS it is now only 2 of the files are 2 bytes long, the rest are 5 bytes
//So in swfextract, the Binary count is wrong, it groups the two 2 byte files together

//and the file extracted for them is blank

//So the count should be 33, but it will show only 32 (IDs 1-32)


ch = new this["un"+(int(geter.replace("aaa", ""))-20)+""]();
addEventListener(Event.ADDED_TO_STAGE, strt, false, 0, true);
}

private function strt(e:Event):void {

//stage.addChild(new child() as Sprite);
removeEventListener(Event.ADDED_TO_STAGE, strt);
AssimilateSWF(load, ch, covered);

}
private function covered(e:Event):void {

stage.addChild(e.target.content); //adding the main app to the stage
}


}



}

That seems like it will work as a basic deter, and you can get clever by using the data from the text in clever ways, perhaps a combination of the letters from the text could be passwords or urls to lock to.

There's one problem though, I can't seem to read a 2-3 byte text file in this way... (still using the above code), most of those are 5 byte files , eg "aaa32", so doing this:

new un33().toString();

returns "aaa32"
But, if the file is only 2 bytes - "32" or 3 - "a32"
the toString method returns just nothing, an empty string ""?
And yet the bytecount is 2 or 3, so its reading it... How can I get the text as a string or number from such a small byteArray/text file?

I think that would be the ticket.

bowljoman
06-19-2010, 04:17 AM
Wow, I think your missing the point.

If you parse the swf file , the first object you put on the display list will point to the dictionary, where a definition will be found, corresponding to the binary data.

Any binary data that is defined and not put on the display list or created can be ignored.

Notice I havnt even started a decompiler yet, I just run my own java or c++ or php based tag parser. After all binaries are extracted, then Ill think about running a decompiler.

bowljoman
06-19-2010, 04:21 AM
On your text issue, you need to read Multi byte chars. UTF16.

tadster
06-19-2010, 05:23 AM
Ok, so all binaries can just be extracted together, like a batch? Then it's just as simple as decompiling the largest one? ! Ok, I think I understand.
But certain binaries may go over looked? Not on the display...ok.
And Multi Byte, thanks!!
Where there is a will, there is a way.. i feel it, i'll find it, one day.

bowljoman
06-19-2010, 05:43 AM
No dude :p

Read the SWF spec carefully.

It tells you exactly where and how to find any binary data that has been defined.

And the swf tags with creation tags and addDisplay tags reference the dictionary , which points to the binary data tag.

You're cooked.

SWF file alone and embed is not the answer.

tadster
06-19-2010, 02:01 PM
Yes, I do understand, all the binary data can be gotten, that's what i said... but small amounts of binary data do get grouped together.
That is what i am finding out now. The outcome of the DefineBinaryData tag, can be manipulated.


And all the binaries can be extracted at once, in a batch... i've written my own little Java app to do that. swfextract can also do that.
But, like i said, the amount of binary data extracted will be wrong if little groups of small binaries (files less than 3 bytes) have been all grouped together as one (which is the behavior)
I don't think your hearing me...
If you have only two files embedded via the Embed tag, two different class names, two different file names, but they are both the same exact size, and that size is less than 3 bytes, the DefineBinaryData tag will only show one Binary available, not two.
They get grouped together as one. Yet in the code, I can read from both individually.
A hacker will not be able to know that they have been grouped.
He will have to decompile it and go off the Classes instead, which will show no data,
since they have been grouped. Also, when extracting such grouped binaries (with the tools i've used so far), no data is shown.

Let's agree that using the Embed tag, does guard against simple decompilers like Sothink and Trillix, but not against the seasoned developer using things like swftools or their own scripts to extract binaries and manipulate swfs. ?

bowljoman
06-19-2010, 03:58 PM
I'll never agree that the swf file contains a safe place to hide anything usable. We haven't even gotten into wire shark yet ;)

Also your forgetting to unzip the compacted byte arrays where you think you are missing bytes.

Generally you should consider as3 about as safe as javascript.

Hiding anything in the SWF file has never been an option. That's what webservices/sessions/cookies/ and DB's are for.

The last shopping cart I made supports Web farm clusters, cached DB, and is very secure.

Never once considered embedding anything.


I think you spent too much time trying to hack your own game with the wrong tools. ;)

bowljoman
06-19-2010, 04:00 PM
For the O.P, the best option is using SWC/RSL

Or refuse to lend out the library without some license agreement.