You are on page 1of 45

SWF Binary Hacks

~ eval のいばら道 ~

Shibuya.JS Technical Talk#3 – Shibuya.es


竹迫 良範
<takesako@shibuya.pl>
はじめに
2
謝罪
今日 Flex2 SDK を
インストールしたばかりです
嘘言ってたらごめんなさい
3
eval の発音について

 eval イーヴァル の検索結果 約 4 件


 eval イヴァル の検索結果 約 11 件
 eval エヴァル の検索結果 約 12 件

 eval イーバル の検索結果 約 13 件


 eval イバル の検索結果 約 13 件
 eval エバル の検索結果 約 28 件

※ 某 G 調査機関による調べによる
4
JavaScript でフォント名一覧を
取得する 3 つの方法

(1) IE 限定 (2) LiveConnect (3) Flash 利用

TAKESAKO @ Yet another CybozuLabs


http://labs.cybozu.co.jp/blog/takesako/2007/03/javascript_getallfonts.html
(1) Dialog Helper Object でフォント名一覧取得

<OBJECT id="dlgHelper"
CLASSID="clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b"
      width="0px" height="0px"> </OBJECT>

function getAllFontsByDialogHelper() {
var fontslist = '';
try {
for (var i = 1; i < dlgHelper.fonts.count; i++) {
fontslist += dlgHelper.fonts(i) + '\n';
}
}
catch(e) {
fontslist = 'sorry, could not get fonts list.';
}
return fontslist;
}
6
7
※ 動作するブラウザが激しく IE に限定される

8
(2) LiveConnect で Java アプレットを操作

java.awt.GraphicsEnvironment#getAllFonts()

function getAllFontsByLiveConnect() {
var fontslist = '';
try {
var fonts = java.awt.GraphicsEnvironment.
            getLocalGraphicsEnvironment().getAllFonts();
for (var i = 0; i < fonts.length; i++) {
fontslist += fonts[i].getFontName() + '\n';
} LiveConnect
} - Netscape3 以降の仕様( JavaScript1.
catch(e) { 1)
fontslist = 'sorry, could not get fonts list.';
} - Firefox, Opera で動作
return fontslist; Java のオブジェクトを JavaScript から操
} 作
9
LiveConnect とは?

 できること
 Java のオブジェクトを JavaScript から操作できる
 その逆も
 動作環境
 Netscape3 以降( JavaScript1.1 )の仕様
 Firefox, Opera で動作
 使用できる条件
 Java アプレットの実行が許可されているとき

10
(3) Flash の TextField.getFontList() を利用

var user_fonts = TextField.getFontList();

user_fonts.sort();

getURL('javascript:fontList("‘
       + escape(user_fonts)
      + ‘“)’, '_self');

こんな感じで .as ファイルを作って


getFontList.swf を作る
11
でも、いちいち swf ファイルを
作るの面倒だよなぁ…

Flash ( ActionScript )で eval 使えたっけ?


SWF Binary Hacks
~ eval のいばら道 ~

斜め下から始める
初めての Flash
13
FlashProxy.swf で Flash 関数を動的実行

 Collection & Copy - JavaScript 用 Flash プロキ


シ、 Javascript Sound Kit ( id:brazil さん作)
http://d.hatena.ne.jp/brazil/20060726/1153884951
<script type="text/javascript">
Sound.methods = "loadSound start stop getId3 getPan setPan
getTransform setTransform getVolume setVolume getDuration
setDuration getPosition setPosition getBytesLoaded
getBytesTotal".split(" ");

function Sound(){
return new FlashProxy("Sound", Sound.methods);
}
var sound = new Sound();

みたいな感じで JavaScript から Flash の関数を動的に呼び出すことができる 14


FlashProxy.as のソースコード( id:brazil さん)
import flash.external.ExternalInterface;

