Overriding private methods in ActionScript, the hard way
July 10, 2009 at 10:49 AM | ActionScript | View CommentsAre you working with a proprietary .swc
? Does it have lots of bugs? Did the authors, in all their infinite wisdom, decide to hide those bugs in private
methods, so you stand no chance of being able to fix them? Well, friend, let me show you how to fix that.
Step 0: Uncompressing the swc
/swf
First make a backup copy of the library (just incase you botch something):
$ cp binary_library.swc binary_library_backup.swc
Then unzip the swc
file like you would any other zip
file:
$ unzip binary_library.swc
This will extract, among other things, a library.swf
file.
This library.swf
will probably be compressed, so you've also got to uncompress it. To do that, I like to use SWFTOOLS:
$ swfcombine -d library.swf -o uncompressed_library.swf
Step 1: Dumping the ABC
Now that you've got a nice uncompressed swf
, it's time to decompile it. To do this, you can use or my patched version of swfdump.
$ java -jar swfdump.jar -abc library.swf > library.abc
Step 2: Finding the multiname pool entry
Now pull up library.abc
in your favorite text editor and search for the method's name under the "MultiName Constant Pool Entries" heading. For example, if the method's name is "priv", you'll be looking for something like this:
6 MultiName Constant Pool Entries
07 01 04 private:priv <-- here
07 02 06 :void
07 02 09 :pub
07 02 01 :A
07 02 10 :Object
Note that the method may be prefixed with a namespace:
6 MultiName Constant Pool Entries
...
07 01 04 com.foo.ClassName:methodName
Technical details: The first of those three bytes refers to the entry kind. The second is a one-based index into the list of namespaces (which are listed under "Namespace Constant Pool Entries") and the third is a one-based index into the list of string constants ("String Constant Pool Entries"). For all the details, see section "4.3 Constant Pool", "4.4.3 Multiname" and "4.1 Primitive data types" (for the definition of u30 – making sure to read the paragraph witch mentions that it uses little-endian byte order) in AVM 2 Machine Overview.
Note: If you're dealing with a large .swf
, there may be four or even five bytes:
07 01 B9 03 :methodName
Don't worry – that's ok!
Make note of the bytes (in this case, 07 01 04
) which prefix the method, then move on to step 3.
Step 3: Find a similar method
Next thing you've got to do is find a method of the same class which has a pubic (or protected) scope. In this case, we have a method called 'pub':
6 MultiName Constant Pool Entries
07 01 04 private:priv
07 02 06 :void
07 02 09 :pub <-- here
Make note here of the byte (02
): that tells the AVM which namespace the method belongs to.
Step 4: Hex edit the uncompressed library
Now, pull up your favorite hex editor and open up the uncompressed_library.swf
, which you created in step 0. Now, remember those bytes which prefix the method name? Search for them (and make sure you only find one instance of them – if there are multiple instances of them, expand the search to take into account the next few bytes (so, in this case, 07 01 04 07 02 06
). Now, once you've found them, simply replace the second byte (in this case 01
) with the second byte of the similar method:
07 01 04
is replaced with:
07 02 04
Step 5: Checking that you got it right
To check and make sure that you got it right, run the swfutil
again, then check the output:
$ java -jar swfdump.jar -abc uncompressed_library.swc
You should see your change reflected in the MultiName constant pool entries:
6 MultiName Constant Pool Entries
07 02 04 :priv
07 02 06 :void
Note that the method is no longer prefixed with 'private' (or whatever the original namespace was).
Now, if the utility crashes, or something else doesn't work, go back and try again – you'll get it eventually.
Step 6: Putting it all back together
You're almost done! All that's left to do is put everything back into the .swc
.
First, copy uncompressed_library.swf
over top of library.swf
:
$ cp library_uncompressed.swf library.swf
Or, optionally, you can re-compress it:
$ swfcombine -z -d library_uncompressed.swf -o library.swf
Then put library.swf
back into the swc
:
$ zip binary_library.swc library.swf
Finally try linking against it to see if everything worked!
See also:
- erlswf – has a much prettier ABC dump.
- AVM 2 Machine Overview – keep this under your pillow.