SWFバイナリ編集のススメ第一回

こんにちは。メディア開発部のよやと申します。バイナリ編集エンジニアです。

はじめに

GREE では携帯向けコンテンツに Flash Lite を利用していますが、Lite には様々な制限(*1)があり、SWF(スウィフ) の動的生成技術を活用しています。

ツール(ming, swfmill, swftools, etc...)を用いた SWF 生成の記事は世間に溢れてますので、SWFバイナリの生編集をテーマに記事を何回かに分けて進めようと思います。
ツールを使う場合でも何かしら問題に遭遇した際の一助になるかもしれません。

第一回の当記事は、SWF仕様書の読み方ガイドです。

SWF仕様

Adobe公式の SWF仕様書は一般公開されています。 英語です。

理解の助けになる日本語のサイトを列挙します。

以下の SWFファイル(orz.swf)をサンプルとして、公式仕様書を読み進めます。

SWFヘッダ

仕様書の SWF Structure Summary - The SWF header で以下のように定義されています。

hexdump コマンドで実際の SWFファイルの先頭を16進数で表示して仕様書と比較してみます。

初めの8bytes
  • 先頭3bytesの FWS は Signature。一文字目が F なので圧縮なし。
  • 4byte目は 0x04 で、SWF の version
  • 5~8byte目の 77 1b 00 00 は FileLength。SWF は基本 LittleEndian なのでbyte列を逆方向に読んで、0x1b77 = 7031 これが SWFファイルのファイル長に相当します。

合ってますね。
といった具合に読み解けます。

RECT

9byte目以降は少々やっかいです。

ここで出てくる RECT(Rectangle Record)は仕様書の Basic Data Types で定義されます。

初めの5bitにフィールド長が入っていて、その長さのフィールドが4つ後ろに続きます。
具体的には、

この中の

のbyte列が対応します。bit で分けると以下のようになります。

初めの 5 bits を読むと 14 という値が入っているので、その後ろに 14bits ずつ Xmin, Xmax, Ymin, Ymax の4つの値が並ぶという訳です。

各々の値は次のようになります。

ここで出てくる twips は長さの単位で(本来は DPI 依存ですが)、SWF では logical pixel(100% 表示での pixel) の 1/20 の長さと定められています。つまり twips の値を 20 で割ると丁度 pixel 値になります。

ヘッダの残り

丁度二行目(offset 0x10)から続いています。

  • FrameRate の 00 0a は LittleEndian なのでひっくり返して 0a 00 。8.8 fixed number (8bit整数.8bit少数 の固定小数点)なので、10.00 [frames/秒] (*2)
  • FrameCount の 28 00 も LittleEndian なので 0x0028 => 40 frames (=コマ数)

以上で、SWF ヘッダが一通り読めました。

  • イメージ図


SWFタグ (short形式)

SWFヘッダの後ろに SWFタグのリストが続きます。(図は仕様書から抜粋)

仕様書の SWF Structure Summary - SWF file structure に以下の定義があります。

SWFタグはSWFヘッダの後ろに続くので、先程の FrameCount の続きから読んでいきます。

タグの先頭2bytes にタグの種類とタグの長さが入っていますが、LittleEndian と bit packing の合わせ技なので、読むのに少しコツがいります。

まず。43 02 を逆方向に読んで 0243 として、これを bit に分解します。

初めの10bits がタグの種類(type)で、続く 6bits が(TagCodeAndLengthを除いた)タグの長さです。

tag type の 9 と SetBackgroundColor の対応は仕様書(swf_file_format_spec_v10.pdf)をテキスト検索して確認してください。

以上から、SetBackgroundColor のタグは以下の byte列になる事が分かります。

背景が (R,G,B) = (0xff, 0xff, 0xff)= 白色となります。

  • イメージ図

SWFタグ (long形式)

6 bits では111111 = 0x3f = 63 byte までしか表現できないので、この 6 bits に 111111 = 0x3f が入っている時は、long 形式が適用されます。

画像や動画等のマルチメディアコンテンツを含むタグはこの形式を利用します。

先程のタグ(SetBackgroundColor)の後ろに丁度、JPEG画像のタグが並んでいるので、それを例にします。

先程の続きなので以下のbyte列が相当します。

まず TagCodeAndLength の 2 byte を読みだします。

Length が 0x3f なので、その後ろに続く 4bytes を本当の Length として読み出します。

  • イメージ図

PHPで読みだし

以上で SWF のヘッダとタグの読み方を一通り説明しました。
参考までに今まで説明した処理を行う PHP プログラムを以下に付けます。

swfdump

BitReader

実行結果

次回予告

次回は SWFバイナリの編集まで話しを進める予定です。
それでは失礼いたします。

*1: Lite の制限については、こちらのURLが分かり易いです => http://d.hatena.ne.jp/hanageman/20080922

*2: 2 byte まとめて一つの値として読んだ上で 0x100 で割ると楽です。