A Flash Developer Resource Site

Page 1 of 2 12 LastLast
Results 1 to 20 of 38

Thread: Please decompile my site, if you can...

  1. #1
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136

    Please decompile my site, if you can...

    I've taken some immense pains with my more recent sites to keep them from being decompiled. I think I've finally hit on a multi-faceted approach that will really protect my as3 source.

    I don't really care much about the code on my home site being decompiled, but I've applied these techniques to it as a way of testing. Can anyone find their way into the source code of the as3 file at joshstrike.com? I'd like to find out if my methods are effective...

    Thanks,
    Josh

  2. #2
    Junior Member
    Join Date
    May 2009
    Posts
    1
    package Initialize_fla
    {
    import flash.display.*;
    import flash.events.*;
    import flash.external.*;
    import flash.media.*;
    import flash.net.*;
    import flash.system.*;
    import flash.text.*;
    import flash.utils.*;

    dynamic public class MainTimeline extends MovieClip
    {
    public var fontsLoaded:Boolean;
    public var coreBytesLoaded:Number;
    public var soundPolicy:SoundLoaderContext;
    public var fontBytesTotal:Number;
    public var soundstream:URLRequest;
    public var t:Timer;
    public var coreReq:URLRequest;
    public var coreLoaded:Boolean;
    public var fontBytesLoaded:Number;
    public var coreBytesTotal:Number;
    public var coreLoader:Loader;
    public var mr:Number;
    public var fontLoader:Loader;
    public var fontReq:URLRequest;

    public function MainTimeline()
    {
    addFrameScript(0, frame1);
    return;
    }// end function

    public function processFinished() : void
    {
    var _loc_1:Class;
    if (fontsLoaded && coreLoaded)
    {
    removeChild(this.loadBar);
    coreLoader.contentLoaderInfo.removeEventListener(P rogressEvent.PROGRESS, this.coreLoadProg);
    fontLoader.contentLoaderInfo.removeEventListener(P rogressEvent.PROGRESS, this.fontLoadProg);
    addChild(coreLoader.contentLoaderInfo.content);
    _loc_1 = fontLoader.contentLoaderInfo.applicationDomain.get Definition("Fonts") as Class;
    Font.registerFont(_loc_1.univers55);
    Font.registerFont(_loc_1.univers55oblique);
    Font.registerFont(_loc_1.univers65);
    Font.registerFont(_loc_1.univers65oblique);
    Font.registerFont(_loc_1.Trixie);
    Font.registerFont(_loc_1.Poplar);
    Font.registerFont(_loc_1.hp14);
    coreLoader.contentLoaderInfo.content["univers55font"] = new _loc_1["univers55"];
    coreLoader.contentLoaderInfo.content["univers55Ofont"] = new _loc_1["univers55oblique"];
    coreLoader.contentLoaderInfo.content["univers65font"] = new _loc_1["univers65"];
    coreLoader.contentLoaderInfo.content["univers65Ofont"] = new _loc_1["univers65oblique"];
    coreLoader.contentLoaderInfo.content["trixiefont"] = new _loc_1["Trixie"];
    coreLoader.contentLoaderInfo.content["labelfont"] = new _loc_1["Poplar"];
    coreLoader.contentLoaderInfo.content["hp14font"] = new _loc_1["hp14"];
    var _loc_2:* = coreLoader.contentLoaderInfo.content;
    _loc_2.coreLoader.contentLoaderInfo.content["initializeAll"]();
    this.getUserIP();
    }// end if
    return;
    }// end function

    public function coreLoadProg(param1:ProgressEvent) : void
    {
    if (coreBytesTotal == 0)
    {
    coreBytesTotal = param1.bytesTotal;
    }// end if
    coreBytesLoaded = param1.bytesLoaded;
    this.updateLoader();
    return;
    }// end function

    public function updateLoader() : void
    {
    var bt:Number;
    var bl:Number;
    var ls:Sprite;
    bt = coreBytesTotal + fontBytesTotal;
    bl = coreBytesLoaded + fontBytesLoaded;
    if (coreBytesTotal > 0 && fontBytesTotal > 0 && !this.loadBar)
    {
    this.loadBar = new Sprite();
    this.lbTxt = new TextField();
    this.lbTxt.text = Math.round(bl / 1024) + " / " + Math.round(bt / 1024);
    this.lbTxt.setTextFormat(new TextFormat("Arial", 9, 0));
    this.lbTxt.y = 4;
    this.lbTxt.x = 56;
    this.loadBar.addChild(this.lbTxt);
    ls = new Sprite();
    var _loc_2:* = ls;
    with (ls)
    {
    graphics.lineStyle(1, 0, 0.6, true);
    graphics.moveTo(0, -2);
    graphics.lineTo(0, 6);
    graphics.moveTo(50, -2);
    graphics.lineTo(50, 6);
    graphics.moveTo(100, -2);
    graphics.lineTo(100, 6);
    }// end with
    this.loadBar.addChild(ls);
    this.loadBar.y = 6;
    this.loadBar.x = 6;
    addChild(this.loadBar);
    }// end if
    if (this.loadBar)
    {
    var _loc_2:* = this.loadBar;
    with (this.loadBar)
    {
    graphics.clear();
    graphics.beginFill(13369344, 0.6);
    graphics.drawRect(0, 0, bl / bt * 100, 4);
    graphics.endFill();
    }// end with
    this.lbTxt.text = Math.round(bl / 1024) + " / " + Math.round(bt / 1024);
    this.lbTxt.setTextFormat(new TextFormat("Arial", 9, 0));
    }// end if
    return;
    }// end function

    function frame1()
    {
    Security.allowDomain("http://10.37.129.2");
    Security.allowDomain("http://www.joshstrike.com");
    Security.allowDomain("http://joshstrike.com");
    Security.loadPolicyFile("http://joshstrike.com/crossdomain.xml");
    Security.loadPolicyFile("http://www.joshstrike.com/crossdomain.xml");
    coreBytesLoaded = 0;
    coreBytesTotal = 0;
    coreLoaded = false;
    fontBytesLoaded = 0;
    fontBytesTotal = 0;
    fontsLoaded = false;
    t = new Timer(100);
    t.start();
    mr = Math.round(Math.random() * 1000);
    coreReq = new URLRequest("Core.swf?r=" + mr);
    coreLoader = new Loader();
    coreLoader.name = "core";
    addChild(coreLoader);
    coreLoader.contentLoaderInfo.addEventListener(Prog ressEvent.PROGRESS, this.coreLoadProg, false, 0, true);
    coreLoader.contentLoaderInfo.addEventListener(Even t.INIT, this.gotCoreLoad, false, 0, true);
    coreLoader.contentLoaderInfo.addEventListener(IOEr rorEvent.IO_ERROR, this.failedLoad, false, 0, true);
    coreLoader.load(coreReq);
    fontReq = new URLRequest("Fonts.swf?r=" + mr);
    fontLoader = new Loader();
    fontLoader.name = "fonts";
    addChild(fontLoader);
    fontLoader.contentLoaderInfo.addEventListener(Prog ressEvent.PROGRESS, this.fontLoadProg, false, 0, true);
    fontLoader.contentLoaderInfo.addEventListener(Even t.INIT, this.gotFontLoad, false, 0, true);
    fontLoader.contentLoaderInfo.addEventListener(IOEr rorEvent.IO_ERROR, this.failedLoad, false, 0, true);
    fontLoader.load(fontReq);
    soundstream = new URLRequest("music/mslide1.mp3");
    this.introSound = new Sound();
    soundPolicy = new SoundLoaderContext(1000, true);
    this.introSound.load(soundstream, soundPolicy);
    this.introSound.addEventListener(IOErrorEvent.IO_E RROR, this.failedLoad, false, 0, true);
    return;
    }// end function

    public function getUserIP() : void
    {
    if (ExternalInterface.available && ExternalInterface.objectID != null)
    {
    ExternalInterface.addCallback("getip", coreLoader.contentLoaderInfo.content["executeCallback"]);
    ExternalInterface.call("callExternalInterface");
    }
    else
    {
    var _loc_1:* = coreLoader.contentLoaderInfo.content;
    _loc_1.coreLoader.contentLoaderInfo.content["executeCallback"]("Not.a.browser.!!!");
    }// end else if
    return;
    }// end function

    public function gotFontLoad(param1:Event) : void
    {
    fontsLoaded = true;
    this.processFinished();
    return;
    }// end function

    public function failedLoad(param1:IOErrorEvent) : void
    {
    return;
    }// end function

    public function gotCoreLoad(param1:Event) : void
    {
    coreLoaded = true;
    this.processFinished();
    return;
    }// end function

    public function fontLoadProg(param1:ProgressEvent) : void
    {
    if (fontBytesTotal == 0)
    {
    fontBytesTotal = param1.bytesTotal;
    }// end if
    fontBytesLoaded = param1.bytesLoaded;
    this.updateLoader();
    return;
    }// end function

    }
    }

  3. #3
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    That's all you got?

  4. #4
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    Okay, I realize that the preloader can be decompiled. What I'm wondering is whether anyone can decompile the guts.

  5. #5
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Yes.

    Is this enough guts to prove it?
    Attached Files Attached Files

  6. #6
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    YES! Thank you, thank you!!! I knew it could be done. What decompiler did you use?

    I'd heard that the latest ******* decompiler can get around GuardBunny, but it's unclear how exactly it's doing it. It might just be searching forward for the GuardBunny class name. Maybe it's actually short-circuiting try/catch statements. I'm assuming all AS3 decompilers still have to actually run the bytecode in a VM in order to function; am I wrong about that?

    Anyway, I've devised what I'm hoping is a devilishly more sophisticated approach that, rather than relying on external variables or an external class, takes advantage of the VM's own security protections. Care to give this one a try???

    http://www.joshstrike.com/SafeDocument.swf

  7. #7
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    I used the HP security tool. I highly doubt it's specifically looking for GuardBunny, so I'm guessing that it does not in fact have to run the bytecode.

    I'll try SafeDocument in a bit.

  8. #8
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    And by the way, the end goal here isn't to stop the NSA from cracking my code; just to fuxr with enough different decompilers to keep the Russians at bay for awhile...

  9. #9
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Is there more to it than this?

    Code:
        public class SafeDocument extends flash.display::MovieClip 
        {
    
            //========================= Variables
            private var l : Loader;
    
            //========================= Methods
    
            public static function SafeDocument()
            {
                return;
                
            }
    
    
            public function SafeDocument()
            {
                r = null;
                context = null;
                this.l = new Loader();
                super();
                try {
                    try {
                                r = new URLRequest("http://www.joshstrike.com/images/web/savela1.jpg");
                                context = new LoaderContext();
                        context.securityDomain = SecurityDomain.currentDomain;
                        l.load(r, context);
                
                    } catch (err:Error) {
                        var loc1:* = err;
                                r = null;
                        this.noImg();
                
                    }
                
                } catch (*:*) {
                    loc1 = *;
                    var loc2:* = null;
                
                }
                return;
                
            }
    
    
            private function init(arg0:flash.events::Event)
            {
                trace("YES");
                return;
                
            }
    
    
            private function noImg()
            {
                try {
                    try {
                        this.boogie();
                
                    } catch (err:Error) {
                        var loc1:* = err;
                                someVal = null;
                        this.noImg();
                
                    }
                
                } catch (*:*) {
                    loc1 = *;
                    var loc2:* = null;
                
                }
                this.noImg();
                return;
                
            }
    
    
            private function boogie()
            {
                i = NaN;
                try {
                    try {
                        for(;;)
                        {
                                        i = 0;
                            while(i < Infinity)
                            {
                                trace("hah");
                                                i = i + 1;
                            }
                            this.noImg();
                        }
                
                    } catch (err:Error) {
                        var loc1:* = err;
                                i = null;
                        this.noImg();
                
                    }
                
                } catch (*:*) {
                    loc1 = *;
                    var loc2:* = null;
                
                }
                this.noImg();
                return;
            }
        }

  10. #10
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    No, that's it. Pretty amazing. I just got the HP tool to try it out.

    I think it definitely _is_ running the bytecode, because it seems to be adding a lot of extras to it to prevent exactly the kind of behavior I was going for.

    Specifically, it takes out the finally{} blocks. And in addition to that, it modified the while() loops. Here is the original code for comparison. Pretty fascinating what it's doing, actually:

    Code:
    package {
    	
    	import flash.display.MovieClip;
    	import flash.display.Loader;
    	import flash.net.URLRequest;
    	import flash.events.Event;
    	import flash.events.IOErrorEvent;
    	import flash.system.LoaderContext;
    	import flash.system.ApplicationDomain;
    	import flash.system.SecurityDomain;
    	
    	public class SafeDocument extends MovieClip {
    				
    		private var l:Loader = new Loader();
    		
    		public function SafeDocument():void {
    			try {
    				var r:URLRequest = new URLRequest("http://www.joshstrike.com/images/web/savela1.jpg");
    				var context:LoaderContext = new LoaderContext();
    				context.securityDomain = SecurityDomain.currentDomain;
    				l.load(r,context);
    			} catch (err:Error) {
    				noImg();
    			} finally {
    				//noImg();
    			}
    		}
    		
    		private function init(evt:Event):void {
    			trace ("YES");
    		}
    		
    		private function noImg():void {
    			try {
    				boogie();
    			} catch (err:Error) {
    				noImg();
    			} finally {
    				noImg();
    			}
    		}
    		private function boogie():void {
    			try {
    				while (true) {
    					for (var i:Number = 0;i<Infinity;i++) {
    						trace ("hah");
    					}
    					noImg();
    				}
    			} catch (err:Error) {
    				noImg();
    			} finally {
    				noImg();
    			}
    		}
    	}
    }

  11. #11
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    It's actually putting all try/catch blocks inside its own try/catch block. !?

  12. #12
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Huh. That is rather interesting. Specifically, I found the "loc = *" line really weird. I wonder if the extracted code would even compile with flash or flex. Still, it gives you enough code to steal the interesting bits.

    I'd suggest a transformative process, so that the actual code is not in the swf file. Rather, some data which is transformed into the code. This could be as simple as a bit inverted version, though I'd actually suggest a stronger encryption with a key that's not embedded in the file (flashvars, externalinterface, generate from url, etc). The point is, make the loader code generate the code to actually run. This would defeat the script kiddies who just want to run a tool and grab the low-hanging fruit. It won't deter a determined attacker for very long.

  13. #13
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    That code would definitely not run. Just the first line in the constuctor, r=null, would fire an error. It seems to be trying to undermine local vars in functions of certain types, in this case URLRequest and LoaderContext. I don't blame it.

    I once modified my standard Loader to bring in the secure bits as a byteArray, like what you're suggesting; it can't be that hard to snatch the data out of the stream though, and there's no kind of encryption that even makes sense for the overhead, considering how easy it would be to decrypt it. The text file is twice the size of the original .swf, and the added security is minimal. The only way I can see making decompilation really truly a costly effort would be to hang the decompilers on something.

    This gives me an idea of what I might have to do, anyway. For one thing, it super() calls to MovieClip; then it creates this static function to mirror the constructor. Pre-empting those two actions might be a good start.

    I'll let you know what I come up with...

  14. #14
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    Ah! Dig it. By adding the static function, it gets it to throw a compiler error and abnegates further errors in the stack. At least that's what seems to happen. If you add that static constructor function and compile in Flash, you get a compiler error, but the big bad crash loop never happens. So they get their code off the stack and then keep moving on.

  15. #15
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    HahahahHAHAAAAAAA!!!!!!!!!!!!!!!!!!

    Took me 20 minutes but I BEAT IT!!!!

    Try it now... look at it first, http://www.joshstrike.com/SafeDocument.swf

    LOLZ

    I am the king of the seeeeeaaaaaaaaaaaa

  16. #16
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    I like it. Be sure to test the other popular decompilers.

  17. #17
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    I don't have / can't afford / can't run any of them...
    Maybe the guys at SOthnk (if I spell it, it will be bleeped) can have a shot at it...

  18. #18
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    I don't have any of them either. I did test with the swfutils demo, which gave me nothing any more useful than the hp tool.

    Mind sharing with us?

  19. #19
    Senior Member joshstrike's Avatar
    Join Date
    Jan 2001
    Location
    Alhama de Granada, España
    Posts
    1,136
    (sucking in breath)

    at the moment it's not really working for my larger .fla's... if you want to know, email me directly (josh at joshstrike.com) there's no way on earth I'm letting this one out to the public...
    Last edited by joshstrike; 05-20-2009 at 12:39 AM.

  20. #20
    Member
    Join Date
    Jul 2005
    Location
    Brisbane, Australia
    Posts
    66
    is this it?

    PHP Code:
    private class fckoff extends flash.display::MovieClip 
    {

        
    //========================= Variables
        
    private var LoaderContext;
        private var 
    Loader;
        private var 
    Sprite;
        private var 
    cc : *;
        private var 
    vx Number 10;
        private var 
    vy Number 10;

        
    //========================= Methods

        
    private static function fckoff()
        {
            return;
            
        }


        private function 
    fckoff()
        {
            
    null;
            
    this.= new Loader();
            
    this.= new LoaderContext();
            
    this.= new Sprite();
            
    this.vx 10;
            
    this.vy 10;
            
    super();
            try {
                    
    = new URLRequest("http://www.joshstrike.com/images/web/savela1.jpg");
                
    this.cc this.c;
                
    this.cc.securityDomain SecurityDomain.currentDomain;
                
    l.load(rthis.cc);
            
            } catch (
    err:Error) {
                var 
    loc1:* = err;
                    
    null;
                
    this.noImg();
            
            }
            
    this.init();
            return;
            
        }


        private function 
    boogie()
        {
            var 
    loc0:* = NaN;
            for(;;)
            {
                
    loc0 0;
                while(
    loc0 Infinity)
                {
                    
    trace("hah");
                    
    loc0 loc0 1;
                    
    loc0 loc0 1;
                }
                
    this.noImg();
            }
            return;
            
        }


        private function 
    doLoop(arg0:flash.events::Event)
        {
            if((
    this.s.550 || this.s.0))
            {
                
    this.vx this.vx 255;
            }
            if((
    this.s.|| this.s.400))
            {
                
    this.vy this.vy 255;
            }
            
    this.s.0;
            
    this.s.0;
            return;
            
        }


        private function 
    init(arg0:flash.events::Event null)
        {
            
    evt arg0;
            var 
    loc1:* = this.s;
            
    graphics.beginFill(167116801);
            
    graphics.drawCircle(0020);
            
    graphics.endFill();
            
    loc1 100;
            
    this.s.100;
            
    this.s.undefined;
            
    addChild(this.s);
            
    s.addEventListener(Event.ENTER_FRAMEthis.doLoopfalse0true);
            return;
            
        }


        private function 
    noImg()
        {
            try {
                try {
                    
    this.boogie();
            
                } catch (
    err:Error) {
                    var 
    loc1:* = err;
                            
    someVal null;
                    
    this.noImg();
            
                }
            
            } catch (*:*) {
                
    loc1 = *;
                var 
    loc2:* = null;
            
            }
            
    this.noImg();
            return;
            
        }




Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center