class FlashProxy{
static var proxy;
var target;

function FlashProxy() {
this.target = new (eval(_root.className));

ExternalInterface.addCallback("dispatch", this, dispatch);


ExternalInterface.addCallback("addListener", this, addListener);
}

function dispatch(prop, args) {


var obj = this.target[prop];
if (obj instanceof Function) {
return obj.apply(this.target, args);

}
return obj;
}

function addListener(event) {
this.target[event] = function(){
ExternalInterface.call("FlashProxy.onTrigger", _root.id, event, arguments);
}
}

static function main(mc) {


proxy = new FlashProxy();
}
} 15
お、 Flash で

16
17
なんか Flash にはいろいろ制限があるみたい
import flash.external.ExternalInterface;

class FlashProxy{
static var proxy;
var target;

function FlashProxy() {
this.target = new (eval(_root.className));

ExternalInterface.addCallback("dispatch", this, dispatch);


ExternalInterface.addCallback("addListener", this, addListener);
}

function dispatch(prop, args) {


var obj = this.target[prop];
この方法だと
if (obj instanceof Function) { TextField.getAllFonts()

return obj.apply(this.target, args);
System.setClipboard みたいな
}
return obj;
スタティック関数の呼び出しができない
} (インスタンスを直接生成できない
function addListener(event) {   abstract クラスのメソッド)
this.target[event] = function(){
ExternalInterface.call("FlashProxy.onTrigger", _root.id, event, arguments);
}
}

static function main(mc) {


proxy = new FlashProxy();
}
} 18
次のバージョンでは eval 自体廃止されちゃうし

19
JavaScript から Flash

スタティック関数を
eval っぽく実行したい!
20
例えば Ruby の場合…

 3つの eval 関数があるのに!

1. ふつうの eval
2. Object#instance_eval
3. Module#module_eval/class_eval

→  空前のメタプログラミング期ブーム
21
それ
Flashy.swf
でできるよ
22
それ Flashy.swf 使えばできるよ

 Javascript から Flash の任意の静的関数を


呼び出すことができる
 <object id=“flashy” data=“Flashy.swf” />

<script language="JavaScript">
var flash = document.getElementById('flashy');
flash.setStatic('flash.system.IME.enabled', true); // IME オン
</script>

Kazuho@Cybozu Labs: JavaScript から Flash の便利な機能を使う方法


http://labs.cybozu.co.jp/blog/kazuho/archives/2007/03/flashy.php
23
Flashy.as のソースコード(奥一穂さん)
package {
import flash.display.*; スタティック関数の呼び出しを動的に
import flash.external.ExternalInterface; (インスタンスを直接生成できない
import flash.utils.getDefinitionByName;
public class Flashy extends Sprite {   abstract クラスのメソッドも呼べる)
public function Flashy() {
ExternalInterface.addCallback("getClass", getClass);
ExternalInterface.addCallback("getStatic", getStatic);
ExternalInterface.addCallback("setStatic", setStatic);
ExternalInterface.addCallback("callStatic", callStatic);
}
public function getClass(expr:String):Object {
return getDefinitionByName(expr);
}
public function getStatic(expr:String):Object {
var m:Object = expr.match(/^(.*)\.(.*?)$/);
return this.getClass(m[1])[m[2]];
}
public function setStatic(expr:String, value:Object):void {
var m:Object = expr.match(/^(.*)\.(.*?)$/);
this.getClass(m[1])[m[2]] = value;
}
public function callStatic(expr:String, args:Array):Object {
var m:Object = expr.match(/^(.*)\.(.*?)$/);
return this.getClass(m[1])[m[2]].apply(m[1], args);
}
}
} 24
Flash の関数を呼ぶだけじゃなく
AS のコードを直接実行してみたい

eval 使えないけど、どうする???
JavaScript で SWF を動的生成すればできる
よ!

<body><embed width="0px" height="0px"


