--- nfo/perl/scripts/fluscate/bin/fluscate.pl 2004/07/23 12:24:52 1.2 +++ nfo/perl/scripts/fluscate/bin/fluscate.pl 2004/08/03 00:24:15 1.6 @@ -1,9 +1,25 @@ #!/usr/bin/perl -# fluscate.pl 0.03 - The Flash Obfuscator +# fluscate - The Flash Obfuscator -# $Id: fluscate.pl,v 1.2 2004/07/23 12:24:52 joko Exp $ +# $Id: fluscate.pl,v 1.6 2004/08/03 00:24:15 joko Exp $ # $Log: fluscate.pl,v $ +# Revision 1.6 2004/08/03 00:24:15 joko +# restructured code (procedures) +# command-line arguments +# new feature: pollute +# +# Revision 1.5 2004/07/26 16:11:58 joko +# updated pod +# included more complete list of flash event-handlers +# fixed substitution regex #1: now using spaces around function names +# +# Revision 1.4 2004/07/26 13:51:54 joko +# updated pod +# +# Revision 1.3 2004/07/23 12:56:07 joko +# updated pod +# # Revision 1.2 2004/07/23 12:24:52 joko # pod # @@ -13,8 +29,10 @@ =pod + fluscate - The Flash Obfuscator + This software is Copyright (C) 2004 Andreas Motl - Ideas and future AppleScript integration by Holger Marseille. + Ideas and MacOS X Application by Holger Marseille This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -37,20 +55,47 @@ =head1 Features + +=head2 Obfuscation + + See ASO Pro: http://www.genable.com/aso/preview.html + + =head2 Functions fluscate handles two different styles of function declarations: - 1. "Normal" ones + 1. "Normal" ones, e.g. function mp3Player ('arg1', 'arg2') - 2. There may be "stacked" function declarations + 2. There may be "stacked" function declarations, e.g. push 'mp3Player' function () +=head2 Pollute + + Some flash-disassemblers might croak when inserting the following code + after a/each "constants"-declaration: + + push 0 + ls: + dup + trace + branchIfTrue ls" + + +=head1 Dependencies + + "flasm" is required to disassemble swf files, see http://www.nowrap.de/flasm.html + ACKs go to Igor Kogan. + =head1 Usage +=head2 General + + Please type "fluscate --help" to get more information about command-line parameters. + =head2 win32 #> flasm.exe -d puzzle.swf > puzzle.flm @@ -59,9 +104,9 @@ =head2 *nix - #> flasm -d puzzle.swf > puzzle.flm - #> cat puzzle.flm | fluscate.pl > puzzle_fusc.flm - #> flasm -a puzzle_fusc.flm + #> ./flasm -d puzzle.swf > puzzle.flm + #> cat puzzle.flm | ./fluscate.pl > puzzle_fusc.flm + #> ./flasm -a puzzle_fusc.flm =head1 Development @@ -76,13 +121,10 @@ zufallsprinip (-21,-3,-89)? (->random) - evtl. constants nach abfrage ersetzen ? leider sehr aufwendig, bei vielen constants (->ask) - rausgeben des arrays mit den "neuen" werten um evtl die obfuscation rückgängig zu machen (->undo) - - " push 0 - ls: - dup - trace - branchIfTrue ls" - ... after each "constants" declaration (->pollute) - what about other symbols beside "function"s? (e.g. variables) (->mode) + - include list of ->keywords from: + http://www.macromedia.com/support/flash/action_scripts/actionscript_dictionary/ + - replace symbols in multiple files (->multifile) =head2 Notes @@ -95,12 +137,74 @@ - "getMember" and "getVariable" also do function calls! - there are reserved function names which must not be replaced! (-> event handlers, e.g. "onPress") + +=head1 Links + +=head2 ActionScript Decompilers / Disassemblers + + Flasm: + http://www.nowrap.de/flasm.html + http://www.opaque.net/~dave/flasm/ + Flare: http://www.nowrap.de/flare.html + Sothink SWF Decompiler: http://www.srctec.com/flashdecompiler/ + Imperator FLA: http://www.ave-imperator.com/ + SWF Decompiler: http://www.19.5degs.com/swfdecompiler.php + Gordon: http://www.futurecandy.com/ + +=head2 ActionScript Editors & Co. + + URL Action Editor and Actionscript Viewer: + http://www.buraks.com/ + http://voisen.org/archives/2003/02/uae_303_and_asv_309.php + SE|PY ActionScript Editor: http://www.sephiroth.it/python/sepy.php + +=head2 Obfuscators + + ASO Pro (ActionScript Obfuscator Pro): http://www.genable.com/aso/preview.html + SWOB (swf obfuscator): http://home.byu.net/jtb64/Swob.htm + OBFU - A Flash Actionscript obfuscator: http://opaque.net/~dave/obfu/ + +=head2 Misc + + ActionScript Protection: + http://www.as-protect.com/ + http://www.quasimondo.com/archives/000377.php + Developer's SWF Guardian: http://anyrd.anyorganization.com/ + Password Busting / SWF Protections: http://www.searchlores.org/cinix_fla.htm + +=head2 Off-Topic + +=head3 XML + + XPath for Actionscript and other stuff: http://www.xfactorstudio.com/Actionscript/ + XMLRPC Flash Libraries for ActionScript 2.0: http://xmlrpcflash.sourceforge.net/ + +=head3 Marshalling / AMF (Flash Remoting protocol) + + AMFPHP - Flash Remoting for PHP: http://www.amfphp.org/ + AMF::Perl - Flash Remoting in Perl and Python: http://simonf.com/amfperl/ + SerializerClass: http://sourceforge.net/projects/serializerclass/ + +=head3 Misc + + PEAR::SWF - Read and write SWF head tag: http://www.sephiroth.it/test/php/SWF/ + Convert videos to flv: + http://ffmpeg.sourceforge.net/ + http://www.videohelp.com/tools?tool=263 + Flash-CMS: http://www.lachoseinteractive.net/fr/produits/alahup/ + =cut use strict; use warnings; +use Getopt::Long; +use Storable; +use Data::Dumper; + +my $VERSION = "0.10"; + my $regex = { 'function' => 'function(?:2|)\s(.+?)\s\(.*?\)', 'constants' => 'constants', @@ -108,69 +212,165 @@ 'function_stacked' => 'function(?:2|)\s\s\(.*?\)', 'push' => 'push\s\'(.+?)\'', }; -my @symbols_events = qw( onPress onReleaseOutside onRelease onMouseDown onEnterFrame ); my @symbols; +my @lines; +my $options; -# 1. read flasm code from STDIN -my @lines = ; +sub read_options { + GetOptions( + "pollute" => \$options->{pollute}, + "help" => \$options->{help}, + "version" => \$options->{version} + ); +} -my $counter = 0; -foreach (@lines) { +sub scan_symbols { + my @symbols_events = qw( + onDragOut + onDragOver + onKeyUp + onKeyDown + onKillFocus + onPress + onRelease + onReleaseOutside + onRollOut + onRollOver + onSetFocus + onActivity + onStatus + onSelect + onData + onLoad + allowDomain + allowInsecureDomain + onMouseDown + onMouseMove + onMouseUp + onMouseWheel + onEnterFrame + onUnload + onLoadComplete + onLoadError + onLoadInit + onLoadProgress + onLoadStart + onID3 + onSoundComplete + onResize + onChanged + onScroller + ); - # trim newlines - #chomp; - my $symbol; - - # check for all "function" / "function2" symbols and ... - if (m/$regex->{function}/) { - # ... remember them - $symbol = $1; - - - } elsif (m/$regex->{function_stacked}/) { - if ($lines[$counter - 1] =~ m/$regex->{push}/) { + my $counter = 0; + foreach (@lines) { + + # trim newlines + #chomp; + my $symbol; + + # check for all "function" / "function2" symbols and ... + if (m/$regex->{function}/) { + # ... remember them $symbol = $1; + + + } elsif (m/$regex->{function_stacked}/) { + if ($lines[$counter - 1] =~ m/$regex->{push}/) { + $symbol = $1; + } } + + if ($symbol and not grep(/$symbol/, @symbols_events)) { + push @symbols, $symbol; + } + + $counter++; + } - if ($symbol and not grep(/$symbol/, @symbols_events)) { - push @symbols, $symbol; - } - - $counter++; - } #print join("\n", @symbols); exit; # 2. step through all symbols found and replace them -my $symbol_counter = -1; -foreach my $symbol (@symbols) { - my $line_counter = 0; - foreach (@lines) { - - # function declarations; single quotes might not be there! - if (m/$regex->{function}/) { - s/'*$symbol'*/'$symbol_counter'/i; - - # "constants"-line at begin of each block; single quotes should already be there - } elsif (m/$regex->{constants}/) { - s/'$symbol'/'$symbol_counter'/i; - - # function calls; replace inside predecessor line of calling-lines - } elsif (m/$regex->{call}/) { - $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_counter'/i; +sub obfuscate { - # function declarations; name of function is pushed on stack one line before! - } elsif (m/$regex->{function_stacked}/) { - $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_counter'/i; + # 1st stage: symbol replacement + my $symbol_counter = -1; + foreach my $symbol (@symbols) { + my $line_counter = 0; + foreach (@lines) { + + # function declarations; single quotes might not be there! + if (m/$regex->{function}/) { + s/\s'*$symbol'*\s/ '$symbol_counter' /i; + + # "constants"-line at begin of each block; single quotes should already be there + } elsif (m/$regex->{constants}/) { + s/'$symbol'/'$symbol_counter'/i; + + # function calls; replace inside predecessor line of calling-lines + } elsif (m/$regex->{call}/) { + $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_counter'/i; + + # function declarations; name of function is pushed on stack one line before! + } elsif (m/$regex->{function_stacked}/) { + $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_counter'/i; + } + + $line_counter++; + } + $symbol_counter--; + } - $line_counter++; - + # 2nd stage: pollute & Co. + if ($options->{pollute}) { + foreach (@lines) { + if (m/$regex->{constants}/) { + my $inject = qq( + push 0 + ls: + dup + trace + branchIfTrue ls + +); + $_ .= $inject; + } + } } - $symbol_counter--; + +} + +sub usage { + print "fluscate - The Flash Obfuscator (v$VERSION)", "\n"; + if (not $options->{version}) { + print <{help} || $options->{version}) { + usage(); + exit; + } + # read flasm code from STDIN + @lines = ; + scan_symbols(); + obfuscate(); + # write all stuff to STDOUT + print STDOUT @lines; +} + +main(); + +1; +__END__