{"id":21483357,"url":"https://github.com/cybershadow/rabcdasm","last_synced_at":"2025-10-11T14:14:10.271Z","repository":{"id":895159,"uuid":"647944","full_name":"CyberShadow/RABCDAsm","owner":"CyberShadow","description":"Robust ABC (ActionScript Bytecode) [Dis-]Assembler","archived":false,"fork":false,"pushed_at":"2023-03-31T23:20:41.000Z","size":452,"stargazers_count":434,"open_issues_count":3,"forks_count":92,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-03-16T22:52:50.416Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://blog.thecybershadow.net/2010/05/05/announcing-rabcdasm/","language":"D","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CyberShadow.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2010-05-05T07:23:23.000Z","updated_at":"2025-02-10T19:49:53.000Z","dependencies_parsed_at":"2023-07-06T17:32:10.477Z","dependency_job_id":null,"html_url":"https://github.com/CyberShadow/RABCDAsm","commit_stats":{"total_commits":330,"total_committers":6,"mean_commits":55.0,"dds":"0.054545454545454564","last_synced_commit":"8ed623a3225ec9947f75f50bc78f5d2412a0802d"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2FRABCDAsm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2FRABCDAsm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2FRABCDAsm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2FRABCDAsm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CyberShadow","download_url":"https://codeload.github.com/CyberShadow/RABCDAsm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244006303,"owners_count":20382444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-23T12:46:34.484Z","updated_at":"2025-10-11T14:14:05.224Z","avatar_url":"https://github.com/CyberShadow.png","language":"D","funding_links":[],"categories":[],"sub_categories":[],"readme":"Robust ABC (ActionScript Bytecode) [Dis-]Assembler\n==================================================\n\n[RABCDAsm][] is a collection of utilities including an ActionScript 3 \nassembler/disassembler, and a few tools to manipulate SWF files. These are:\n\n * `rabcdasm` - ABC disassembler\n * `rabcasm` - ABC assembler\n * `abcexport` - extracts ABC from SWF files\n * `abcreplace` - replaces ABC in SWF files\n * `swfdecompress` - decompresses zlib-compressed SWF files\n * `swf7zcompress` - (re-)compress the contents of a SWF using 7-Zip\n * `swflzmacompress` - compress the contents of a SWF using LZMA\n * `swfbinexport` / `swfbinreplace` - extract/replace contents of binary data \n   tags from SWF files\n\n`abcexport` and `abcreplace` are reimplementations of similar utilities from \nmy [swfutilsex][] Java package, however these work faster as they do not parse \nthe SWF files as deeply.  \n`swfdecompress` is ancillary and is only useful for debugging and studying of \nthe SWF file format, and not required for ABC manipulation. It is functionally \nequivalent to [flasm][]'s `-x` option. If you frequently work on compressed \nSWF files, you may want to decompress them to speed processing up.  \n`swf7zcompress` is an utility to further reduce the size of SWF files. It uses \n[7-Zip][] to compress the data better than the standard zlib library would. It \nrequires that the `7z` command-line program be installed and in `PATH`.  \n`swflzmacompress` compresses SWF files using the [LZMA][] algorithm, support \nfor which was introduced in Flash 11. It will only work with SWF files with \nversion 13 or higher.  \n`swfbinexport` and `swfbinreplace` aid in the manipulation of \n`DefineBinaryData` tags in SWF files (some files may contain nested SWF files \nstored in these tags).\n\n  [RABCDAsm]: http://github.com/CyberShadow/RABCDAsm\n  [swfutilsex]: http://github.com/CyberShadow/swfutilsex\n  [flasm]: http://flasm.sourceforge.net/\n  [7-Zip]: http://www.7-zip.org/\n  [LZMA]: http://en.wikipedia.org/wiki/Lempel-Ziv-Markov_chain_algorithm\n\nMotivation and goals\n--------------------\n\nThis package was created due to lack of similar software out there. \nParticularly, I needed an utility which would allow me to edit ActionScript 3 \nbytecode with the following properties:\n\n 1. Speed. Less waiting means more productivity. `rabcasm` can assemble large \n    projects (\u003e200000 LOC) in under a second on modern machines.\n 2. Comfortably-editable output. Each class is decompiled to its own file, \n    with files arranged in subdirectories representing the package hierarchy. \n    Class files are `#include`d from the main file.\n 3. Most importantly - robustness! If the Adobe AVM can load and run the file, \n    then it must be editable - no matter if the file is obfuscated or \n    otherwise mutilated to prevent reverse-engineering. RABCDAsm achieves this \n    by using a textual representation closer to the ABC file format, rather \n    than to what an ActionScript compiler would generate.\n\nCompiling from source\n---------------------\n\nRABCDAsm is written in the [D programming language, version 2][d2].\n\nAssuming you have [git][] and a D2 compiler, such as [dmd][] or [gdc][] \ninstalled, compiling should be as straight-forward as:\n\n    git clone git://github.com/CyberShadow/RABCDAsm.git\n    cd RABCDAsm\n    dmd -run build_rabcdasm.d\n\nSubstitute `dmd` with `gdmd` if you're using gdc. You can use the `DC` and \n`DCFLAGS` environment variables to override the detected compiler and default \ncompilation flags (`-O -inline`).\n\nTo be able to manipulate SWF files packed with LZMA compression, you'll need \nto have the [liblzma library][] and development files installed on your system.\n\nNote: DMD 2.066 is required for long path support on Windows since RABCDAsm \n1.16.\n\n  [d2]: http://dlang.org/\n  [dmd]: http://www.digitalmars.com/d/download.html\n  [gdc]: http://bitbucket.org/goshawk/gdc/\n  [git]: http://git-scm.com/\n  [liblzma library]: http://tukaani.org/xz/\n\nPre-compiled binaries\n---------------------\n\nYou can find pre-compiled Windows binaries on [my website][downloads]. \nHowever, please don't expect them to be up-to-date with the latest source \nversions.\n\n  [downloads]: http://files.thecybershadow.net/RABCDAsm/\n\nUsage\n-----\n\nTo begin hacking on a SWF file:\n\n    abcexport file.swf\n\nThis will create `file-0.abc` ... `file-N.abc` (often just `file-0.abc`). Each \nfile corresponds to an ABC block inside the SWF file.\n\nTo disassemble one of the `.abc` files:\n\n    rabcdasm file-0.abc\n\nThis will create a `file-0` directory, which will contain `file-0.main.asasm` \n(the main program file) and files for ActionScript scripts, classes, and \norphan and script-level methods.\n\nTo assemble the `.asasm` files back, and update the SWF file:\n\n    rabcasm file-0/file-0.main.asasm\n    abcreplace file.swf 0 file-0/file-0.main.abc\n\nThe second `abcreplace` argument represents the index of the ABC block in the \nSWF file, and corresponds to the number in the filename created by `abcexport`.\n\n`swfbinexport` and `swfbinreplace` are used in the same manner as `abcexport` \nand `abcreplace`.\n\nSyntax\n======\n\nThe syntax of the disassembly was designed to be very simple and allow fast \nand easy parsing. It is a close representation of the `.abc` file format, and \nthus it is somewhat verbose. All constant pool elements (signed/unsigned \nintegers, doubles, strings, namespaces, namespace sets, multinames) are always \n*expanded inline*, for ease of editing. Similarly, classes, instances, methods \nand method bodies are also defined inline, in the context of their \"parent\" \nobject. By-index references of classes and methods (used in the `newclass`, \n`newfunction` and `callstatic` instructions) are represented via \nautomatically-generated unique \"reference strings\", declared as `refid` fields.\n\nIf you haven't yet, I strongly recommend that you look through Adobe's \n[ActionScript Virtual Machine 2 (AVM2) Overview][avm2]. You will most likely \nneed to consult it for the instruction reference anyway (although you can also \nuse [this handy list][avm2i] as well). You will find it difficult to \nunderstand the disassembly without good understanding of concepts such as \nnamespaces and multinames.\n\n  [avm2]: https://www.adobe.com/content/dam/acom/en/devnet/pdf/avm2overview.pdf\n  [avm2i]: https://web.archive.org/web/20160215185222/www.anotherbigidea.com/javaswf/avm2/AVM2Instructions.html\n\nOverview\n--------\n\nIn order to guarantee unambiguity and data preservation, all strings read from \nthe input file - including identifiers (variable/function/class names) - are \nrepresented as string literals. Thus, the syntax does not have any \"reserved \nwords\" or such - an unrecognized word is treated as an error, not as an \nidentifier.\n\nWhitespace (outside string literals, of course) is completely ignored, except \nwhere required to separate words. Comments are Intel-assembler-style: a single \n`;` demarks a comment until the next end-of-line. Control directives (such as \n`#include`) are allowed anywhere where whitespace is allowed.\n\nThe syntax is comprised of hierarchical blocks. Each block contains a number \nof fields - starting with a keyword specifying the field type. A block is \nterminated with the `end` keyword. Some fields contain a limited number of \nparameters, and others are, or contain blocks.\n\nHierarchy\n---------\n\nThe topmost block in the hierarchy is the `program` block. This must be the \nfirst block in the file (thus, `program` must be the first word in the file as \nwell). The `program` block contains `script` fields, and `class` / `method` \nfields for \"orphan\" classes and methods (not owned by other objects in the \nhierarchy). Orphan methods are usually anonymous functions. The file version \nis also specified in the `program` block, using the `minorversion` and \n`majorversion` fields (both unsigned integers).\n\n`script` blocks have one mandatory `sinit` field (the script initialization \nmethod) and `trait` fields.\n\nA \"trait\" can be one of several kinds. The kind is specified right after the \n`trait` keyword, followed by the trait name (a multiname). Following the name \nare the trait fields, varying by trait kind:\n\n * `slot` / `const` : `slotid` (unsigned integer), `type` (multiname), `value`\n * `class` : `slotid`, `class` (the actual class block)\n * `function` : `slotid`, `method` (the actual method block)\n * `method` / `getter` / `setter` : `dispid` (unsigned integer), `method`\n\nAdditionally, all traits may have `flag` fields, describing the trait's \nattributes (`FINAL` / `OVERRIDE` / `METADATA`), and `metadata` blocks.\n\n`metadata` blocks (which are ignored by the AVM) consist of a name string, and \na series of `item` fields - each item having a key and value string.\n\n`class` blocks have mandatory `instance` and `cinit` fields, defining the \nclass instance and the class initializer method respectively. They may also \nhave `trait` fields and a `refid` field (the `refid` field is not part of the \nfile format - it's an unique string to allow referencing the class, see above).\n\n`instance` blocks - always declared inline of their `class` block - must \ncontain one `iinit` field (the instance initializer method), and may contain \none `extends` field (multiname), `implements` fields (multinames), `flag` \nfields (`SEALED` / `FINAL` / `INTERFACE` / `PROTECTEDNS`), one `protectedns` \nfield (namespace), and `trait` fields.\n\n`method` blocks may contain one `name` field (multiname), a `refid` field, \n`param` fields (multinames - this represents the parameter types), one \n`returns` field (multiname), `flag` fields (`NEED_ARGUMENTS` / \n`NEED_ACTIVATION` / `NEED_REST` / `HAS_OPTIONAL` / `SET_DXNS` / \n`HAS_PARAM_NAMES`), `optional` fields (values), `paramname` fields (strings), \nand a `body` field (method body).\n\n`body` blocks - always declared inline of their `method` block - must contain \nthe `maxstack`, `localcount`, `initscopedepth` and `maxscopedepth` fields \n(unsigned integers), and a `code` field. It may also contain `try` and `trait` \nfields.\n\n`code` blocks - always declared inline of their `body` block - are somewhat \ndifferent in syntax from other blocks - mostly in that they may contain \nlabels. Labels follow the most common syntax - a word followed by a `:` \ncharacter, optionally followed by a relative byte offset (in case of pointers \ninside instructions). Multiple instruction arguments are comma-separated. \nInstruction arguments' types depend on the instruction - see the `OpcodeInfo` \narray in `abcfile.d` for a reference.\n\n`try` blocks - always declared inline of their `body` block - represent an \n\"exception\" (try/catch) block. They contain five mandatory fields: `from`, \n`to` and `target` (names of labels representing start and end of the \"try\" \nblock, and start of the \"catch\" block respectively), and `type` and `name` \n(multinames), representing the type and name of the exception variable.\n\nValues have the syntax *type* `(` *value* `)` . *type* can be one of \n`Integer`, `UInteger`, `Double`, `Utf8`, `Namespace`, `PackageNamespace`, \n`PackageInternalNs`, `ProtectedNamespace`, `ExplicitNamespace`, \n`StaticProtectedNs`, `PrivateNamespace`, `True`, `False`, `Null` or \n`Undefined`. The type of the value depends on *type*. Types `True`, `False`, \n`Null` and `Undefined` have no value.\n\nConstants\n---------\n\nMultinames have the syntax *type* `(` *parameters* `)` . *type* can be one of \n`QName` / `QNameA`, `RTQName` / `RTQNameA`, `RTQNameL` / `RTQNameLA`, \n`Multiname` / `MultinameA`, `MultinameL` / `MultinameLA`, or `TypeName`. \n*parameters* depends on *type*:\n\n * `QName` / `QNameA` `(` *namespace* `,` *string* `)`\n * `RTQName` / `RTQNameA` `(` *string* `)`\n * `RTQNameL` / `RTQNameLA` `(` `)`\n * `Multiname` / `MultinameA` `(` *string* `,` *namespace-set* `)`\n * `MultinameL` / `MultinameLA` `(` *namespace-set* `)`\n * `TypeName` `(` *multiname* `\u003c` *multiname [* `,` *multiname ... ]* `\u003e` `)`\n\nNamespace sets have the syntax `[` *[ namespace [* `,` *namespace ... ] ]* `]` \n(that is, a comma-separated list of namespaces in square brackets). Empty \nnamespace sets can be specified using `[]`.\n\nNamespaces have the syntax *type* `(` *string [* `,` *string ]* `)` . The \nfirst string indicates the namespace name. In the case that there are multiple \ndistinct namespaces with the same type and name (as `PrivateNamespace` \nnamespaces usually are), a second parameter may be present to uniquely \ndistinguish them. Internally (the ABC file format), namespaces are \ndistinguished by their numerical index. When disassembling, `rabcdasm` will \nattempt to assign descriptive labels to homonym namespaces based on their \ncontext.\n\nStrings have a syntax similar to C string literals. Strings start and end with \na `\"`. Supported escape sequences (a backslash followed by a letter) are `\\n` \n(generates ASCII 0x0A), `\\r` (ASCII 0x0D), and `\\x` followed by two \nhexadecimal digits, which inserts the ASCII character with that code. Any \nother characters following a backslash generate that character - thus, you can \nescape backslashes using `\\\\` and double quotes using `\\\"`. When decompiling, \nhigh-ASCII characters (usually UTF-8) are not escaped - if you see gibberish \ninstead of international text, configure your editor to open the files in \nUTF-8 encoding.\n\nAdditionally, constant pool types (signed/unsigned integers, doubles, strings, \nnamespaces, namespace sets and multinames) may also have the value `null` \n(which represents the index 0 in the ABC file). Note that `null` is \nconceptually different from zero, an empty string or empty namespace set.\n\nMacros\n------\n\nRABCDAsm has some basic macro-like capabilities, controlled by directives and \nvariables. These bear some similarity to the C preprocessor, however these are \nprocessed in-loop rather than as a separate pre-processing step.\n\n### Directives\n\nDirectives start with a `#`, followed by a word identifying the directive:\n\n  * `#include` *string* - inserts the contents of the file by the specified \n    filename inline. Functionally equivalent to `#mixin #get` *string* , but \n    faster.\n  * `#mixin` *string* - inserts the contents of the specified string inline. \n    Not very useful on its own.\n  * `#call` *string* `(` *[ string [* `,` *string ... ] ]* `)` - same as \n    `#mixin`, however it additionally sets the special variables `$1`, `$2` \n    etc. to the contents of the specified arguments. When the end of the \n    inserted string is reached, the old values of `$1`, `$2` etc. are restored.\n  * `#get` *string* - inserts **a string containing** the contents of the file \n    by the specified filename inline. Similar to #include, but it inserts a \n    string (surrounded by `\"` etc.) instead.\n  * `#set` *word* *string* - assigns the contents of the string to the \n    variable *word*.\n  * `#unset` *word* - deletes the variable *word*.\n  * `#privatens` *number* *string* - deprecated, currently ignored.\n  * `#version` specifies the syntax version of the disassembly. Newer RABCDAsm \n    versions may emit disassembly output that is not backwards-compatible, but \n    should still understand older disassemblies. The versions are:\n     1. The first version.\n     2. Introduced in v1.11 to work around error in ABC format specification.\n     3. Introduced in v1.12 to support multiple non-private namespaces with \n        the same name. This is the current version.\n\n### Variables\n\nVariables are manipulated with the `#set` and `#unset` directives, and can be \ninstantiated in two ways:\n\n  1. `$`*name* - this inserts the contents of the variable inline. Note that \n     although variables are defined using a string syntax, they are not \n     inserted as a string using this syntax. Thus, the code:\n\n        #set str \"Hello, world!\"\n        ...\n        pushstring $str\n\n     will expand to `pushstring Hello, world!`, which will result in an error.\n     To correct the problem, add escaped quotes around the variable contents\n     ( `#set str \"\\\"Hello, world!\\\"\"` ), or use the second syntax:\n  \n  2. `$\"`*name*`\"` - this inserts a string containing the contents of the \n     variable inline. This syntax also works for `#call` arguments (e.g. \n     `$\"1\"`).\n\n### Example\n\nHere's an example of how to use the above features to create a macro which \nlogs a string literal and the contents of a register:\n\n    #set log \"\n        findpropstrict      QName(PackageNamespace(\\\"\\\"), \\\"log\\\")\n        pushstring          $\\\"1\\\"\n        getlocal            $2\n        callpropvoid        QName(PackageNamespace(\\\"\\\"), \\\"log\\\"), 2\n    \"\n    \n    ; ...\n    \n    pushbyte 2\n    pushbyte 2\n    add_i\n    setlocal1\n    #call $\"log\"(\"two plus two equals\", \"1\")\n     \nHighlighting\n------------\n\nIncluded with the project is the file `asasm.hrc`, a simple syntax definition \nfor the [Colorer take5][] syntax highlighting library. It should be \nstraight-forward to adapt it to other syntax highlighting systems.\n\n  [Colorer take5]: http://colorer.sourceforge.net/\n\nHacking\n=======\n\nABC is internally represented in two forms. The `ABCFile` class stores the raw \ndata structures, as they appear in the binary file. `ASProgram` uses pointers \ninstead of indexes, allowing easy manipulation without having to worry about \nrecord order or constant pools. Conversion between various states is done as \nfollows:\n\n                                 file.abc\n                                   |  ^\n                  ------ ABCReader |  | ABCWriter ----\n                 /                 v  |               \\\n                /                ABCFile               \\\n               /                   |  ^                 \\\n        rabcdasm---------- ABCtoAS |  | AStoABC --------rabcasm\n               \\                   v  |                 /\n                \\               ASProgram              /\n                 \\                 |  ^               /\n                  --- Disassembler |  | Assembler ----\n                                   v  |\n                                file.asasm\n\n`AStoABC` will rebuild the constant pools, in a manner similar to Adobe's \ncompilers (reverse-sorted by reference count). The exact order will almost \nsurely be different, however.\n\nShould you need to write an utility to manipulate ABC, you can use the \nexisting code to load the file to either an `ABCFile` or `ASProgram` instance, \nand perform the necessary manipulations using those classes.\n\nTips\n====\n\nThe following tips come from the author's experience and may be useful for \nRABCDAsm users.\n\n1. Once you have disassembled a SWF file you intend to modify, you should \n   immediately add the directory to a distributed source control system, such \n   as [Git][] or [Mercurial][]. This will allow you to easily track and undo \n   your changes, and easily merge your changes with new versions of SWF files.\n\n  [Git]: http://git-scm.com/\n  [Mercurial]: http://mercurial.selenic.com/\n\n2. If you plan on making non-trivial changes to SWF files, you should install \n   the [debug Flash Player][]. This will allow you to see validation and \n   run-time error messages, instead of simply getting an empty window.\n\n  [debug Flash Player]: http://www.adobe.com/support/flashplayer/downloads.html\n\n3. The [Fiddler][] Web Debugging Proxy can be very useful for analyzing \n   websites with SWF content. The following script fragment (which is to be \n   placed in the `OnBeforeResponse` function) will automatically save all SWF \n   files while preserving the directory structure.\n\n        if (oSession.oResponse.headers.ExistsAndContains(\"Content-Type\",\n                \"application/x-shockwave-flash\")) {\n            // Set desired path here\n            var path:String = \"C:\\\\Temp\\\\FiddlerCapture\\\\\" +\n                oSession.host + oSession.PathAndQuery;\n            if (path.Contains('?'))\n                path = path.Substring(0, path.IndexOf('?'));\n            var dir:String = Path.GetDirectoryName(path);\n            if (!Directory.Exists(dir))\n                Directory.CreateDirectory(dir);\n            oSession.utilDecodeResponse();\n            oSession.SaveResponseBody(path);\n        }\n\n   A more robust version of the above snippet is available as a Fiddler plugin \n   [here][FiddlerAutoCapture].\n\n   Once you have edited a SWF file, you can use Fiddler's [AutoResponder][] to \n   replace the original file with your modified version.\n\n  [Fiddler]: http://www.fiddler2.com/fiddler2/\n  [AutoResponder]: http://www.fiddler2.com/fiddler2/help/AutoResponder.asp\n  [FiddlerAutoCapture]: https://github.com/CyberShadow/FiddlerAutoCapture\n\nLimitations\n===========\n\n* None known.\n\nLicense\n=======\n\nRABCDAsm is distributed under the terms of the GPL v3 or later, with the \nexception of `murmurhash2a.d`, `zlibx.d` and LZMA components, which are in the \npublic domain, and `asasm.hrc`, which is tri-licensed under the MPL 1.1/GPL \n2.0/LGPL 2.1. The full text of the GNU General Public License can be found in \nthe file `COPYING`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcybershadow%2Frabcdasm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcybershadow%2Frabcdasm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcybershadow%2Frabcdasm/lists"}