Skip to main content

SWF/ABC toolkit for parsing, analyzing, and manipulating Flash files and AVM2 bytecode

Project description

flashkit

Parse, analyze, and manipulate Adobe Flash SWF files and AVM2 bytecode.

Install

pip install -e .

Quick start

from flashkit.workspace import Workspace

ws = Workspace()
ws.load_swf("application.swf")

# Find all classes extending Sprite
for cls in ws.find_classes(extends="Sprite"):
    print(f"{cls.qualified_name}{len(cls.fields)} fields, {len(cls.methods)} methods")

# Inspect a specific class
player = ws.get_class("PlayerManager")
print(player.super_name)    # "EventDispatcher"
print(player.interfaces)    # ["IDisposable", "ITickable"]
print(player.fields[0].name, player.fields[0].type_name)  # "mHealth", "Number"

# Search strings used in bytecode
from flashkit.analysis import StringIndex
strings = StringIndex.from_workspace(ws)
for s in strings.search("config"):
    print(s)

CLI

flashkit info

$ flashkit info application.swf
File: application.swf
  Format:     SWF
  SWF version: 40
  Tags:       142
  ABC blocks: 1
  Classes:    823
  Methods:    14210
  Strings:    35482
  Packages:   47

flashkit classes

flashkit classes app.swf                # all classes
flashkit classes app.swf -s Manager     # search by name
flashkit classes app.swf -p com.game    # filter by package
flashkit classes app.swf -e Sprite      # filter by superclass
flashkit classes app.swf -i             # interfaces only
flashkit classes app.swf -v             # verbose output

flashkit class

$ flashkit class application.swf PlayerManager
PlayerManager
  Package: com.game
  Extends: EventDispatcher
  Implements: IDisposable, ITickable

  Instance Fields (3)
    mHealth: Number
    mName: String
    mLevel: int

  Instance Methods (5)
    init(): void
    get name(): String
    set name(value: String): void
    takeDamage(amount: Number): void
    serialize(): ByteArray

flashkit strings

flashkit strings app.swf                # list all
flashkit strings app.swf -s config      # search
flashkit strings app.swf -s config -v   # with usage locations
flashkit strings app.swf -s "\\d+" -r   # regex
flashkit strings app.swf -c             # classify (URLs, debug)

flashkit tags

flashkit tags app.swf

flashkit disasm

flashkit disasm app.swf --class PlayerManager
flashkit disasm app.swf --method-index 42

flashkit tree

flashkit tree app.swf BaseEntity              # show descendants
flashkit tree app.swf PlayerManager -a        # show ancestors

flashkit callers / flashkit callees

flashkit callers app.swf toString
flashkit callees app.swf PlayerManager.init

flashkit refs

flashkit refs app.swf Point

flashkit packages / flashkit extract / flashkit build

flashkit packages app.swf                     # list packages
flashkit extract app.swf -o ./output          # extract ABC blocks
flashkit build app.swf -o rebuilt.swf         # rebuild (compressed)
flashkit build app.swf -o out.swf -d          # rebuild (decompressed)

Library

Load and query

from flashkit.workspace import Workspace

ws = Workspace()
ws.load_swf("application.swf")
ws.load_swz("module.swz")

print(ws.summary())

cls = ws.get_class("MyClass")
print(cls.name, cls.super_name, cls.interfaces)
print(cls.fields)   # list of FieldInfo
print(cls.methods)  # list of MethodInfoResolved

ws.find_classes(extends="Sprite")
ws.find_classes(package="com.example", is_interface=True)

Analysis

from flashkit.analysis import InheritanceGraph, CallGraph, StringIndex

graph = InheritanceGraph.from_classes(ws.classes)
graph.get_children("BaseEntity")
graph.get_all_parents("MyClass")
graph.get_implementors("ISerializable")

calls = CallGraph.from_workspace(ws)
calls.get_callers("toString")
calls.get_callees("MyClass.init")

strings = StringIndex.from_workspace(ws)
strings.search("config")
strings.url_strings()
strings.classes_using_string("http://example.com")
Parse SWF and ABC directly
from flashkit.swf import parse_swf, TAG_DO_ABC2
from flashkit.abc import parse_abc, serialize_abc

header, tags, version, length = parse_swf(swf_bytes)

for tag in tags:
    if tag.tag_type == TAG_DO_ABC2:
        null_idx = tag.payload.index(0, 4)
        abc = parse_abc(tag.payload[null_idx + 1:])
        print(f"{len(abc.instances)} classes, {len(abc.methods)} methods")

        # Round-trip fidelity: serialize(parse(data)) == data
        assert serialize_abc(abc) == tag.payload[null_idx + 1:]
Build SWF programmatically
from flashkit.abc import AbcBuilder, serialize_abc
from flashkit.swf import SwfBuilder

b = AbcBuilder()
b.simple_class("Player", package="com.game",
               fields=[("hp", "int"), ("name", "String")])
b.script()
abc_bytes = serialize_abc(b.build())

swf = SwfBuilder(version=40, width=800, height=600, fps=30)
swf.add_abc("GameCode", abc_bytes)
swf_bytes = swf.build(compress=True)
Disassemble method bodies
from flashkit.abc import decode_instructions

for body in abc.method_bodies:
    for instr in decode_instructions(body.code):
        print(f"0x{instr.offset:04X}  {instr.mnemonic}  {instr.operands}")

Project structure

flashkit/
  cli/           CLI (one module per command)
  swf/           SWF container (parse, build, tags)
  abc/           AVM2 bytecode (parse, write, disasm, builder)
  info/          Resolved class model (ClassInfo, FieldInfo, MethodInfo)
  workspace/     File loading and class index
  analysis/      Inheritance, call graph, references, strings
  search/        Unified query engine

References

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyflashkit-1.0.0.tar.gz (77.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyflashkit-1.0.0-py3-none-any.whl (71.9 kB view details)

Uploaded Python 3

File details

Details for the file pyflashkit-1.0.0.tar.gz.

File metadata

  • Download URL: pyflashkit-1.0.0.tar.gz
  • Upload date:
  • Size: 77.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyflashkit-1.0.0.tar.gz
Algorithm Hash digest
SHA256 82253952be9daafc269246789c7d4a402be3f1ef7925ff699c60d46862a9c243
MD5 aaef86b3db490da98fc6c612026ce7e8
BLAKE2b-256 fd37f5919efa34f914040f9ceb2ae60d4a04d9cbc2f065a75d1eb43b238a8e46

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyflashkit-1.0.0.tar.gz:

Publisher: release.yml on bitalizer/pyflashkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyflashkit-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: pyflashkit-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 71.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyflashkit-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c0be800e15af6cb705f458c6f215ff15fa053d8206bcd62379b627de29a53365
MD5 2d039074bedf15003304910ef17dcf58
BLAKE2b-256 172109246b107fd6ea4d34de77f7b3de61128242ed5fb4c228c7797908833fa3

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyflashkit-1.0.0-py3-none-any.whl:

Publisher: release.yml on bitalizer/pyflashkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page