Link to home
Start Free TrialLog in
Avatar of MattKenefick
MattKenefickFlag for United States of America

asked on

This is my anti-decompilation method. Can you help test?

I've been developing this for a while, trying to get as much information and workarounds as possible and I think I've come up with something rather successful. It's a way for people to be unable to take your SWF files and decompile them. It doesn't actually make them un-decompilable.. but rather makes it "impossible" to get them.. Therefore you can't decompile them. At least I'm hoping.

Right now it only seems to work for non-IE browsers. Firefox, Netscape, Opera, Safari etc for Mac/PC are all game. I've been spreading this around as many forums and to as many people as I can looking for someone that can do it but haven't found anyone yet but there has been attempts.

This forum is where all the experts are so I wanted to see if someone here could do it.

Test: http://www.seesaw-server.net/decompile/

The server is secure but the certificate is a temporary cob job.. It'll ask to accept but its safe.
If you find code with LoadVars.. you're in the wrong file.

Good luck. Person that can do it and explain how they did this gets points. Will split points for multiple winners. ( This is not really a contest. It is to help me get this working )
Avatar of Steve Bink
Steve Bink
Flag of United States of America image

Is this what you mean?

I was able to download the SWF, but since I have no experience in decompiling flash apps, I don't really know what to do with it.  :)

The basic idea is that the SWF must necessarily be sent to the client because otherwise they would not see it.  Even with a normal browser client, an add-on can provide functionality for saving SWF files to local storage.
[user@mybox:/home/user/temp]
$> ls
total 8.0K
drwxr-xr-x  2 user user 4.0K Jan 25 08:55 ./
drwx------  6 user user 4.0K Jan 25 08:54 ../
 
[user@mybox:/home/user/temp]
$> wget http://www.seesaw-server.net/decompile/flash/initial.swf
--08:55:24--  http://www.seesaw-server.net/decompile/flash/initial.swf
           => `initial.swf'
Resolving www.seesaw-server.net... 74.208.46.102
Connecting to www.seesaw-server.net|74.208.46.102|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 319 [application/x-shockwave-flash]
 
100%[==========================================================================================================>] 319           --.--K/s
 
08:55:24 (33.80 MB/s) - `initial.swf' saved [319/319]
 
 
[user@mybox:/home/user/temp]
$> ls
total 12K
drwxr-xr-x  2 user user 4.0K Jan 25 08:55 ./
drwx------  6 user user 4.0K Jan 25 08:54 ../
-rw-rw-r--  1 user user 319 Jan 24 12:21 initial.swf

Open in new window

Avatar of MattKenefick

ASKER

well that file is the wrong one. You don't want to save initial.swf.

Thats the point of this. :)

If you open that file, does it just say "Loading..." ?
The point of this test is to see if you can get your hands on the SWF file that says "flyyyyyyyy". Good try so far though. You're on the right track it seems!
I've been looking through swfobject.js, and found where it loads the original SWF.  When the object is initialized, it uses 'flash/initial.swf' as the source, and embeds the player into the div element id="jonathan".  So far so good.

From here, there is no reference to another filename in the HTML or scripts.  There was, however, an oddity in the header exchange (see the attached code snippet).  After the page is loaded, my client sends out two more requests: one POST for /decompile/swf.php, followed by a GET for the same URL.

So, off to wget again, and I download a whole 17 bytes of plain text: "Dont hotlink this".  I found this a bit curious since the 200/OK response on that request included this line:

Content-Type: application/x-shockwave-flash

My theory of your method is that your initial.swf calls swf.php as a resource, using the POST method as a trigger or flag.  initial.swf uses the response as the source of another SWFObject, which is initialized from within initial.swf.  Once the write() function of that new object is called, the div element's innerHTML property is overwritten with the new embedding, thus replacing initial.swf with the requested flash.

Am I getting warm?  
POST /decompile/swf.php HTTP/1.1
Host: www.seesaw-server.net
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=on3gugpsab0ok4otuphi6usj23
Content-type: application/x-www-form-urlencoded
Content-length: 83
 
myurl=https%3A%2F%2Fwww%2Eseesaw%2Dserver%2Enet%2Fdecompile%2Fflash%2Finitial%2Eswf
 
GET /decompile/swf.php HTTP/1.1
Host: www.seesaw-server.net
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Cookie: PHPSESSID=on3gugpsab0ok4otuphi6usj23
If-Modified-Since: Fri, 25 Jan 2008 16:16:55 GMT

