swf ファイルの中身を書き換えて実行する方法

FFDec というすごいツール

JPEXS Free Flash Decompiler - Opensource SWF decompiler and editor

このソフトを使うと、swfファイルの読み込み、中身の書き換えまで全部できちゃう。それでいて完全無料(オープンソース)。良い時代になったものですね!!

たとえば以下のソースコードを swf ファイルにコンパイルする

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    
    public class Main extends Sprite 
    {
        
        public function Main() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
        }
        
    }
    
}

コンパイルしてできた swf ファイルを FFDec で開くとこのように ソースコード/中間言語を並べて見ることができる

f:id:castaneai:20171009174638p:plain

中間言語の説明がすぐに見れてすごい

中間言語の行にカーソルを合わせると、すぐ下に命令の説明が表示されるので、元々知らなくてもある程度はすぐに理解できる。これすごい。 特に、説明文にあるスタックの状況表示が Before → After の形式で簡潔に書かれているのが非常に良い。

f:id:castaneai:20171009174845p:plain

対応するソースコードがすぐに見れてすごい

下の動画のように、ソースコード(or 中間言語)の行を選択すると、対応する中間言語(or ソースコード)に自動的にジャンプする。 ソースコードと中間言語の対応関係がすぐにわかって非常に良い。

f:id:castaneai:20171009175341g:plain

その場ですぐに書き換えできてすごい

Edit P-Code ボタンを押すとその場で中間言語を書き換えできる。 Saveするとすぐに左のソースコードにも反映されるので、自分が書いた中間言語が正しいかどうか、すぐにチェックできる。

f:id:castaneai:20171009175658p:plain

そして、FFDecのメニューにある Save ボタンで 即座に swfファイルに変更を反映できる。非常に良い

f:id:castaneai:20171009175814p:plain

Webブラウザで見ている swf を書き換える

Webページにすでに埋め込んでいる swf ファイルの動作を変更したいこともあるかもしれない。 そういった場合は、その swf ファイルをローカルに保存して、サーバーから来る swf ファイルを置換して差し替えればよい

Windows であれば Fiddler を使うと簡単である。

次のサイトに書いてある Auto responder をつかって特定のswfファイルをローカルで変更したものに差し替えればよい。

qiita.com

中間言語 (P-Code) のリファレンスが見たい

Adobeが提供しているリファレンスがある。なぜPDFファイル…って思ったけど中身はまぁ見やすい。

ActionScript Virtual Machine 2 (AVM2) Overview - Adobe

特定の値をブラウザ側のFlashPlayerに表示させる方法

swfファイルを書き換えながら実行していると、処理のある時点での値を見たい、ということがよくある。 その場合は throw でエラーとして投げる のが簡単で良かった

中間言語の throw の説明は次の通り、スタックの一番上にあるものを throw するだけ、というシンプルな機能。

f:id:castaneai:20171009182717p:plain

たとえば、レジスタ1に格納されている値を表示したい場合は、次の2行で済む。すごい楽!

getlocal_1
throw

throw はブラウザのFlashPlayerでも表示される

ブラウザ上でのFlash Playerであっても、デバッグ用のPlayerを入れることでエラーを表示させることができる。

たとえば Chrome だと次のサイトに方法がのっている。

Google Chrome での Flash Player コンテンツデバッガの有効化

throw "hello world!"; とすると、次のようにFlash Player側でエラーダイアログが出る。スタックトレースも出る。すごい!

f:id:castaneai:20171009183033p:plain

printデバッグ的な手法として trace() 関数 というのもあるが、この関数はReleaseビルドされていると表示されなかったりするらしく、ブラウザ上で実行しているswfでは見えないこともあったため自分は採用しなかった。

ただ、throw には欠点もあって、プログラムがその時点で完全に止まってしまう ので、該当箇所のデバッグが完了したら throw はちゃんと消しておく。

まとめ

  • FFDec すごい
  • Fiddler すごい
  • 実行中の値を見るには、throw を使うと楽

参考サイト