記号だけのJavaScriptプログラミングの原理 その2
こんにちは。13日から韓国に来ています。はせがわです。
前回、記号だけのJavaScriptの動作原理を紹介したときは、alert を表示する簡単なコードについて解説しました。
今日は、任意のコードを記号だけで記述する方法について説明します。
前回の方法では、"false","true","[object Object]" という文字列から文字を切り出し、文字列 "alert(1)" を Function コンストラクタに渡して無名関数として実行する、という方法を採りました。
ですので、"alert" 以外の文字を自由に作ることができれば、記号だけで任意のコードを書ける、ということになります。
任意の文字を作り出すということで、最初に思いつくのは String.fromCharCode ですが、記号だけで大文字 C を生成するのはなかなか難しいため、もう少し簡単な方法を考えます。
JavaScriptでは、"\101" のような表記で8進数を使って文字列定数を表現することができますので、これを利用して記号と数値だけで任意の文字を作り出します。
functoin (){ return "\101"; // 文字 'A' を返す関数 }
関数は、前回同様 Number.constructor.constructor すなわち Function コンストラクタを利用し、また "return" という文字は "true" と "undefined" から生成します。これらを組み合わせることで、任意の文字を生成する関数を記号だけで作ることができました。
(0)[ "constructor" ][ "constructor" ] ( (!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ] (!!{}+"")[ 3 ] + // 'e' : "true"[ 3 ] (!!{}+"")[ 0 ] + // 't' : "true"[ 0 ] (!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ] (!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ] ({}.$+"")[ 1 ] + // 'n' : "undefined"[ 1 ] "\"" + // '"' "\\" + // '\' -~[] + // 1 -[] + // 0 -~[] + // 1 "\"" // '"' );
8進数で表現できない文字は、\uXXXX という形式で表現します。
$ = +[]; // $ = 0 $ = { ___ : $++, // 0 __$ : $++, // 1 _$_ : $++, // 2 _$$ : $++, // 3 $__ : $++, // 4 $_$ : $++, // 5 $$_ : $++, // 6 $$$ : $++ // 7 }; (0)[ "constructor" ][ "constructor" ] ( (!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ] (!!{}+"")[ 3 ] + // 'e' : "true"[ 3 ] (!!{}+"")[ 0 ] + // 't' : "true"[ 0 ] (!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ] (!!{}+"")[ 1 ] + // 'r' : "true"[ 1 ] ({}.$+"")[ 1 ] + // 'n' : "undefined"[ 1 ] "\"" + // '"' "\\" + // '\' (!!{}+"")[ 2 ] + // 'u' : "true"[ 0 ] $._$$ + // 3 $.___ + // 0 $.$__ + // 4 $._$_ + // 2 "\"" // '"' );
このような方法を利用することで、あらゆる任意の JavaScript を記号だけにすることができました。
実際に、jjencode が生成するJavaScriptを読み解くとより理解が深まると思います。