Open in new window

Almost but not quite. Nothing is ever replaced on the DOM. The initial.swf loads the new SWF into itself.
So far, I can identify only two avenues for exposure.

First is initial.swf.  Not being familiar with decompiling flash, I have no idea how much information can be gleaned from it.  If the javascript interaction can be exposed by decompiling it, then your target filename is compromised.  Everything has to be loaded from somewhere, and that call is necessarily public since it is (ostensibly) the public that is calling it.

Second is the POST to swf.php.  This can certainly be engineered by anyone familiar with HTTP headers.  Does your application account for the possibility of forged requests?
The call from inside the initial.swf is public, you already have it. You can forge a POST request to swf.php if you like, but it shouldn't do you any good.

You can try though :)
Thats what this is all about.
ASKER CERTIFIED SOLUTION
Avatar of Steve Bink
Steve Bink
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
damn..
Sounds right.. I'll work on patching that up.

When you're sending those direct headers to the server, any active javascript on the page won't run right?
Actually, I engineered them from within Firefox, using the URLParams add-on.

http://urlparams.blogwart.com/share/index.php

It was easier than researching how to duplicate them using PHP's CURL, but I imagine I could do it there as well.  Through Firefox, I obviously have the ability to parse/run javascript.  Even without it, someone with enough knowledge will be able to interpret the script for simulation purposes.

I'm very interested in your future progress along these lines.  I've previously looked into 'privatizing' otherwise public resources before.  The main obstacle I always ran into was client communication.  Anything that actually goes client-side will be traceable by the user, and can usually be reproduced as a manual simulation.
Not necessarily. There are things you can't fake which in this case involved session and such. But encrypting certain data like Dates and Times that the user doesn't necessarily know could provide as a key. It's publically know that it's used, but to manually override, you'd have to know WHAT is in it.

I'll continue working on this and see what I can do. It's not bad so far though. It blocks media tab, swf catchers, direct downloading, hotlinking, etc..

And really.. you have to be a little clever to figure this one out. But as good as it is so far, it is worthless once one person gets it.
Yup.  Kudos for the effort so far, and you're right that it will block most casual attempts.  It took me about two and a half hours to crack it, but it would take me less than that now to engineer an automated system to exploit it.

My point about client-side communication is that any information you are sending from the client to the server is already compromised, meaning the client machine MUST know the information.  Encryption and what not adds a certain level of obfuscation to this type of strategy, but not much else.  For example, imagine you used a hash or encryption of the session ID and date.  To send the encrypted data, the encryption must take place on the client machine, which leaves the process open for inspection.  Encrypting the data server-side leaves the strategy exposed, which means a user can engineer an attempt much like I've done here.  I don't believe it is possible to create a foolproof strategy for this because the client side must always participate in some integral way.

I haven't looked yet, but have you examined the potential for the flash to remain in the client cache or temporary files?  This isn't a problem with streaming media, but any finite resource (such as flash apps) have to reside somewhere...
As far as I can tell, the flash is completely cleared from the cache once you get it. Which is why I believe it doesnt' work in Internet Explorer. But i've poked through and used Media Cache searchers to pick it up and it's been unable to.

Thats the results of my cache preventing methods and the fact it embeds it dynamically with script.
And also the fact that it isn't the directly embeded clip.. Which is why initial.swf loads it. The cache goes to flash.. The browsers just cache initial.swf which is worthless.
is there a way to determine whether ornot someone is looking through a browser?
Not by any method known to be dependable.  The server knows about the user agent because of the header in the request, which can be (and often is) forged or otherwise edited.  Before I reinstalled URLParams, I looked at another add-on that does just that.  It would have allowed me to edit the user agent string generated by Firefox.
Yeah.. It's tough. There's gotta be something .. Some kind of trick that'll help here. I really thought SESSIONS was the ticket
It's tough because at SOME point you have to expose it to the user.  Anything exposed to the user must instantly be considered compromised.  I feel your pain...  :/

I was considering some type of captcha-esque system.  When the user clicks on the link to the video, it goes first to a page which generates a random key, drops it into a session variable, and associates the key with the video.  As the flash app GETs (drop the POST step), the back-end page can draw from that key.  Once the video is sent, the key association is cleared.

The downside: the GET is visible to the user, and there is span of time, however limited, that the video can be retrieved manually.  Using an add-on such as TamperData could provide enough of a delay to allow for an exploit.