こんにちは。エンジニアの はる です。
今回はちょっとだけマニアックにswfのバイナリ解析方法について書いてみたいと思います。
バイナリって何となく苦手意識のある方も多いかと思いますが、swfのバイナリ解析は数パターンの計算方法だけ抑えてしまえば意外と素直に読み解けてしまいます。
文系大学出身&英語が読めない私でも大丈夫だったので、興味のある方は是非!
まずはバイナリファイルを閲覧・編集できる環境を用意します。
バイナリエディタは様々なものがありますが、自分の環境や好みに合わせて選んでみてください。代表的なものを下記します。
1. バイナリモードでswfファイルを開く vi -b hoge.swf 2. テキスト形式から16進数ダンプ形式に変換 :%!xxd 3. 16進数ダンプ形式からテキスト形式に変換 :%!xxd -r
以上の用意ができたら、解析用SWFをお好きなバイナリエディタで開けば、準備完了です。
SWFのバイナリは下記のような形式で構成されています。
ヘッダ(header、header_movie)に基本情報が格納されており、コンテンツ(tag block)にシェイプやスクリプト等のコンテンツ情報が順々に格納されています。
SWF | |||||||||
---|---|---|---|---|---|---|---|---|---|
header(8バイト) | header_movie(可変長) | tag block(可変長) | tag block(可変長) | .. | end tag | ||||
圧縮有無(3バイト) | SWFのバージョン(1バイト) | ファイルサイズ(4バイト) | ステージの幅・高さ(可変長) | フレームレート(2バイト) | _rootのフレーム数(2バイト) | TLC構造(可変長) | TLC構造(可変長) | ... | 2バイト |
まずはヘッダから読み解いていきましょう。ヘッダから読み取れる情報は以下の6種類です。
上記の情報が格納されているヘッダの構成は以下のようになっています。
ヘッダ | |||||
---|---|---|---|---|---|
header(8バイト) | header_movie(可変長) | ||||
圧縮有無(3バイト) | SWFのバージョン(1バイト) | ファイルサイズ(4バイト) | ステージの幅・高さ(可変長) | フレームレート(2バイト) | _rootのフレーム数(2バイト) |
それでは実際にバイナリを読み解いていきましょう。1バイト目から順に解説していきます。
SWFが圧縮されたものがどうかを判別します。
16進数 | 説明 | 備考 |
---|---|---|
46 57 53 | 圧縮されていないSWF | FWS |
43 57 53 | 圧縮されたSWF(※SWF6以降のみ) | CWS |
CWSの場合、8バイト以降がZLIB圧縮されていることを示しています。この場合、8バイト以降をZLIB展開する必要があります。
※以降の解説はFWSの前提ですすめさせていただきます。
SWFのバージョンが格納されています。以下の例の場合、SWF7形式であることが分かります。
16進数 | 説明 | 備考 |
---|---|---|
07 | SWFのバージョン |
swfファイルのファイルサイズが格納されています。ただし、数値はリトルエンディアン形式で格納されているため、注意が必要です。
16進数 | 説明 | 備考 |
---|---|---|
ec 52 01 00 | ファイルサイズ | リトルエンディアン形式 |
<計算方法>
1. バイトスワップec 52 01 00 | |
逆順 | 00 01 52 ec |
1.の結果(16進数) | 000152ec |
---|---|
10進数 | 86764 |
3. ファイルサイズ = 86764 byte
ステージの幅・高さが格納されています。ただし、数値はRECT構造体で表現されているのに加え、単位はTWIPSのため、注意が必要です。
16進数 | 説明 | 備考 |
---|---|---|
70 00 09 60 00 00 96 00 00 ... | ステージの幅・高さ | RECT構造体で表現。単位はTWIPS(トゥイップ) |
<計算方法>
1. 2進数に変換16進数 | 70 00 09 60 00 00 96 00 |
---|---|
2進数 | 01110000 00000000 00001001 01100000 00000000 00000000 10010110 00000000 00000000 |
2進数 | 01110 |
---|---|
10進数 | 14 |
最初の5ビット | 14ビット | 14ビット | 14ビット | 14ビット | 余りのビット |
---|---|---|---|---|---|
01110 | 000 00000000 000 | 01001 01100000 0 | 0000000 0000000 | 0 10010110 00000 | 000 |
X座標の最小値 | X座標の最大値 | Y座標の最小値 | Y座標の最大値 | 余りのビット | |
---|---|---|---|---|---|
16進数 | 00000000000000 | 01001011000000 | 00000000000000 | 01001011000000 | 000 |
10進数 | 0 | 4800 | 0 | 4800 | - |
X座標の最小値 | X座標の最大値 | Y座標の最小値 | Y座標の最大値 | |
---|---|---|---|---|
twips | 0 | 4800 | 0 | 4800 |
pt | 0 | 240 | 0 | 240 |
6. 縦幅 = 240px, 横幅 = 240px
フレームレートが格納されています。
16進数 | 説明 | 備考 |
---|---|---|
00 08 | フレームレート | 逆順にした結果の1ビット目が整数部、2ビット目が小数部 |
<計算方法>
1. バイトスワップ00 08 | |
逆順 | 08 00 |
1.の結果(16進数) | 08.00 |
---|---|
10進数 | 8.0 |
3. フレームレート = 8 fps
_root(メインタイムライン)のフレーム数が格納されています。
16進数 | 説明 | 備考 |
---|---|---|
14 00 | _rootのフレーム数 | リトルエンディアン形式 |
<計算方法>
1. バイトスワップ14 00 | |
逆順 | 00 14 |
1.の結果(16進数) | 00 14 |
---|---|
10進数 | 20 |
3. _rootのフレーム数 = 20
ヘッダの解析はこれで終了です。SWF解析の肝は次バイトからのコンテンツ(tag block)ですが、これはヘッダ解析で行った計算方法の応用です。
ここから先は、tagの種類毎にtag blockの構造が異なるため、Adobe社が配布している『SWF file format specification』を片手にtagの種類を特定し、それに合った計算方法で解析していくことになります。
今回は一例として、ヘッダに続くtab block(SetBackgroundColor)の解説を行います。
コンテンツ | ||||
---|---|---|---|---|
tag block(可変長) | ... | |||
record header(2バイト) | contents(lengthバイト) | ... | ||
tag(10ビット) | length(6ビット) | contents(lengthバイト) | ... |
コンテンツ | |||||
---|---|---|---|---|---|
tag block(可変長) | ... | ||||
record header(6バイト) | contents(lengthバイト) | ... | |||
tag(10ビット) | 3f(6ビット) | length(4バイト) | contents(lengthバイト) | ... |
16進数 | 43 02 ff ff ff ff 0a 05 00 00 00 69 6e 69 74 00 3f 03 3a 03 00 00 88 06 01 1e 00 00 ... |
---|---|
2進数 | 01000011 00000010 11111111 11111111 11111111 11111111 ... |
16進数 | 説明 | 備考 |
---|---|---|
43 02 | tag(10ビット)+length(6ビット) | リトルエンディアン形式 |
<解析方法>
1. バイトスワップ43 02 | |
逆順 | 02 43 |
16進数 | 02 43 |
---|---|
2進数 | 00000010 01000011 |
tag | length |
---|---|
0000001001 | 000011 |
2進数 | 10進数 | 結果 | |
---|---|---|---|
タグ種別 | 0000001001 | 9 | SetBackgroundColor |
length | 000011 | 3 | 3 |
5. タグ形式2(※「length >= 3f」または特殊形式)の場合、続く4ビットを取得し、lengthを算出する
6. 続くlengthバイトを取得し、『SWF file format specification』の各タグ処理の記載に沿って解析RGB | ff ff ff |
---|
setBackgroundColor(5バイト) | ||
---|---|---|
tag(1バイト) | length(1バイト) | RGB(3バイト) |