type="application/x-shockwave-flash" flashvars="param=val"
src="data:application/x-shockwave-flash;base64,
Q1dTCbwDAAB42l1SQW/TMBS23a5uu5VtGqqGEFKlTaqE1CbtDmhVFzG1KxoHi
uCCkCbqOm5j5iaR4y7dATEu/AROO8PP4IzEoTvwBzhx4R9wwE7G2mFF8nufv+
/zy3uegexPAO58BmAbgu7mPQDA+61vEIC2dEetF91eZTYRftTS2UHVUypsWVY
cx/V4rx7IsdXY39+37KbVbNY0oxad+4rMan60U3USgy6LqOSh4oFfMTkZBlN1
UK1eu7r0xjScSpFYutRigk2YryKrUW9oI5e2RoGcEOWQMBScEmNnzWqRF9DTm
Jyx2kiQyGtbC6LRKK4Ecw7dYMgqPcFmlWblcKFP2CnFkN1Foc7SbxKjrtNgYo
UycKdU1zTSVol4WWIswulQ8Mhj0pn6p34Qp1csUMOhkhEV3Gb8w8y5IP54Ssb
MOXqWnN3kSY1EMadp248se89q7qVFGKxt/dfra0SPzwHdjV+ZNuigj5dfXhf1
YJOFwKc3KIl+X95/t6nh78Uel5HqcEkFA1/vftCYYY8kmbAG2AB1gC4u/mCgw
9Ulainpfd3lUSjIee5lKLli+bEkocdpVBiyMfd7XIiiK0mcSjDzXQPliet2PC
7cXH/4llG1llqxMzP79SOzdbUtUVS3r9RNb0ipm8e+YpJQxc9YipRvnXcC/RC
5z+RKGZYz26i8CkoYIoyyGK5gmMMQY5jHsIBhEWfXMCphdAej9QxYXhCiQibp
AkQQZiHQCcwXMnP7iYayqFBszO3KBfoxPwYn6CkCOrwaZWqwn4V6333+cLfdX
8nosJ8DJ/iqj6EWIu2V35nbDAzy9qBgD4r2YNUerNkDpL9X4EGyPEPd2DKXLw
/msc7/AuHTEs4="></embed></body>
26
URI data: スキームで GIF 画像を動的に生成

 GIF 画像を base64 でエンコード( RFC2397 )


<img id="icon_here">

<script>
var data = ‘data:image/gif;base64,’+
‘R0lGODlhAAEwAMQAAJ2M5Me98GRK1DoYyYBr3PHv ・・・(中略)・・・
Pe99XO81Y50auc6PBkZEgpzbmt7HJa2I57CffgnMNqmWHAWNBwwGsKp
KsrmJqltOOV69nuYxSkqpoTata18rWtrr1rTIIAQA7';

var icon_elem = document.getElementById("icon_here");


icon_elem.src = data;
</script>

http://www.kawa.net/works/js/data-scheme/base64.html
Firefox, Opera で動作 残念ながら IE では動作しませんが・・・
27
GIF  SWF
28
SWF ファイルフォーマットの仕様書

 Adobe Player Licensing から入手可能


 http://www.adobe.com/licensing/developer/
メールアドレス( Adobe ID )を登録
ライセンスに同意する必要がある
Flash6 以降の情報のみ
 Alexis' SWF Reference
 http://sswf.sourceforge.net/SWFalexref.html
Flash6 以前の情報についても書いてある
 2001 年からの蓄積

29
Alexis' SWF Reference http://sswf.sourceforge.net/SWFalexref.html

: : : : 30
SWF File Header, SWF Tags…
struct swf_header {
unsigned char f_magic[3]; 'FWS' or 'CWS'
unsigned char f_version;
unsigned long f_file_length;
}
struct swf_header_movie {
swf_rect f_frame_size;
unsigned short fixed f_frame_rate;
unsigned short f_frame_count;
};

