JSFuck

JSFuckはJavaScriptのサブセットとして考案された難解プログラミング言語。[・]・(・)・!・+の6文字のみコードを書く。

JavaScriptの様々な言語仕様を利用することで、非常に冗長なコードになってしまうものの上記6文字だけでJavaScriptの全機能を使用できるJane Bailey/The Daily WTF: "Bidding on Security". http://thedailywtf.com/articles/bidding-on-security。

名前はBrainfuckに由来するが、独自のコンパイラやインタプリタを必要とするBrainfuckとは異なり、JSFuckはあくまでもJavaScriptの言語仕様に基づいているためJavaScriptの処理系（WebブラウザやJavaScriptエンジン）で動作する。

 歴史 
2009年7月にHasegawa YosukeがJavaScriptを[]()!+,\"$.:;_{}~=の18文字に変換するWebアプリケーションを作った。

2010年1月には、sla.ckers.orgというWebアプリケーションセキュリティサイトの「Obfuscation」フォーラムで非公式の競争が開催され、文字数を当時必要最小限だと思われていた8文字（[]()!+,/）に抑える方法が考案された。その後、どうにか , と / を使わないようにできないか模索され、同年3月にはJS-NoAlnumと呼ばれる現在の6文字で表現されるエンコーダーができた。同年11月にハセガワはJSF*ckと呼ばれる6文字で表現されるエンコーダーを完成させた。2012年には、Martin Kleppe が"jsfuck"と名前をつけたプロジェクトをGitHub上で公開した。そしてJSFuck.comというサイトでエンコーダーの実装を公開している。

JSFuckはマルウェアをウェブサイトにクロスサイトスクリプティング (XSS)等によって埋め込むことにも使われたことがあるhttps://arstechnica.com/security/2016/02/ebay-has-no-plans-to-fix-severe-bug-that-allows-malware-distribution/ Ars Technica: Ebay has no plans to fix severe bug that allows malware distribution。他の潜在的な使用方法としては、難読化がある。よく使われるJavaScriptライブラリであるjQueryも、6文字で完全に置き換えられたことがあるhttps://github.com/fasttime/jquery-screwed jQuery JavaScript library made of only six different characters: ! ( ) + [ ]。

 変換の手順 

JSFuckは非常に冗長である。JavaScriptではalert("Hello World!")としてポップアップを開くであろうコードは21字である。しかし、同じことをJSFuckでしようとすると22948字にもなる。いくつかの文字はJSFuckで表現しようとすると1000文字を超える。この節はどうやって文字を生成することができるのか説明する。
 数字 
0は+[]によって作られる。ここで、[]は空の配列であり、+はである。ここに型変換が働いて、は0とみなされる単項和演算子 + を付けられた項は暗黙的に数値に型変換される。配列を数値に変換するとその文字列の表す数値が得られる（参照：）が、[]（空配列）の場合得られる値 +[] はゼロである。。

1は+!![] か +!+[]で、論理値true (JSFuckでは!![]か!+[]として表現される)が数字の1に変換されたものである[]（空配列）は論理値 true を持つと定義されている（すなわちtruthyである（参照：））ため、これに二重not演算した !![] はtrueであり、それを数値に型変換した +!![] は1になる。。

2から9については、（前述の通り1）をその回数だけ繰り返し、それをで連結すれば良い。これを踏まえると2は!![]+!![]や!+[]+!+[]と書くことができる。

2桁以上の場合は、1桁ずつ数字として配列に詰めたあと、それを1要素連結すればよい。例として"10"は[1] + [0]と書き換えることができる。前述の0と1の作り方を適用すると、これは[+!+[]]+[+[]]となる。数値を返したい場合は、頭にをつける(この例では10 = +([+!+[]]+[+[]]))

 文字 

JSFuckではいくつかの文字は論理値や"NaN"、"undefined"から添字付き(角括弧の中に数字が入ったもの)で取り出すことになる。他の文字を生成するためにさらなるトリックが存在する。を数字に型変換すると、となり、を簡単に取り出すことができるようになるhttp://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html "Brainfuck Beware: JavaScript is after you!"。下に記したのは最もシンプルにプリミティブな値を作るコードである。

(ただし、幾つかのコンパイラでは!+[]が警告されるため!![]に統一している。)

 値  JSFuck false  ![] true  !![] NaN  +[![]] undefined  [] Infinity  +(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])

 例:"a"の生成 
 "a": 文字列"false"から取ることにする。"false"の2文字目は"a"である。これは
 "false"[1]としてアクセスできる。"false"はfalse+[]から作ることができる。すなわち、falseと空の配列を足すことになる。
 (false+[])[1]: falseは![]から生成できるので(論理否定を空の配列に適用する)
 (![]+[])[1]: 1は数字であるので、これを+trueで置き換えると
 (![]+[])[+true]: そしてfalseは![]でtrueは!![]なので
 (![]+[])[+!![]] - これで"a"を返す。
