言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

Tamarin でアセンブル/逆アセンブル

Flex SDKTamarin を使って Flash バイトコードを abcasm でアセンブルしたり abcdump で逆アセンブルする方法を書きます。私は Mac で作業しましたが、他でも大体同じだと思います。

出来る事

良くわからない事。

  • ABC ファイルを SWF に埋込んでブラウザから実行する方法。(知ってたら教えてください!)
    • 追記: asc の swf オプションで abc の代わりに swf が作られますが、これでも abc から swf を作れるわけじゃないです。
    • java -jar $FLEX/lib/asc.jar -swf test,400,300,30 hello.as

使うもの

  • Tamarin : abcasm, abcdump(avmshell) を利用。書いている時点でリビジョン 711。
    • 2009年7月現在 avmshell の動作が変なので、そこだけ 2008 年末のバージョンを使う
  • Flex SDK 3 : asc を利用
  • Java

ツールの説明

改めて書いてみると強烈にややこしい。。。

Flex SDK 3 の準備

http://www.adobe.com/products/flex/flexdownloads/ からダウンロードするだけです。

$ export FLEX=(flex_sdk_3 の場所)

環境変数をセットしておきます。

Tamarin の準備

Tamarin のビルドに必要なコマンドラインを書きます。大体 https://developer.mozilla.org/ja/Tamarin_Build_Documentation の解説通りですが、hg update を使って古いバージョンで作業する所だけ違います。

$ hg clone http://hg.mozilla.org/tamarin-central/
$ cd tamarin-central
$ hg update -r 703 # 作業ディレクトリをリビジョン 703 に戻す。
$ mkdir objdir-release
$ cd objdir-release
$ python ../configure.py --enable-shell
$ make
$ ./objdir-release/shell/avmshell # 動作確認
avmplus shell 1.0 build cyclone

動作確認します。ActionScriptFlexコンパイルして Tamarin で実行します。

$ echo 'print("hello, world")' > hello.as
$ java -jar $FLEX/lib/asc.jar hello.as
$ ./objdir-release/shell/avmshell hello.abc
hello, world

abcdump の準備

abcdump は ActionScript で書かれているので、一旦 abc にコンパイルして先ほど作った avmshell 経由で動かします。abcdump.abc の作成に必要なコマンドラインを書きます。

$ java -jar $FLEX/lib/asc.jar -import core/builtin.abc shell/ByteArray.as 
$ java -jar $FLEX/lib/asc.jar -import core/builtin.abc -import shell/ByteArray.abc utils/abcdump.as 

util/abcdump.abc に出来上がります。以下動作確認です。abc ファイルの名前は -- の後ろに書きます。

$ ./objdir-release/shell/avmshell utils/abcdump.abc -- hello.abc > hello2.abs

abcasm の準備

折角なので、出来上がった hello2.abs をもう一度コンパイルしてみます。ただし、このファイルには前後に余計なコメントが付いているので、編集してアセンブラだけにしてください。こんな風になると思います。

$ cat hello2.abs 
function script0$init():*       /* disp_id 0*/
{
  // local_count=2 max_scope=1 max_stack=2 code_len=15
  0         getlocal0     
  1         pushscope     
  2         findpropstrict      print
  4         pushstring          "hello, world"
  6         callproperty        print (1)
  9         coerce_a      
  10        setlocal1     
  11        getlocal1     
  12        returnvalue   
  13        kill                1
}

次に、リビジョン 703 には abcasm が含まれていないので再びソースを 711 に戻します。

$ hg udpate -r 711

いよいよコンパイルして実行です。abcasm はシェルスクリプトで、内部で java を読んでいます。

$ ./utils/abcasm/abcasm.sh hello2.abs 
hello2.abs
$ ./objdir-release/shell/avmshell hello2.abc 
hello, world

また、utils/abcasm/ ディレクトリに面白いアセンブルソースのサンプルが色々あるので、バイトコードの練習にいいと思います。

Mercurial コマンド豆知識

Mercurial コマンド hg は馴染みが無いのでいくつかコマンドをメモります。

  • hg clone : サーバーからレポジトリをコピーする。
  • hg pull : サーバーから作業ディレクトリに最新のレポジトリを取り込む
  • hg update -r リビジョン : 作業ディレクトリをあるリビジョンに移動する。
  • hg log : 作業ログ
  • hg status : レポジトリから変更されたファイルを表示
  • hg identify -i : 作業レポジトリのリビジョン番号を表示