Results 1 to 3 of 3

Thread: Code Obfuscation For AS3

  1. #1
    164
    posts
    Registered User

    Code Obfuscation For AS3

    http://osflash.org/flex2cpp
    http://flex2cpp.sourceforge.net/

    I made some horrifying discoveries with 'abcdump': even the names of some local variables and constants (ones initialized when declared) and function parameters (ones with default values) were preserved in the output, so the obfuscator renames local variables as well.

    Thinking about all those evil people (like me) who occasionally use a Flash decompiler, I made an automatic function/variable finder and renamer for my preprocessor-based builds.
    Original
    Code:
            /**
             * Do the complete flood Fill starting at {dx,dy}, disregarding any meaning for values that aren't blocked or 'unfilled'
             * You wind up with a trail from sx,sy to dx,dy of decreasing values for Path()
             * @param pathmap Bitmap already filled with the map template
             * @param dx,dy The target
            **/
            static public function FillBasic( pathmap : BitmapData, dx:int, dy:int ) : void
            {
                pathmap.lock();
                FIFO_DECL(stack);        // Stack for values searched
                var curr:Object;
                var newvalue:uint;
                var currx:int;
                var curry:int;
                var tx:int;
                var ty:int;
                var value:uint;
                value = pathmap.getPixel( dx, dy );
                if( FILLED(value) )
                    return;
                FIFO_FIRST(stack,dx,dy);
                pathmap.setPixel( dx, dy, TARGET_VALUE );
                while( null != (curr = FIFO_EARLIEST(stack)) )
                {
                    currx = curr.x;
                    curry = curr.y;
                    value = pathmap.getPixel( x, y )+1;
                    #define trydir(dirx,diry) \
                        tx = currx dirx;\
                        ty = curry diry;\
                        newvalue = pathmap.getPixel( tx, ty );\
                        if( UNFILLED(newvalue) )\
                        {\
                            pathmap.setPixel( tx, ty, value );\
                            FIFO_PUSH( stack, tx, ty )\
                        }
                    trydir(+1,ppNULL)
                    trydir(ppNULL,+1)
                    trydir(-1,ppNULL)
                    trydir(ppNULL,-1)
                    FIFO_POP_DISCARD(stack);
                    #undef trydir
                }
                pathmap.unlock();        
            }
    Preprocessed (and pretty-printed) debug build
    Code:
      /**
             * Do the complete flood Fill starting at {dx,dy}, disregarding any meaning for values that aren't blocked or 'unfilled'
             * You wind up with a trail from sx,sy to dx,dy of decreasing values for Path()
             * @param pathmap Bitmap already filled with the map template
             * @param dx,dy The target
            **/
            static public function FillBasic( pathmap:BitmapData, dx:int, dy:int ):void
            {
                pathmap.lock();
                var headstack:Object = null;
                var tailstack:Object = null;;    // Stack for values searched
                var curr:Object;
                var newvalue:uint;
                var currx:int;
                var curry:int;
                var tx:int;
                var ty:int;
                var value:uint;
                  value = pathmap.getPixel( dx, dy );
                if ( ( ( value ) <= 0x00ff0000 ) )
                      return;
                {
                    tailstack = headstack =
                    {
                  x: dx, y: dy, next:null};
                };
                pathmap.setPixel( dx, dy, 0x01000000 );
                while ( null != ( curr = headstack ) )
                {
                    currx = curr.x;
                    curry = curr.y;
                    value = pathmap.getPixel( x, y ) + 1;
    
                    tx = currx + 1;
                    ty = curry;
                    newvalue = pathmap.getPixel( tx, ty );
                    if ( ( ( newvalue ) > 0x00ff0000 ) )
                    {
                        pathmap.setPixel( tx, ty, value );
                        {
                            tailstack = tailstack.next =
                            {
                          x: tx, y: ty, next:null};
                        }
                    }
                    tx = currx;
                    ty = curry + 1;
                    newvalue = pathmap.getPixel( tx, ty );
                    if ( ( ( newvalue ) > 0x00ff0000 ) )
                    {
                        pathmap.setPixel( tx, ty, value );
                        {
                            tailstack = tailstack.next =
                            {
                          x: tx, y: ty, next:null};
                        }
                    }
                    tx = currx - 1;
                    ty = curry;
                    newvalue = pathmap.getPixel( tx, ty );
                    if ( ( ( newvalue ) > 0x00ff0000 ) )
                    {
                        pathmap.setPixel( tx, ty, value );
                        {
                            tailstack = tailstack.next =
                            {
                          x: tx, y: ty, next:null};
                        }
                    }
                    tx = currx;
                    ty = curry - 1;
                    newvalue = pathmap.getPixel( tx, ty );
                    if ( ( ( newvalue ) > 0x00ff0000 ) )
                    {
                        pathmap.setPixel( tx, ty, value );
                        {
                            tailstack = tailstack.next =
                            {
                          x: tx, y: ty, next:null};
                        }
                    }
                    {
                        headstack = headstack.next;
                    };
    
                }
                pathmap.unlock();
            }
    Preprocessed, Obfuscated( and pretty-printed) release-mode build
    Code:
      /**
             * Do the complete flood Fill starting at {dx,dy}, disregarding any meaning for values that aren't blocked or 'unfilled'
             * You wind up with a trail from sx,sy to dx,dy of decreasing values for Path()
             * @param _355 Bitmap already filled with the map template
             * @param dx,dy The target
            **/
            static public function _160( _355:BitmapData, _118:int, _119:int ):void
            {
                _355.lock();
                var _45:Object = null;
                var _304:Object = null;;    // Stack for values searched
                var _91:Object;
                var _286:uint;
                var _93:int;
                var _94:int;
                var _421:int;
                var _422:int;
                var _428:uint;
                  _428 = _355.getPixel( _118, _119 );
                if ( ( ( _428 ) <= 0x00ff0000 ) )
                      return;
                {
                    _304 = _45 =
                    {
                  x: _118, y: _119, _290:null};
                };
                _355.setPixel( _118, _119, 0x01000000 );
                while ( null != ( _91 = _45 ) )
                {
                    _93 = _91.x;
                    _94 = _91.y;
                    _428 = _355.getPixel( x, y ) + 1;
    
                    _421 = _93 + 1;
                    _422 = _94;
                    _286 = _355.getPixel( _421, _422 );
                    if ( ( ( _286 ) > 0x00ff0000 ) )
                    {
                        _355.setPixel( _421, _422, _428 );
                        {
                            _304 = _304._290 =
                            {
                          x: _421, y: _422, _290:null};
                        }
                    }
                    _421 = _93;
                    _422 = _94 + 1;
                    _286 = _355.getPixel( _421, _422 );
                    if ( ( ( _286 ) > 0x00ff0000 ) )
                    {
                        _355.setPixel( _421, _422, _428 );
                        {
                            _304 = _304._290 =
                            {
                          x: _421, y: _422, _290:null};
                        }
                    }
                    _421 = _93 - 1;
                    _422 = _94;
                    _286 = _355.getPixel( _421, _422 );
                    if ( ( ( _286 ) > 0x00ff0000 ) )
                    {
                        _355.setPixel( _421, _422, _428 );
                        {
                            _304 = _304._290 =
                            {
                          x: _421, y: _422, _290:null};
                        }
                    }
                    _421 = _93;
                    _422 = _94 - 1;
                    _286 = _355.getPixel( _421, _422 );
                    if ( ( ( _286 ) > 0x00ff0000 ) )
                    {
                        _355.setPixel( _421, _422, _428 );
                        {
                            _304 = _304._290 =
                            {
                          x: _421, y: _422, _290:null};
                        }
                    }
                    {
                        _45 = _45._290;
                    };
    
                }
                _355.unlock();
            }
    The Makefile script
    Code:
    ##################################
    #
    # Make a list of classes, functions 
    # and class member variables.
    #
    symbols:
        @find src -name "*.as3" -exec sed -n \
            -e "s/^.*function \(.*\)(.*$$/\1/p"\
            -e "s/^.*\b\(public\|protected\|private\|internal\)\b.*\b\(var\|const\)\b[ \t]*\(.*\):.*$$/\3/p" \
            {} ;
    
    ##################################
    #
    # Make a list of symbols (except constructors),
    # sort them, remove duplicates, remove extra
    # whitespace, #define them to _1, _2, _3...
    # In other words, auto-generate an obfuscate.h
    # to turn release-mode code into spaghetti drool.
    # 
    obfuscate:
        @find src -name "*.as3" -exec sed -n \
            -e "s/^.*function \(.*\)(.*).*:.*$$/\1/p" \
            -e "s/^.*\b\(var\|const\)\b[ \t]*\([A-Za-z0-9_]*\).*:.*$$/\2/p" \
            {} ;\
        |sort|sed "$!N; /^\(.*\)\n\1$$/!P; D"\
        |sed -e "s/[ \t]*$$//" -e "s/^/#define /" \
        |sed -n -e "/.*/ p;=" |sed -e "N;s/\n/ _/"
    It's just the first pass. What it really needs to do is generate the obfuscate.h based on the already-preprocessed code and then rebuild, so all of the symbols are discovered, including the preprocessor-generated ones.

    The major caveat is that YOUR code can't contain any names from the Actionscript libraries (i.e. mask, x, y, bitmapData, etc.) because it's a simple sed script that doesn't compare to a big list of exceptions. I might spend more time on it, but it only took a couple of hours of edit/compile/curse to wring all the little devils out of my code, and it would take a day or two to write a dedicated obfuscation tool.

    It also doesn't rename classes, because it would need to rename the files, too.

    You can also make your own obfuscation entries in your include file to eliminate local classes and things that the obfuscate-a-tronic doohicky doesn't notice.

    Here's a recommended 'obfuscate.h' pattern...
    Code:
    #ifndef OBFUSCATE_H
    #define OBFUSCATE_H
    #ifndef DEBUG
    
    // Define things the search doesn't spot
    #define MyLocalClass _o
    #define MyOtherLocalClass _0
    
    // Include the auto-generated definitions
    #include "auto-obfuscate.h"
    
    #endif // DEBUG
    #endif // OBFUSCATE_H

  2. #2
    Wow, great work. Any chance for a GUI in the near future? Or maybe even a Flash extension?

  3. #3
    164
    posts
    Registered User
    GUI? For a Makefile? You speak heresy!

    Besides, it's not like I can type sed "s/CLI/GUI/g"<Makefile>extension.java, and have Make fit into Flash.

    The obfuscator is a byproduct of using the preprocessor. You betcha it would be nice to integrate CPP (or some other preprocessor) into Flash its self for those poor benighted souls who don't know how to write code in classes and make their application into an 'easter egg hunt' through Flash's gawdawful mousey-clicky hell.

    Somebody could write up an equally good xml script for ANT that does the same kinds of things the makefile does, or I suppose they could even write the code in Java and integrate it into that extension thingamajig. I don't have time for it. I'm too busy on an (ooh retro, ouch) AS2 project for money, and I still have the rest of that 3D game engine and AS server back-end to finish, too.

    Most decent code editors (unlike Flash, which is in no way a decent anything) have simple, press-a-key-and-run-this-script-in-the-shell forms, and that's the only level of GUI I use. jEdit's nice. It has the syntax highlighting for AS, and has a little 'command line' inside of it. That's actually fairly typical for many good programmer's editors.

    Anyway, anybody could grab what they want from the tool and do what they want with it, include see how it works and reinvent the wheel for themselves. It's PD, and I don't even care if they act like they invented it. It's not like it's ground-breaking new work, and I won't pretend for a moment that it's a wheel nobody else has invented.

    The sed invocations in the 'obfuscate:' target are regular expression stuff to ferret out the symbols and such, and turn it into #define symbol _123. The double-dollars $$ on the end-of-line symbols are for Make, which uses '$' for other things, so it needs to be escaped.

    Of course, it might be telling that the sed scripts made sense when I typed 'em up, but probably wouldn't make sense to other people who haven't spent some time in a Linux shell like BASH. In other words, the obfuscation script is its self somewhat obfuscated. Sorry about that. Just a convenient way to wring text out of a file.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

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

Home About kirupa.com Meet the Moderators Advertise

 Link to Us

 Credits

Copyright 1999 - 2012