/[cvs]/nfo/perl/scripts/fluscate/bin/fluscate.pl
ViewVC logotype

Contents of /nfo/perl/scripts/fluscate/bin/fluscate.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations)
Tue Aug 3 02:36:05 2004 UTC (19 years, 11 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +137 -25 lines
File MIME type: text/plain
new features: Random, Undo, Interactive mode

1 #!/usr/bin/perl
2
3 # fluscate - The Flash Obfuscator
4
5 # $Id: fluscate.pl,v 1.6 2004/08/03 00:24:15 joko Exp $
6 # $Log: fluscate.pl,v $
7 # Revision 1.6 2004/08/03 00:24:15 joko
8 # restructured code (procedures)
9 # command-line arguments
10 # new feature: pollute
11 #
12 # Revision 1.5 2004/07/26 16:11:58 joko
13 # updated pod
14 # included more complete list of flash event-handlers
15 # fixed substitution regex #1: now using spaces around function names
16 #
17 # Revision 1.4 2004/07/26 13:51:54 joko
18 # updated pod
19 #
20 # Revision 1.3 2004/07/23 12:56:07 joko
21 # updated pod
22 #
23 # Revision 1.2 2004/07/23 12:24:52 joko
24 # pod
25 #
26 # Revision 1.1 2004/07/23 12:13:14 joko
27 # initial commit
28 #
29
30 =pod
31
32 fluscate - The Flash Obfuscator
33
34 This software is Copyright (C) 2004 Andreas Motl
35 Ideas and MacOS X Application by Holger Marseille
36
37 This program is free software; you can redistribute it and/or
38 modify it under the terms of the GNU General Public License
39 as published by the Free Software Foundation; either version 2
40 of the License, or (at your option) any later version.
41
42 This program is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
46
47 You should have received a copy of the GNU General Public License
48 along with this program; if not, write to the Free Software
49 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50
51 =cut
52
53
54 =pod
55
56 =head1 Features
57
58
59 =head2 Obfuscation
60
61 See ASO Pro: http://www.genable.com/aso/preview.html
62 fluscate implements a subset of these features plus some others.
63
64 =head2 Symbols
65
66 =head3 Functions
67
68 fluscate handles two different styles of function declarations:
69
70 1. "Normal" ones, e.g.
71 function mp3Player ('arg1', 'arg2')
72
73 2. There may be "stacked" function declarations, e.g.
74 push 'mp3Player'
75 function ()
76
77 =head2 Pollute
78
79 Some flash-disassemblers might croak when inserting the following code
80 after a/each "constants"-declaration:
81
82 push 0
83 ls:
84 dup
85 trace
86 branchIfTrue ls
87
88 Needs testing!
89
90 =head2 Random
91
92 Instead of using '-1', '-2', '-3', etc., this option creates randomized numbers
93 as symbol replacements.
94
95 =head2 Undo
96
97 fluscate now has "undo"-functionality which can revert symbol replacements.
98 First, use "fluscate -m -s" (memorize+save switches) to store your metadata and
99 "fluscate -m -l -u" (memorize+load+undo switches) to make things undone.
100
101 =head2 Interactive mode
102
103 Can ask you about each symbol whether to replace it. Use "-i -f file.flm".
104
105
106 =head1 Dependencies
107
108 "flasm" is required to disassemble swf files, see http://www.nowrap.de/flasm.html
109 ACKs go to Igor Kogan.
110
111
112 =head1 Usage
113
114 =head2 General
115
116 Please type "fluscate --help" to get more information about command-line parameters.
117
118 =head2 Semantic use:
119
120 =head3 win32
121
122 #> flasm.exe -d puzzle.swf > puzzle.flm
123 #> cat puzzle.flm | perl fluscate.pl > puzzle_fusc.flm
124 #> flasm.exe -a puzzle_fusc.flm
125
126 =head3 *nix
127
128 #> ./flasm -d puzzle.swf > puzzle.flm
129 #> cat puzzle.flm | ./fluscate.pl > puzzle_fusc.flm
130 #> ./flasm -a puzzle_fusc.flm
131
132
133 =head1 Development
134
135 =head2 Todo
136
137 - provide list of flash event handler names to exclude from symbol replacement
138 - include list of ->keywords from:
139 http://www.macromedia.com/support/flash/action_scripts/actionscript_dictionary/
140
141 =head2 Wishlist
142
143 - what about other symbols beside "function"s? (e.g. variables) (->mode)
144 - replace symbols in multiple files (->multifile)
145 - more symbol-replacement-modes:
146 normal, random, random-alphanumeric (e.g. ahjit, twobc, plodf), wordlist, etc.
147
148 =head2 Notes
149
150 - no function may be called "Initialize", rename it to (e.g.) "Initialize2", reassembling will not work otherwise
151 (doesn't matter when obfuscating since function names will be replaced of course)
152 - function names seem to be/work case insensitive (shuffle <-> Shuffle)
153 - successfully tested with http://download.macromedia.com/pub/flash/showme/win/puzzle.zip
154 - make sure -1, -2, -3, .... gets replaced with '-1', '-2', '-3', ...
155 - there are multiple caller lines: callFunction, callMethod; do we have to take special care to methods?
156 - "getMember" and "getVariable" also do function calls!
157 - there are reserved function names which must not be replaced! (-> event handlers, e.g. "onPress")
158
159
160 =head1 Links
161
162 =head2 ActionScript Decompilers / Disassemblers
163
164 Flasm:
165 http://www.nowrap.de/flasm.html
166 http://www.opaque.net/~dave/flasm/
167 Flare: http://www.nowrap.de/flare.html
168 Sothink SWF Decompiler: http://www.srctec.com/flashdecompiler/
169 Imperator FLA: http://www.ave-imperator.com/
170 SWF Decompiler: http://www.19.5degs.com/swfdecompiler.php
171 Gordon: http://www.futurecandy.com/
172
173 =head2 ActionScript Editors & Co.
174
175 URL Action Editor and Actionscript Viewer:
176 http://www.buraks.com/
177 http://voisen.org/archives/2003/02/uae_303_and_asv_309.php
178 SE|PY ActionScript Editor: http://www.sephiroth.it/python/sepy.php
179
180 =head2 Obfuscators
181
182 ASO Pro (ActionScript Obfuscator Pro): http://www.genable.com/aso/preview.html
183 SWOB (swf obfuscator): http://home.byu.net/jtb64/Swob.htm
184 OBFU - A Flash Actionscript obfuscator: http://opaque.net/~dave/obfu/
185
186 =head2 Misc
187
188 ActionScript Protection:
189 http://www.as-protect.com/
190 http://www.quasimondo.com/archives/000377.php
191 Developer's SWF Guardian: http://anyrd.anyorganization.com/
192 Password Busting / SWF Protections: http://www.searchlores.org/cinix_fla.htm
193
194 =head2 Off-Topic
195
196 =head3 XML
197
198 XPath for Actionscript and other stuff: http://www.xfactorstudio.com/Actionscript/
199 XMLRPC Flash Libraries for ActionScript 2.0: http://xmlrpcflash.sourceforge.net/
200
201 =head3 Marshalling / AMF (Flash Remoting protocol)
202
203 AMFPHP - Flash Remoting for PHP: http://www.amfphp.org/
204 AMF::Perl - Flash Remoting in Perl and Python: http://simonf.com/amfperl/
205 SerializerClass: http://sourceforge.net/projects/serializerclass/
206
207 =head3 Misc
208
209 PEAR::SWF - Read and write SWF head tag: http://www.sephiroth.it/test/php/SWF/
210 Convert videos to flv:
211 http://ffmpeg.sourceforge.net/
212 http://www.videohelp.com/tools?tool=263
213 Flash-CMS: http://www.lachoseinteractive.net/fr/produits/alahup/
214
215 =cut
216
217
218 use strict;
219 use warnings;
220
221 use Getopt::Long;
222 use Storable;
223 use Data::Dumper;
224 use Term::ReadKey;
225
226 my $VERSION = "0.10";
227
228 my $regex = {
229 'function' => 'function(?:2|)\s(.+?)\s\(.*?\)',
230 'constants' => 'constants',
231 'call' => '(?:callFunction|callMethod|getMember|getVariable)',
232 'function_stacked' => 'function(?:2|)\s\s\(.*?\)',
233 'push' => 'push\s\'(.+?)\'',
234 };
235 my @symbols;
236 my $symbols_table;
237 my @lines;
238 my $options;
239
240 sub read_options {
241 GetOptions(
242 "pollute" => \$options->{pollute},
243 "help" => \$options->{help},
244 "version" => \$options->{version},
245 "random" => \$options->{random},
246 "memorize" => \$options->{memorize},
247 "load" => \$options->{load},
248 "save" => \$options->{save},
249 "undo" => \$options->{undo},
250 "interactive" => \$options->{interactive},
251 "file=s" => \$options->{file},
252 );
253 }
254
255 sub scan_symbols {
256 my @symbols_events = qw(
257 onDragOut
258 onDragOver
259 onKeyUp
260 onKeyDown
261 onKillFocus
262 onPress
263 onRelease
264 onReleaseOutside
265 onRollOut
266 onRollOver
267 onSetFocus
268 onActivity
269 onStatus
270 onSelect
271 onData
272 onLoad
273 allowDomain
274 allowInsecureDomain
275 onMouseDown
276 onMouseMove
277 onMouseUp
278 onMouseWheel
279 onEnterFrame
280 onUnload
281 onLoadComplete
282 onLoadError
283 onLoadInit
284 onLoadProgress
285 onLoadStart
286 onID3
287 onSoundComplete
288 onResize
289 onChanged
290 onScroller
291 );
292
293 my $counter = 0;
294 foreach (@lines) {
295
296 # trim newlines
297 #chomp;
298 my $symbol;
299
300 # check for all "function" / "function2" symbols and ...
301 if (m/$regex->{function}/) {
302 # ... remember them
303 $symbol = $1;
304
305 } elsif (m/$regex->{function_stacked}/) {
306 if ($lines[$counter - 1] =~ m/$regex->{push}/) {
307 $symbol = $1;
308 }
309 }
310
311 if ($symbol and not grep(/$symbol/, @symbols_events)) {
312 push @symbols, $symbol;
313 }
314
315 $counter++;
316
317 }
318
319 }
320
321 sub scramble_symbols {
322 if ($options->{random}) {
323 #my $range = $#symbols;
324 #my $range = 7;
325 my $range = 10000;
326 my $rndmem = {};
327 foreach (@symbols) {
328 shuffle:
329 my $rnd = -int(rand($range) + 1);
330 goto shuffle if ($rndmem->{$rnd});
331 $symbols_table->{$_} = $rnd;
332 $rndmem->{$rnd}++;
333 }
334 } else {
335 my $symbol_counter = -1;
336 foreach (@symbols) {
337 $symbols_table->{$_} = $symbol_counter;
338 $symbol_counter--;
339 }
340 }
341 }
342
343 sub select_symbols {
344 print STDERR "Please answer with y/n to select symbols for replacement:", "\n";
345 ReadMode 3;
346 foreach (keys %$symbols_table) {
347 print STDERR $_, ": ";
348 getkey:
349 my $key = ReadKey(0) || "";
350 goto getkey if ($key !~ m/[yn]/i);
351 print STDERR $key, "\n";
352 delete $symbols_table->{$_} if ($key =~ m/n/i);
353 }
354 ReadMode 0;
355 }
356
357 # 2. step through all symbols found and replace them
358 sub obfuscate {
359
360 # 1st stage: symbol replacement
361 foreach my $symbol (keys %{$symbols_table}) {
362 my $symbol_new = $symbols_table->{$symbol};
363 my $line_counter = 0;
364 foreach (@lines) {
365
366 # function declarations; single quotes might not be there!
367 if (m/$regex->{function}/) {
368 s/\s'*$symbol'*\s/ '$symbol_new' /i;
369
370 # "constants"-line at begin of each block; single quotes should already be there
371 } elsif (m/$regex->{constants}/) {
372 s/'$symbol'/'$symbol_new'/i;
373
374 # function calls; replace inside predecessor line of calling-lines
375 } elsif (m/$regex->{call}/) {
376 $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_new'/i;
377
378 # function declarations; name of function is pushed on stack one line before!
379 } elsif (m/$regex->{function_stacked}/) {
380 $lines[$line_counter - 1] =~ s/'$symbol'/'$symbol_new'/i;
381 }
382
383 $line_counter++;
384
385 }
386 }
387
388 # 2nd stage: pollute & Co.
389 if ($options->{pollute}) {
390 foreach (@lines) {
391 if (m/$regex->{constants}/) {
392 my $inject = qq(
393 push 0
394 ls:
395 dup
396 trace
397 branchIfTrue ls
398
399 );
400 $_ .= $inject;
401 }
402 }
403 }
404
405 }
406
407 sub usage {
408 print "fluscate - The Flash Obfuscator (v$VERSION)", "\n";
409 if (not $options->{version}) {
410 print <<USAGE;
411 [-p|--pollute] Pollute code by inserting snippet making life harder for disassemblers
412 [-h|--help] This text
413 [-v|--version] Show version information only
414 [-m|--memorize] Enable "memorize"-mode: can load and save symbol replacement metadata
415 [-l|--load] Load symbol replacement table from file
416 [-s|--save] Save symbol replacement table to file
417 [-u|--undo] Replaces obfuscated symbols with original ones; valid only with "memorize" and "load"
418 [-f|--file] Specify path to file for interactive mode
419 USAGE
420 };
421 }
422
423 sub main {
424
425 # basic option handling
426 read_options();
427 #print Dumper($options);
428 if ($options->{help} || $options->{version}) {
429 usage();
430 exit;
431 }
432 if ($options->{interactive} and not -z STDIN) {
433 print "Can not switch to interactive mode while reading from STDIN, please specify file with '-f'.", "\n";
434 exit;
435 }
436
437 if ($options->{file}) {
438 # read flasm code from file
439 if (!open(FH, $options->{file})) {
440 print "Could not open file '$options->{file}'!", "\n";
441 exit;
442 }
443 @lines = <FH>;
444 close(FH);
445 } else {
446 # read flasm code from STDIN
447 @lines = <STDIN>;
448 close(STDIN);
449 }
450
451 # symbol stuff (build/load/save)
452 my $file = "fluscate.syms";
453 if ($options->{memorize} and $options->{load}) {
454 # load
455 $symbols_table = retrieve($file);
456 if ($options->{undo}) {
457 %$symbols_table = reverse %$symbols_table;
458 }
459 } else {
460 # build
461 scan_symbols();
462 scramble_symbols();
463 # save
464 if ($options->{memorize} and $options->{save}) {
465 store($symbols_table, $file);
466 }
467 }
468
469 if ($options->{interactive}) {
470 select_symbols();
471 }
472 #print Dumper($symbols_table); exit;
473
474 # replacements
475 obfuscate();
476 # write all stuff to STDOUT
477 print STDOUT @lines;
478 }
479
480 main();
481
482 1;
483 __END__

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed