[SWF-convert] PHPを使ってSWF情報の取得

2016年5月3日

PHP swf テクノロジー プログラミング

SWF変換を行う前にSWFのSDKを熟読する必要がある。 Adobeサイトで公開されている事は知っているが、今までまともに読んだことが無かった。 ググってみると、偶然に知り合ったyoyaさんのサイトが山のように出てくる。 どうやら、最近まあまあ流行っているらしいFlash変換エンジンの技術の入り口に立てたようである。

SWFデータのdump

yoyaさんのブログを見ると載っているソースコードを利用して、local環境でSWFファイルの内容をdumpして見てみたいと思う。 ライブラリと実行プログラムの2つが必要なので、下記を作成

dump.php

yoyaさんのソースですが、冒頭の箇所はswfファイル指定できるように改造しています。 <?php /** * reference : http://labs.gree.jp/blog/2010/08/631/ * write : yoya * [sample] * php dump.php [target-swf-file(*hoge.swf)] **/ if(!$argv[1]){ echo "error".PHP_EOL; exit(); } $swfFile = $argv[1]; require_once "BitReader.php"; $swfdata = file_get_contents($swfFile); $reader = new BitReader; $reader->input($swfdata); /* SWF Header */ echo 'Signature: '.$reader->getData(3).PHP_EOL; echo 'Version: '.$reader->getUI8().PHP_EOL; echo 'FileLength: '.$reader->getUI32LE().PHP_EOL; echo 'FrameSize: '.PHP_EOL; $NBits = $reader->getUIBits(5); echo "\tXmin: ".($reader->getUIBits($NBits) / 20).PHP_EOL; echo "\tXmax: ".($reader->getUIBits($NBits) / 20).PHP_EOL; echo "\tYmin: ".($reader->getUIBits($NBits) / 20).PHP_EOL; echo "\tYmax: ".($reader->getUIBits($NBits) / 20).PHP_EOL; $reader->byteAlign(); echo 'FrameRate: '.($reader->getUI16LE() / 0x100).PHP_EOL; echo 'FrameCount: '.$reader->getUI16LE().PHP_EOL; /* SWF Tags */ echo 'Tag:'.PHP_EOL; while (true) { $tagAndLength = $reader->getUI16LE(); $type = $tagAndLength >> 6; $length = $tagAndLength & 0x3f; if ($length == 0x3f) { $length = $reader->getUI32LE(); } echo "\ttype: $type length: $length".PHP_EOL; $contents = $reader->getData($length); if ($type == 0) { // END Tag break; } } exit(0);

BitReader.php

yoyaさんのライブラリをそのまま掲載しています。 SWFバイナリ編集のススメ第一回 <?php class BitReader { var $_data; // input_data var $_byte_offset; var $_bit_offset; function input($data) { $this->_data = $data; $this->_byte_offset = 0; $this->_bit_offset = 0; } function byteAlign() { if ($this->_bit_offset > 0) { $this->_byte_offset ++; $this->_bit_offset = 0; } } function getData($length) { $this->byteAlign(); $data = substr($this->_data, $this->_byte_offset, $length); $data_len = strlen($data); $this->_byte_offset += $data_len; return $data; } function getUI8() { $this->byteAlign(); $value = @ord($this->_data{$this->_byte_offset}); $this->_byte_offset += 1; return $value; } function getUI16LE() { $this->byteAlign(); $ret = @unpack('v', substr($this->_data, $this->_byte_offset, 2)); $this->_byte_offset += 2; return $ret[1]; } function getUI32LE() { $this->byteAlign(); $ret = @unpack('V', substr($this->_data, $this->_byte_offset, 4)); $this->_byte_offset += 4; return $ret[1]; } function getUIBit() { $value = @ord($this->_data{$this->_byte_offset}); $value = 1 & ($value >> (7 - $this->_bit_offset)); $this->_bit_offset ++; if (8 <= $this->_bit_offset) { $this->_byte_offset++; $this->_bit_offset = 0; } return $value; } function getUIBits($width) { $value = 0; for ($i = 0 ; $i < $width ; $i++) { $value <<= 1; $value |= $this->getUIBit(); } return $value; } function getImage() { $this->byteAlign(); $ret = @unpack('v', substr($this->_data, $this->_byte_offset, 2)); return $this->_byte_offset; } }

実行

$ php dump.php hoge.swf Signature: FWS Version: 4 FileLength: 7031 FrameSize: Xmin: 0 Xmax: 240 Ymin: 0 Ymax: 240 FrameRate: 10 FrameCount: 40 Tag: type: 9 length: 3 type: 21 length: 2276 type: 2 length: 52 type: 26 length: 10 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 4 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 7 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 26 length: 8 type: 1 length: 0 type: 28 length: 2 type: 21 length: 4090 type: 22 length: 94 type: 26 length: 6 type: 1 length: 0 type: 0 length: 0 Tag-typeがたくさん表示されるが、SWFは上部の固定HEADER部分とコンテンツ内容でもあるTag部分の2ブロック構成なのである。

Header詳細

Headerは非常に簡単な構成で、バイナリファイルとしてもアドレス固定なので、分解はし易いと思います。

Signature

「FWS」と「CWS」の2パターンしか存在せず、分かりやすい情報です。 SWFをパブリッシュする時に「圧縮」オプション設定がされているかどうかの判別用です。 圧縮されている場合はTag部分が圧縮されているので解凍処理を行なってから分析しなければいけないので、CWSは面倒くさいとおぼえておきましょう。 FWS:非圧縮 CWS:圧縮

Version

Flash-version

FileLength

データ長

FrameSize

SWFの画面サイズ
Xmin: 0 Xmax: 240 Ymin: 0 Ymax: 240

FrameRate

指定されたフレームレート

FrameCount

フレーム数

Tags

画像や動画、音声などの情報や、フレームやshape情報、ActionScript情報などが格納されているので、ここの中を整理することで、SWFの解析ができるという事なんですね。

各種link

Adobe SWF SDK Flash SWF バイナリ 他にも有志はたくさんいますが、上記サイトでかなり深いところまで勉強できます。 ※yoyaさんのソースコードにはお世話になっています。

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。