====== SWF9Tools wiki page ======
This page describes tools being used to help construct a SWF9 disassembler. This involves tools to analyze the instruction set of the new Flash 9 virtual machine (AVS2).
A disassembler is being written in C++ by Asger Alstrup. The tools below help to extract the binary output of the Flex compiler and compare two code fragments differentially.
A partial list of opcodes we have discovered is listed here [[SWF9Opcodes]], however most of the new information is going straight into the disassembler program code.
== Utilities ==
=== SWF Uncompressor ===
The following small utility written in Java will uncompress a swf file and extract a given instance of a tag. It takes input from stdin and writes to stdout
[[unzip.java]]
=== Tag Extractor ===
This utility extracts a tag with a given code from a swf file. If there is more than one tag with the desired code, the second command line arg says which tag to extract.
[[etag.java]]
=== Binary Diff Workflow script ===
This script (runs in Cygwin on a Windows box) will take a source file which contains two Javascript programs, for which you want to examine the binary differences in the compiled output.
Let us say you wanted to compare the compiled output of these two programs:
package
{
var foo:Number = 0;
}
================
package
{
var foo:Number = 1;
}
You would place the two programs in a file with that separator shown, and the workflow script "doit", below, will take that and compile the two programs separately, extract the SWF9 code block(s) from the compiled swf files, and produce a binary diff of the output.
The output looks like [[Image:Swfdiff.png|SWF9 Diff]]
This script assumes that the ExamDiff application is installed as show, and that the Flex compiler is installed in the indicated path as well. The "unzip" and "etag" java utilities listed above are also required to be in the current working directory.
==== doit ====
#!/usr/bin/bash
./splitfile $@
flex="/Program Files/Macromedia/Flex Builder 2 Alpha 1/Flex Framework 2 Alpha 1"
java -Xms96m -Xmx384m -Dsun.io.useCanonCaches=false -jar "${flex}/lib/mxmlc.jar" -flexlib "${flex}/frameworks/" a.as
java -Xms96m -Xmx384m -Dsun.io.useCanonCaches=false -jar "${flex}/lib/mxmlc.jar" -flexlib "${flex}/frameworks/" b.as
#PREFIX=`echo "$@" | sed -e "s/\(.*\)[.]as/\1/g"`
#SWF=${PREFIX}.swf
java -cp . unzip < a.swf > tags
java -cp . etag < tags 52 0 > a.tag52
java -cp . etag < tags 4c 0 > a.tag4c
java -cp . unzip < b.swf > tags
java -cp . etag < tags 52 0 > b.tag52
java -cp . etag < tags 4c 0 > b.tag4c
# Compare files
"/cygdrive/c/Program Files/ExamDiff Pro/ExamDiff" a.tag52 b.tag52 /o:cmp.html /html
echo "<table border=1 width=\"100%\">
<tr><td width=\"50%\">
" > out.html
echo "<pre>" >> out.html
echo "
<b>a.as:</b>" >> out.html
cat a.as | sed 's/</\</g;s/>/\>/g;s/&/&/g;' - >> out.html
echo "</pre>
</td><td width=\"50%\">
<pre><b>b.as:</b>" >> out.html
cat b.as | sed 's/</\</g;s/>/\>/g;s/&/&/g;' - >> out.html
echo "</pre>
</td>
</tr>
</table>" >> out.html
tail +7 cmp.html >> out.html
echo "result in out.html"
The steps are:
==== splitfile ====
First, a small PERL program splits a source file into two halves, at the boundary "================".
**splitfile**
#!/usr/bin/perl
open(F1, ">a.as");
open(F2, ">b.as");
$a = 0;
while (<>) {
if ($_ =~ "================") {
$a = 1;
} elsif ($a eq 0) {
print F1 $_;
} else {
print F2 $_;
}
}
==== Further steps ====
Once the source file has been split, the two halves are compiled separately with Flex's Javascript compiler.
The output swf files are then passed through the unzip decompressor and then the first instance of tag 0x52 is extracted. This seems to be the tag which contains the AVM2 instructions, at least for small source files. Larger MXML files compile into what looks like two 0x52 tags, with one being a small preamble, and the bulk of the app in the second tag. There are also tag 0x45 and 0x4C which seem to contain some declarations or AVM2 file format codes.
Let's collect the info discovered here: [[SWF9Opcodes]]
==== Alternative to ExamDiff ====
You can also use a slightly modified version of HexDump.java found at http://david.tribble.com/src/java/tribble/util/HexDump.java
with this doit.sh script:
#!/usr/bin/bash
./splitfile $@
flex="/Program Files/Macromedia/Flex Builder 2 Alpha 1/Flex Framework 2 Alpha 1"
java -Xms96m -Xmx384m -Dsun.io.useCanonCaches=false -jar "${flex}/lib/mxmlc.jar" -flexlib "${flex}/frameworks/" a.as
java -Xms96m -Xmx384m -Dsun.io.useCanonCaches=false -jar "${flex}/lib/mxmlc.jar" -flexlib "${flex}/frameworks/" b.as
#PREFIX=`echo "$@" | sed -e "s/\(.*\)[.]as/\1/g"`
#SWF=${PREFIX}.swf
java -cp . unzip < a.swf > tags
java -cp . etag < tags 52 0 > a.tag52
java -cp . etag < tags 4c 0 > a.tag4c
java -cp . unzip < b.swf > tags
java -cp . etag < tags 52 0 > b.tag52
java -cp . etag < tags 4c 0 > b.tag4c
# Dump hex as ascii
java -cp . HexDump a.tag52 > a.tag52hex
java -cp . HexDump b.tag52 > b.tag52hex
# Compare files
diff -y a.tag52hex b.tag52hex > out.txt