JavaScript は奇妙で興味深い言語であり、今でも機能するクレイジーなコードを書くことができます。これは、私たちが物事をどのように扱うかに基づいて、物事を特定のタイプに変換するのに役立ちます。
文字列を追加すると、JavaScript はテキスト表現が必要であると想定するため、それを文字列に変換します。正または負の接頭記号を追加すると、JavaScript はそれを数値形式で表したいとみなして、可能であれば文字列を数値に変換します。否定記号を追加すると、JavaScript は文字列をブール値に変換します。
JavaScript では 6 つの記号 [,]、(,)、! を使用して魔法のコードを書くことができます。現在携帯電話を使用していない場合は、ブラウザのコンソールを開いて、コード値 true を指定して任意のコード例をコンソールに貼り付けることができます。
基本的な、覚えておくべきいくつかの黄金律から始めましょう:
! 続く文字はブール値に変換されます
+ 続く文字は数値に変換されます
[] 続く文字は変換されますブール値に変換すると文字列に変換されます
次の例を見てください:
![] === false +[] === 0 []+[] === ""
もう 1 つ知っておくべきことは、次のように角括弧を使用して文字列から特定の文字を取得できることです:
"hello"[0] === "h"
こちらも覚えておいてください文字列を追加し、式全体を数値に変換することで、複数の数値をまとめて表現できます。
+("1" + "1") === 11
引き続きいくつかのものを組み合わせて、文字 a
![] === false ![]+[] === "false" +!![] === 1 ------------------------ (![]+[])[+!![]] === "a" // same as "false"[1]
を取得しましょう。 推論を適用してみましょう!
true と false を通して同様の文字 a、e、f、l、r、s、t、u を取得できますが、他の場所から文字を取得することはできますか?
[][[]] などの特別な数式を使用して未定義を取得し、上で説明した黄金律を使用して他の文字 d、i、n を取得することができます。
`[][[]] + [] === "undefined"`
これまでに取得したすべての文字を使用して、fill、filter、および find を綴ることができます。もちろん、他にも綴ることができる単語がいくつかありますが、これらの単語で最も重要なことは、それらはすべて配列メソッドであるということです。これは、それらが配列オブジェクトの一部であり、[2,1].sort() のように配列インスタンスを直接呼び出すことができることを意味します。
さて、JavaScript について知っておくべきもう 1 つの重要な点は、オブジェクトのプロパティにはドット表記または角括弧 [] を通じてアクセスできるということです。上記の配列メソッドは配列オブジェクト自体のプロパティであり、ドット表記の代わりに角括弧を使用してこれらのメソッドを呼び出すことができます。
つまり、[2,1]["sort"]() は [2,1].sort() と同等です。
続けて、配列メソッドを使用しようとすると何が起こるか見てみましょう。これまでのところ、使用できます私たちは綴ったことはありますが、文字とは呼んでいません。
[]["fill"]
これは関数 fill() { [ネイティブ コード] } を取得します。黄金律を使用してこのメソッド ヘッダーを文字列として再度使用できます:
[]["fill"]+[] === "function fill() { [native code] }"
それで、他の文字を取得します: c、o、v、(、 )、{、[、]、}。
新しい c と o を使用して、単語コンストラクターを形成できるようになりました。コンストラクターはメソッドであり、すべての JS オブジェクトは単純に独自のコンストラクターを返します。
これまで扱ってきたオブジェクトについては、文字列として表されるコンストラクター関数を取得できます:
true["constructor"] + [] === "function Boolean() { [native code] }" 0["constructor"] + [] === "function Number() { [native code] }" ""["constructor"] + [] === "function String() { [native code] }" []["constructor"] + [] === "function Array() { [native code] }" ({})["constructor"] + [] === "function Object() { [native code] }"
これらの式を使用して、次の文字をライブラリに追加できます:
これで、関数 "toString"` は角括弧を使用でき、次のように呼び出すことができます:
(10)["toString"]() === "10"
黄金律を使用すると、必要なものを文字列に変換できますが、上記の方程式はどのように使用するのでしょうか?
そうですね、Number 型の toString メソッドには radix ("radix") という秘密の引数があります。次のように、値を文字列に変換する前に基数に変換します。
(12)["toString"](10) === "12" // 十进制 (12)["toString"](2) === "1100" // 二进制 (12)["toString"](8) === "14" // 八进制 (12)["toString"](16) === "c" // 十六进制
しかし、基数が 16 にしか書き込まれないのはなぜでしょうか?最大値は、0 ~ 9 と a ~ z のすべての文字を含む 36 です。これで、必要な英数字を取得できるようになりました。
(10)["toString"](36) === "a" (35)["toString"](36) === "z"
素晴らしいですね! しかし、句読点や大文字などの他の記号はどうなるでしょうか?さらに詳しく見てみましょう。
JS が実行されるタイミングに応じて、特定の事前定義されたオブジェクトまたはデータにアクセスする場合とアクセスしない場合があります。これをブラウザで実行すると、いくつかの既存の HTML ラッパー メソッドにアクセスできます。
たとえば、bold は <> タグでラップされた文字列メソッドです。
"test"["bold"]() === "<b>test</b>"
これで、 と / の 2 つの文字が得られます。
エスケープ メソッドについて聞いたことがあるかもしれません。このメソッドは主に文字列を、単純なブラウザで解釈できる URI に適した形式に変換します。スペース文字を渡すと、「%20」が返されます。
各文字を自動変換できるツールはこちらです。 ツールアドレス: http://www.jsfuck.com/ ソースコードアドレス: https://raw.githubusercontent.com/aemkei/jsfuck/master/jsfuck.js
なぜこれらの文字が役に立つのですか?
少し前に eBay が、販売者がこれらの文字のみを使用してページに実行可能な JS を配置できるようにするという悪いことをしたわけではありませんが、これはかなりまれな攻撃ベクトルです。難読化という人もいますが、実際には、難読化するより良い方法があります。
最後に、この探検旅行を楽しんでいただければ幸いです。
リソース:
https://en.wikipedia.org/wiki/JSFuck
https://esolangs.org/wiki/JSFuck
http://patriciopalladino.com/blog/2012/08/09/ non-alphanumeric-javascript.html
https://raw.githubusercontent.com/aemkei/jsfuck/master/jsfuck.js