JavaScriptで実際に試してみると、alert((![]+[])[+!![]])とalert("a")は同じ出力であるAdapted from: https://esolangs.org/wiki/JSFuck。

 他の生成 
FunctionのコンストラクタはJavaScriptとして有効なコードを実行することができるので、alert(1)はFunction("alert(1)")()と同じである。Functionのコンストラクタは、[]["at"] (Array.prototype.at) のように標準の関数のconstructorプロパティから取り出すことができる。このことを踏まえると、alert(1)は[]["at"]["constructor"]("alert(1)")()と書き換えることができる。

 文字表 

文字を作ることができる一番短いコードを下に記した。他の文字も生成できるがおそらくもっと長くなるだろう。

(ただし、幾つかのコンパイラでは!+[]が警告されるため!![]に統一している。)
 文字  JSFuck  意味インデックスは0始まりであるため、何文字目か指定する添字は1引いた値になる。 +  (+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]])+[])[!![]+!![]]  1e+100 の3文字目 .  (+(+!![]+[+!![]]+(!![]+[])[!![]+!![]+!![]]+[!![]+!![]]+[+[]])+[])[+!![]]  1.1e+21 の2文字目 0  +[]  空配列を数値に変換した値 1  +!![]  論理値 true を数値に変換した値 2  !![]+!![]  目的の値になるまで論理値 true (=1)を加算した値 3  !![]+!![]+!![] 4  !![]+!![]+!![]+!![] 5  !![]+!![]+!![]+!![]+!![] 6  !![]+!![]+!![]+!![]+!![]+!![] 7  !![]+!![]+!![]+!![]+!![]+!![]+!![] 8  !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] 9  !![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] a  (![]+[])[+!![]]  false の2文字目 c  ([]+[][(![]+[])[+!![]]+(!![]+[])[+[]]])[!![]+!![]+!![]]  function at() { [native code] } の4文字目 d  ([]+[])[!![]+!![]]  undefined の3文字目 e  (!![]+[])[!![]+!![]+!![]]  true の4文字目 f  (![]+[])[+[]]  false の1文字目 i  ([![]]+[])[+!![]+[+[]]]  falseundefined の11文字目 I (i)  (+(+!![]+(!![]+[])[!![]+!![]+!![]]+(+!![])+(+[])+(+[])+(+[]))+[])[+[]]  Infinity の1文字目 l (L)  (![]+[])[!![]+!![]]  false の3文字目 N  (+[![]]+[])[+[]]  NaN の1文字目 n  ([]+[])[+!![]]  undefined の2文字目 o  (!![]+[][(![]+[])[+!![]]+(!![]+[])[+[]]])[+!![]+[+[]]]  truefunction at() { [native code] } の11文字目 r  (!![]+[])[+!![]]  true の2文字目 s  (![]+[])[!![]+!![]+!![]]  false の4文字目 t  (!![]+[])[+[]]  true の1文字目 u  ([]+[])[+[]]  undefined の1文字目 y  (+[![]]+[+(+!![]+(!![]+[])[!![]+!![]+!![]]+[+!![]]+[+[]]+[+[]]+[+[]])])[+!![]+[+[]]]  NaNInfinity の11文字目 (  ([]+[][(![]+[])[+!![]]+(!![]+[])[+[]]])[+!![]+[]+(+!![])]  function at() { [native code] } の12文字目 )  ([]+[][(![]+[])[+!![]]+(!![]+[])[+[]]])[+!![]+[]+(!![]+!![])]  function at() { [native code] } の13文字目

 コード表 
組み合わせることができる一番短いコードを下に記した。

これらを組み合わせ、コードを単純化することができるだろう。
+JSFuck出力型[][]object +[]0number![]falsebooleanobject!![]trueboolean[]+[]""string[+[]][0]object[![]][false]object +!![]1number[[[]]][[[]]]object[]undefinedundefined[]+![]"false"string[!![]][true]object +[]+[]"0"string +[![]]NaNnumber[[]+[]][""]object[[+[]]][[0]]object[[![]]][[false]]object[]+!![]"true"string[[]][[]]object[+!![]][1]object[[]][undefined]object[[]+![]]["false"]object[[!![]]][[true]]object[+[]+[]]["0"]object[+[![]]][NaN]object +!![]+[]"1"string

 セキュリティ 

JSFuckのような難読化技術は、「通常の」JavaScriptに備わる"クラッキング防止システム"が存在しないRé Medina,  Matías A. (2012-09). Bypassing WAFs with non-alphanumeric XSS. Retrieved from http://blog.infobytesec.com/2012/09/bypassing-wafs-with-non-alphanumeric-xss.html.ため、eBayのオークションのページにJSFuckで書かれたスクリプトを埋め込むことができた。

 脚注 

 外部リンク 
 JSFuck - Write any JavaScript with 6 Characters: []()!+ – JavaScriptをJSFuckに変換するWebアプリケーション
 JavaScript code of the aforementioned converter
 JScrewIt - JavaScriptをJSFuckに変換するツール

Category:難解プログラミング言語
Category:JavaScript