struct swf_csmtextsettings {
swf_tag f_tag; /* 74 */
unsigned short f_text_id_ref;
unsigned f_use_flag_type : 2;
unsigned f_grid_fit : 3;
unsigned f_reserved : 3;
long float f_thickness;
long float f_sharpness;
unsigned char f_reserved;
}; 31
SWF ファイルを
DIS アセンブル
しながら勉強したい…
32
swfdump コマンドで DIS アセンブル

 SWFTOOLS の swfdump コマンドを使うと


SWF ファイルの内容をダンプすることができる
http://www.swftools.org/documentation.html
> swfdump --full FlashProxy.swf

[HEADER] File version: 8


[HEADER] File is zlib compressed. Ratio: 63%
[HEADER] File size: 796 (Depacked)
[HEADER] Frame rate: 20.000000
[HEADER] Frame count: 1
[HEADER] Movie width: 450.00
[HEADER] Movie height: 325.00
[009] 3 SETBACKGROUNDCOLOR (ff/ff/ff)
[027] 4 DEFINESPRITE defines id 20480
[000] 0 END
[038] 21 EXPORTASSETS
exports 20480 as "__Packages.MTASC"
[03b] 643 DOINITACTION adds information to id 20480
( 206 bytes) action: Constantpool(22 entries)
String:"FlashProxy" String:"_global" String:"target" String:"_root"
String:"className" String:"dispatch" String:"flash" String:"external" 33
swfdump はアクションレコードの抽出が苦手

:
(    8 bytes) action: unknown[8e] (remainder of 8 bytes:"\0\0\0\2)\0p\0")
:

アクションレコードの抽出に失敗 …

orz 34
SWF::Parser (CPAN) なら・・・

 dumpswf.plx

dumpswf.plx Flash.swf > Flash.pl

Flash.swf そのものを生成する
Perl スクリプト「 Flash.pl 」を生成

http://www.nmt.ne.jp/~ysas/butaperl/swf/Parser.sjis.pod.html
http://search.cpan.org/~YSAS/SWF-File/lib/SWF/Parser.pm

35
Sothink SWF Decompiler (試用期間 30 日)

http://www.sothink.com/product/flashdecompiler/ 36
DIS アセンブル結果( Sothink SWF Decompile
r)

37
しかし、
URI データスキームに
埋め込みの SWF は
Flash Player 9
では動かない… orz
Flash Player 8 では動いたのに(><)
38
Flash 上で動く ECMAScript の処理系
があればいいじゃね?

Flash Lite 職人である鴨志田さんに聞いてみると


そういう処理系があるらしい!
40
ScriptEngine.swf の特徴

 バイトコードインタプリタ
 一旦スクリプトをバイトコード的なものに変換してから
独自 VM 上で実行
 ECMA-262 3rd Edition にほぼ準拠
 +いくつかの拡張(コルーチンなど)
ActionScript1 的な感じで記述が可能
 詳しくは Web で
http://www.be-interactive.org/?itemid=6
http://www.be-interactive.org/?itemid=194

41
Xelf (ゼルフ)の開発者 – 新藤さん(高校 3 年生)

名前の由来: Flex の逆で xleF


http://bcnranking.jp/it_junior/21-00012742.html

ゲームを製作しやすくしよう
プロジェクトの一環とし
て、 ECMAScript + α の
処理系を Flash(AS) 上に
実装
期待 age

42
まとめ
43
Flash で eval っぽいことをするには?

 JavaScript でできないことをプラグインで
 Java アプレット + LiveConnect ( IE では使えない)
 Flash 使えばいろいろできる(クロスブラウザ)
 JavaScript から Flash のコードを実行したい
 ActionScript で任意の関数を呼ぶ方法
FlashProxy.swf ( id:brazil さん)
Flashy.swf (奥一穂さん)
 SWF ファイルの動的生成( URI データスキーム)
Flash Player 9 以降ではもう使えない技… orz
 Flash 上で動く ECMAScript + α の処理系あるよ
 これ最強! 新藤さん GJ
44
ご清聴ありがとうございました

Special Thanks to: CybozuLabs 奥さん、鴨志田さん 45

You might also like