記号だけで書けちゃうJavaScript

-- Views

May 01, 26

スライド概要

profile-image

プログラミングが好きで、LTやってます

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

記号だけで書けちゃうJavaScript 2025/08/04 俺たちの勉強会 #3 #orestudy

2.

自己紹介:murasuke ・株式会社 ツールラボ 開発部 3年ほど前に転職して、勉強会に出る時間ができました ・前回、俺たちの勉強会#2 で「人生初のLT」をやりました👏 ・6月の社員旅行(in 熱海)で 「呑みながらLT会」やりました (盛り上がったので多分来年もやります!)

3.
[beta]
これはJavaScriptの式です。(ブラウザで)実行できます
_=
({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]
+(!![]+[])[-~[]]+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![
]+[])[-~[]];__=
(!![]+[])[-~[]]+({}+[])[-~-~-~-~[]]+(!![]+[])[+[]]+([]['']+[])[+[]]+(!![]+[])[-~[]]+([]['']+
[])[-~[]];[][_][_]((![]+[])[-~[]]+(![]+[])[-~-~[]]+(!![] + [])[-~-~-~[]]+(!![] +
[])[-~[]]+(!![] + [])[+[]]+'('+"'"+[][_][_](__+'
"\\'+([]['']+[])[+[]]+(+[])+(+[])+(-~-~[]<<-~[])+(-~-~[]<<-~-~[])+'"')()+(!![] +
[])[-~-~-~[]]+(![]+[])[-~-~[]]+(![]+[])[-~-~[]]+({} + [])[-~[]]+','+[][_][_](__+'
"\\'+([]['']+[])[+[]]+(+[])+(+[])+(-~-~-~-~-~-~-~[])+(-~-~-~-~-~-~-~[])+'"')()+(
{} + [])[-~[]]+(!![] + [])[-~[]]+(![]+[])[-~-~[]]+([][[]] + [])[-~-~[]]+'!'+"'"+')')()

4.

ブラウザのコンソールで実行できます! ちゃんと?「 alert(’Hello, world!’)」が実行できました

5.

なぜ [] や ![]や[_] だけでコードが書けるのか JavaScriptは ● 「記号」と「文字列」のみで(キーワードを使わずに) 「実行」する方法があります ● 「任意の文字 」は「記号」の組み合わせで作ることができます ⇒ つまり「 スクリプト」から「文字」を排除することが可能です 1. 実行する処理を「記号」+「文字列」で表現するテクニック 2. 「文字列」を「記号」に置き換えるテクニック について解説します

6.

実行する処理を「記号」+「文字列」で表現する 「Functionコンストラクタ」を使います (eval()ではなく ) new Function('実行する処理')(); // newはJSの仕様で省略可 空配列のリテラルからプロトタイプチェーンをたどることで取得できます ⇐ Arrayのコンストラクタ ⇐ これがFunctionコンストラクタ 任意の文字列の実行を行う処理は、このように書くことができます [].constructor.constructor('実行する処理')

7.

実行する処理を「記号」+「文字列」で表現する ● 「プロパティ」は「配列のアクセス」に書き換えることができます [][‘constructor’][‘constructor’]('実行する処理')() (任意の文字列を実行する処理を、キーワードを使わずに) 「文字列」と「記号」で表現することができました ● 次は「文字列」を「記号」で表す方法を解説します!

8.

「文字列」を「記号」に置き換えるテクニック 「記号」から「文字」の作り方を順に見ていきます 1. 記号の組み合わせで「 数字」を作る 2. 評価結果 (例:false)を文字列化して「 文字」を切り出す 3. 文字コードから (なんとかして )「文字」を生成する

9.

記号の組み合わせで「数字」を作る 評価結果が0になる式を作る (空配列に+をつけることで 数値(0)として評価される) > +[] 0 0の補数を取ることで-1を作る > ~+[] -1 マイナス符号を付けて1にする > -~+[] 1 1の補数をとると「-2」 繰り返して大きな数字を作る > ~-~+[] -2 シフト演算で大きな数を作る > -~-~[]<<-~-~[] 8

10.

評価結果(例:false)を文字列化して「文字」を切り出す 評価結果がfalseになる式を作る > ![] false 評価結果を文字列化(+[])する > ![]+[] ’false’ 評価結果から1文字取り出す > (![]+[])[0] ’f’ 0になる式(+[])と合わせる > (![]+[])[+[]] ’f’ ここまでで、「‘f’, ‘a’, ‘l’, ‘s’, ‘e’」 の5文字を作ることができました

11.
[beta]
評価結果(例:false)を文字列化して「文字」を切り出す
評価結果から文字を切り出す際に使える式の例
![]+[]; // 'false'
!![]+[]; // 'true'
{}+[]; // '[object Object]'
[][[]]+[]; // 'undefined'
-~[]/[]+[]; // 'Infinity'
+{}+[]; // 'NaN'
※残念ながら、すべてのアルファベットを作ることはできません

12.
[beta]
文字コードから(なんとかして)「文字」を生成する
前ページで作れない文字は、文字エスケープ(\uHHHH)から作ります
> Function('return "\u0041"')()
'A'

Functionコンストラクタは、既出なので置き換えます
> []['constructor']['constructor']('return "\u0041"')()
'A'

'constructor'、'return'、'\u0041'は、前ページで作った文字から作れるので・・・
> ({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]+(!![]+[])[-~[]]
+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![]+[])[-~[]]
'constructor'
> (!![]+[])[-~[]]+({}+[])[-~-~-~-~[]]+(!![]+[])[+[]]+([]['']+[])[+[]]+(!![]+[])[-~[]]+([]['']+[])[-~[]]
'return'
> ' "\\'+([]['']+[])[+[]]+(+[])+(+[])+(-~-~[]<<-~[])+(-~[])+'"'
' "\\u0041"'

13.
[beta]
文字コードから(なんとかして)「文字」を生成する
全てを組み合わせることで、(なんとか)「A」を作ることができました!
>
[][(({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]+(!
![]+[])[-~[]]+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![]+[])[-~[
]])][(({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]+
(!![]+[])[-~[]]+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![]+[])[~[]])]((!![]+[])[-~[]]+({}+[])[-~-~-~-~[]]+(!![]+[])[+[]]+([]['']+[])[+[]]+(!![]+[])[-~[]]+([][''
]+[])[-~[]]+' "\\'+([]['']+[])[+[]]+(+[])+(+[])+(-~-~[]<<-~[])+(-~[])+'"')()
'A'

14.
[beta]
まとめ
●

Functionコンストラクタで (キーワードを使わず )「任意の js文字」が実行できる

> []['constructor']['constructor']('任意のjs文字列')()

●

Functionコンストラクタの「 'constructor'」を「記号」に置き換えることができる

> [][({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(!![]+[])[+[]]+(!![]+[])[-~[]]
+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![]+[])[-~[]]][({}+[])[-~-~-~-~-~[]]+({}+[])[-~[]]+([]['']+[])[-~[]]+(![]+[])[-~-~-~[]]+(
!![]+[])[+[]]+(!![]+[])[-~[]]+([]['']+[])[+[]]+({}+[])[-~-~-~-~-~[]]+(!![]+[])[+[]]+({}+[])[-~[]]+(!![]+[])[-~[]]]('任意のjs文字列')()

●

「`任意のjs文字列`」も「記号化が可能」(置き換えるだけ)

これで明日から「記号」で書いて同僚に迷惑をかけることができますね!
変換プログラム:https://github.com/murasuke/js-obfuscator