4 Commits
3 changed files with 73 additions and 60 deletions
+45 -42
View File
@@ -1,7 +1,7 @@
Robust ABC (ActionScript Bytecode) [Dis-]Assembler
==================================================
[RABCDAsm][] is a collection of utilities including an ActionScript
[RABCDAsm][] is a collection of utilities including an ActionScript 3
assembler/disassembler, and a few tools to manipulate SWF files.
These are:
@@ -31,7 +31,7 @@ Motivation and goals
--------------------
This package was created due to lack of similar software out there.
Particularly, I needed an utility which would allow me to edit ActionScript
Particularly, I needed an utility which would allow me to edit ActionScript 3
bytecode with the following properties:
1. Speed. Less waiting means more productivity. `rabcasm` can assemble large
@@ -102,6 +102,9 @@ To assemble the `.asasm` files back, and update the SWF file:
rabcasm file0/file0.main.asasm
abcreplace file0.swf 0 file0/file0.main.abc
The second `abcreplace` argument represents the index of the ABC block in the
SWF file, and corresponds to the number in the filename created by `abcexport`.
Syntax
======
@@ -311,20 +314,20 @@ be instantiated in two ways:
Here's an example of how to use the above features to create a macro which
logs a string literal and the contents of a register:
#set log "
findpropstrict QName(PackageNamespace(\"\"), \"log\")
pushstring $\"1\"
getlocal $2
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
"
; ...
pushbyte 2
pushbyte 2
add_i
setlocal1
#call $"log"("two plus two equals", "1")
#set log "
findpropstrict QName(PackageNamespace(\"\"), \"log\")
pushstring $\"1\"
getlocal $2
callpropvoid QName(PackageNamespace(\"\"), \"log\"), 2
"
; ...
pushbyte 2
pushbyte 2
add_i
setlocal1
#call $"log"("two plus two equals", "1")
Highlighting
------------
@@ -344,19 +347,19 @@ instead of indexes, allowing easy manipulation without having to worry about
record order or constant pools. Conversion between various states is done as
follows:
file.abc
| ^
ABCReader | | ABCWriter
v |
ABCFile
| ^
ABCtoAS | | AStoABC
v |
ASProgram
| ^
Disassembler | | Assembler
v |
file.asasm
file.abc
| ^
------ ABCReader | | ABCWriter ----
/ v | \
/ ABCFile \
/ | ^ \
rabcdasm---------- ABCtoAS | | AStoABC --------rabcasm
\ v | /
\ ASProgram /
\ | ^ /
--- Disassembler | | Assembler ----
v |
file.asasm
`AStoABC` will rebuild the constant pools, in a manner similar to Adobe's
compilers (reverse-sorted by reference count). The exact order will almost
@@ -394,19 +397,19 @@ RABCDAsm users.
placed in the `OnBeforeResponse` function) will automatically save all SWF
files while preserving the directory structure.
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
"application/x-shockwave-flash")) {
// Set desired path here
var path:String = "C:\\Temp\\FiddlerCapture\\" +
oSession.host + oSession.PathAndQuery;
if (path.Contains('?'))
path = path.Substring(0, path.IndexOf('?'));
var dir:String = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
oSession.utilDecodeResponse();
oSession.SaveResponseBody(path);
}
if (oSession.oResponse.headers.ExistsAndContains("Content-Type",
"application/x-shockwave-flash")) {
// Set desired path here
var path:String = "C:\\Temp\\FiddlerCapture\\" +
oSession.host + oSession.PathAndQuery;
if (path.Contains('?'))
path = path.Substring(0, path.IndexOf('?'));
var dir:String = Path.GetDirectoryName(path);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
oSession.utilDecodeResponse();
oSession.SaveResponseBody(path);
}
Once you have edited a SWF file, you can use Fiddler's [AutoResponder][] to
replace the original file with your modified version.
+22 -16
View File
@@ -21,6 +21,7 @@ module abcexport;
import std.file;
import std.path;
import std.string;
import std.stdio;
import swffile;
void main(string[] args)
@@ -28,22 +29,27 @@ void main(string[] args)
if (args.length == 1)
throw new Exception("No file specified");
foreach (arg; args[1..$])
{
scope swf = SWFFile.read(cast(ubyte[])read(arg));
uint count;
foreach (ref tag; swf.tags)
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
{
ubyte[] abc;
if (tag.type == TagType.DoABC)
abc = tag.data;
else
try
{
scope swf = SWFFile.read(cast(ubyte[])read(arg));
uint count = 0;
foreach (ref tag; swf.tags)
if ((tag.type == TagType.DoABC || tag.type == TagType.DoABC2))
{
auto p = tag.data.ptr+4; // skip flags
while (*p++) {} // skip name
abc = tag.data[p-tag.data.ptr..$];
ubyte[] abc;
if (tag.type == TagType.DoABC)
abc = tag.data;
else
{
auto p = tag.data.ptr+4; // skip flags
while (*p++) {} // skip name
abc = tag.data[p-tag.data.ptr..$];
}
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
}
write(getName(arg) ~ .toString(count++) ~ ".abc", abc);
}
}
if (count == 0)
throw new Exception("No DoABC tags found");
}
catch (Object o)
writefln("Error while processing %s: %s", arg, o);
}
+6 -2
View File
@@ -109,6 +109,10 @@ final class RefBuilder : ASTraitsVisitor
{
foreach (i, ref v; as.scripts)
addMethod(v.sinit, "script" ~ .toString(i) ~ "_sinit");
foreach (vclass; as.orphanClasses)
addClass(vclass, "orphan");
foreach (method; as.orphanMethods)
addMethod(method, "orphan");
super.run();
}
@@ -257,9 +261,9 @@ final class RefBuilder : ASTraitsVisitor
return uniqueName;
}
void addClass(ASProgram.Class vclass)
void addClass(ASProgram.Class vclass, string field = null)
{
addObject(vclass, classByName, string.init);
addObject(vclass, classByName, field);
addMethod(vclass.cinit, "cinit");
addMethod(vclass.instance.iinit, "iinit");
}