Transcript Document

SWF Binary Hacks
~ evalのいばら道 ~
Shibuya.JS Technical Talk#3 – Shibuya.es
竹迫 良範
<[email protected]>
はじめに
2
謝罪
今日 Flex2 SDK を
インストールしたばかりです
嘘言ってたらごめんなさい
3
eval の発音について
eval イーヴァル
eval イヴァル
eval エヴァル
の検索結果 約 4 件
の検索結果 約 11 件
の検索結果 約 12 件
eval イーバル
eval イバル
eval エバル
の検索結果 約 13 件
の検索結果 約 13 件
の検索結果 約 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
catch(e) {
- Netscape3以降の仕様(JavaScript1.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でも
evalできる?
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);
}
return obj;
}
や
System.setClipboard みたいな
スタティック関数の呼び出しができない
(インスタンスを直接生成できない
abstract クラスのメソッド)
function addListener(event) {
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;
abstract クラスのメソッドも呼べる)
public class Flashy extends Sprite {
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
unsigned char
unsigned long
}
f_magic[3]; 'FWS' or 'CWS'
f_version;
f_file_length;
struct swf_header_movie {
swf_rect
unsigned short fixed
unsigned short
};
f_frame_size;
f_frame_rate;
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]
[HEADER]
[HEADER]
[HEADER]
[HEADER]
[HEADER]
[HEADER]
[009]
[027]
[000]
[038]
File version: 8
File is zlib compressed. Ratio: 63%
File size: 796 (Depacked)
Frame rate: 20.000000
Frame count: 1
Movie width: 450.00
Movie height: 325.00
3 SETBACKGROUNDCOLOR (ff/ff/ff)
4 DEFINESPRITE defines id 20480
0
END
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 Decompiler)
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
Flashy.swf
(id:brazilさん)
(奥一穂さん)
SWFファイルの動的生成(URIデータスキーム)
Flash Player 9 以降ではもう使えない技…orz
Flash上で動く ECMAScript+αの処理系あるよ
これ最強! 新藤さんGJ
44
ご清聴ありがとうございました
Special Thanks to: CybozuLabs 奥さん、鴨志田さん
45