web-dev-qa-db-ja.com

JavaScriptの組み込み文字列とは何ですか?

この質問は質問のタイトルに要約するのが難しい

[〜#〜] update [〜#〜]この質問から抽出した文字に基づいて、入力から難読化された文字列を作成するJSFiddleを作成しました:それにアクセスできます ここ 、または 要点 の方が簡単ですか?

私は最近 this profile で次のような難読化されたJavaScriptの楽しいビットに出会いました:

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1
+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+([,][
~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+
1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

驚きを台無しにしてすみませんが、これが評価されるとき、これはこれを返します:

"I love you" in Chrome
"I lone you" In Firefox
"I lo[e you" in IE10

これが分割されたときに機能する方法は、一連のメッセージを生成し、そのようにそれらから文字を引き出すことです(例として「I」を使用):

[]+1/!1
returns
"Infinity"
then
[[]+1/!1]
creates this array:
["Infinity"]
then
[[]+1/!1][1^1]
Takes the first (1^1 == 0) element of that array
"Infinity"
finally
[[]+1/!1][1^1][1>>1]
Takes the first (1>>1 == 0) char of that string
"I"

生成されるその他の文字列には次のものがあります。

({}+[])       -> "[object Object]" (where the space comes from)
([]+!!-[])    -> "false" (used for it's "l")
[/~/+{}][+!1] -> "/~/[object Object]" (this is used for an "o")
(/<</[1]+[])  -> "undefined"

「n」と「[」の代替品を見つけることに興味があり、これを思いつきました。

String.fromCharCode(('1'.charCodeAt(0)<<1)+(10<<1))

私は1と0を使用するという精神で感じていますが、元のコードのよりエレガントな側面の1つ、つまり文字列とはまったく関係がないという外観に違反しています。他の誰かが、元の難読化されたコードを維持する「v」を生成する方法を知っていますか?

これは、多くの才能のあるJavaScriptプログラマーがこれを詳しく調べた後に見つかった追加情報です

Firefoxは「I lone you」を返します

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+

[1^11<<1]は、これから特定の文字をトリミングします。

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])

これは次のように評価されます。

"function test() {
    [native code]
}"

「V」があるかもしれません!!!

同じコードがこれを返すため、Chromeは「I love you」を返します。

"function test() { [native code] }"

「実際のプログラミングの問題」との疑わしい接続のために質問を閉じる前に、 @ Supr's@ Cory's および-に基づいて構築された要約ソリューションを追加すると思いました @ alpha123's 、見よ:

alert([[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+(
[]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+[([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(
!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[
])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[
])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[
])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11
+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<
1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1
)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>
1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]+([,][~1]+[]
)[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+
(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</
[1]+[])[1/1.1&1])

コードとそれが生成するメッセージの複雑さを考えると、JavaScriptエンジンがあなたにそれをどのように特別に感じさせるかを伝えているようです:)

146
Jason Sperske

まず、Jasonとその面白いスニペットで遊んでくれたすべての貢献者に感謝します。 2月14日に妻に送信するために、楽しみのためにそのコードを書きました:)持っていたラップトップにはChromeのみがインストールされていますFirefoxおよびIEでの動作を確認するオプションはありません。さらに、組み込みメソッドのtoString()表現が他のブラウザで異なるように見えることを本当に期待していませんでした。

さて、実際の問題に移ります、コードを正確に見てみましょう。はい、ここで"v"が本当の「問題」でした。 [native code]文字列を解析する以外、この文字を取得する方法は他にありません。これは、組み込みメソッドから取得できます。 1以外の文字列と数字を使用しないように制限しているため、名前に使用可能な文字のみがあるメソッドを利用する必要がありました。

利用可能な文字は、既存のキーワードと文字列表現から取得できます。つまり、最初からNaNnullundefinedInfinitytruefalse、および"[object Object]"。それらのいくつかは、文字列に簡単に変換できます。 1/!1+[]"Infinity"を提供します。

配列[]、オブジェクト{}、正規表現/(?:)/、数字1.1、文字列"1"のさまざまな組み込みメソッドを分析し、美しいものを発見しました test() と呼ばれるRegExpオブジェクトのメソッド。その名前は、利用可能なすべての文字から組み立てることができます。 trueからの"t"および"e"、およびfalseからの"s"。文字列"test"を作成し、正規表現リテラル/-/の角括弧表記を使用してこのメ​​ソッドに対処しました。この行で正しく識別されています。

/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]

すでに説明したように、このコードはChromeで次のように評価されます。

function test() { [native code] }

firefoxの場合:

function test() {
    [native code]
}

およびIEとして:

 function test() {     [native code] }  

(後者では有料specialfunctionキーワードの前のスペースに注意)

そのため、明らかにわかるように、私のコードは提示された文字列から24番目の文字を取得していました。Chromeでは"v"(予定どおり)でしたが、残念ながらFirefoxおよびIE-"n"および"["

すべてのブラウザーで同じ出力を作成するために、他の回答に示されているものとは異なるアプローチを使用しました変更されたバージョンは次のようになります。

javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+/\[[^1]+\]/[([]+![])[1<<1<<
1]+(/|/[(1+{})[1+11>>>1]+[[]+{}][+!1][1]+([]+1/[])[1<<1>>1]
+([1<1]+[])[1+11>>>1+1]+[[!!1]+1][+[]][1-1]+([]+!!/!/)[1|1]
+(/1/[1]+[])[!1%1]+(-{}+{})[-1+1e1-1]+(1+[!!1])[1]+([]+1+{}
)[1<<1]+[!!/!!/+[]][+[]][1&1]]+/=/)[1e1+(1<<1|1)+(([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[1^1]==+!1)]+(!![]+{})[1|1<<1]+[1+{}+1][!1+!1][(11>>1)+1
]](([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+
(!!1+[])[1^1]]))[1&.1][11>>>1]+([,][~1]+[])[1-~1]+[[]+{}][!
1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[]
,[]+{}][1<<1>>>1][1||1]+(/[<+>]/[1&1|1]+[1.1])[1/11.1&1.11]

ただし、読者の興味を引くために、そのためのソリューションは提供しません。私はあなたがそれがどのように機能するかを簡単に理解するだろうと正直に信じています...そして一部の人はクロスブラウザの方法で彼らの最愛の人を驚かせることができます;)

追伸 まだ別の難読化ツール

普遍的な難読化ツールを作成するというジェイソンのアイデアに触発されて、もう1つ書いた。 JSBin: http://jsbin.com/amecoq/2で見つけることができます。数字[0-9]、小さなラテン文字[a-z]、およびスペースを含むテキストを難読化できます。文字列の長さは主にRAMで制限されます(少なくとも私の回答の本文は難読化されました)。出力は、Chrome、Firefox、およびIEでサポートされています。

ヒント:ツールは、上記で示したものとは異なる難読化アプローチを使用します。

83
VisioN

質問のnative codeビットが使用されないのはなぜですか?これはChromeとFirefoxの両方で'v'を提供します:

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]>([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]?([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]

IEをサポートするために編集し、三項演算子なしで実行します。これはChrome、IE、およびFFで動作します。配列を構築し、==を使用してブラウザを決定します。

[([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]

読みやすい:

[
    //ie
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],
    //ch
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],
    //ff
    ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]
]
[
    //ch?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+
    //ff?
    ((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)
]
26
Supr

これは、私が得ることができるものとほぼ同じですが、残念ながら、unescape()を呼び出すことにより、元の難読化の規則に違反しています。

_unescape((/%/+[])[1]+(/1/[1]+[])[1%1]+(+!1)+(+!1)+(1e1+(11*(1-~1)<<1)))
_

取り壊す:

_(/%/+[])[1]          => "%"
(/1/[1]+[])[1%1]     => "u"
(+!1)                => "0"
(+!1)                => "0"
(1e1+(11*(1-~1)<<1)) => "76"
===========================
unescape("%u0076")   => "v"
_

他のアイデア:

  1. どういうわけかunescape("\x76")に到達する
  2. 何らかの方法でString.fromCharCode()を呼び出さずに_118_を変換します
  3. 単語「Invalid」を含む例外からテキストを取得します

更新:

私はコードゴルフを始め、短くして、パーツをより多くの_1_ sなどに置き換えています。

8
Cᴏʀʏ

general use-caseの場合、文字の大文字小文字の区別があまり気にならなければ、少しだまされがちです。

数字0 .. 25を文字に変換する関数「c」を作成します。

c=function(v){for(var i in window){for(var ci in i){if(parseInt(i[ci],(10+11+11)+(1<<1)+(1<<1))==(v+10)){return i[ci]}}}};

パフォーマンス上の理由から、必要に応じてレターを事前にキャッシュしてください。

l=[];for(var i=0; i<(11+11)+(1<<1)+(1<<1);i++){l[i]=c(i);}

Chromeコンソールでは、結果の配列は次のようになります。

> l;
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "K", "l", "m", "n", "o", "p", "q", "r", "S", "t", "u", "v", "w", "x", "y", "Z"]

したがって... vl[10+10+1]

または、次のような一般的なソリューション:

p=(function(){10%11}+[])[1+11+(1<<1)]; // "%"
u=(function(){club=1}+[])[1+11+(1<<1)]; // "u"
vc=p+u+(0+[])+(0+[])+((111>>1)+11+10+[]); // "%u0076"
unescape(vc);

または、このためにspecific問題、たぶんただ:

(function(){v=1}+[])[10+(1<<1)]; // "v"
4
svidgen

N/vを生成する部分は次のとおりです。

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]

Firefoxでは、([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])の評価

"function test() {
    [native code]
}"

while Chromeそれは

"function test() { [native code] }"

1^11<<1は23です。したがって、Firefoxの余分な空白のため、これは「v」に到達するのに十分ではなく、代わりに「n」になります。

これが、Function#toStringの動作に依存すべきではない理由です。 ;)

編集:最後に、かなり難読化されたクロスブラウザバージョンを見つけました:

[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]+([,][~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]

これにより、n/vセクションが次のように置き換えられます。

([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]

これはparseIntの違いを悪用します(Firefoxは0から始まる数字を8進数として解析しますが、Chromeはそうではありません))。 (別の 'v'が見つかりません:P)。
parseIntは少し不自然に見えますが、今のところそれが最善です。

4
Peter C

これにより、Chromeでvが得られます。

_Object.getOwnPropertyNames(Object)[17][3];
_

これはFirefoxで行います:

_Object.getOwnPropertyNames(Object)[9][3]
_

両方ともObject.prototype.preventExtensions()からそれを引き出すので、おそらくそのメソッドを参照するためのクロスブラウザーの方法を見つけることができます。 (これはObject.Prototypeで唯一の17文字の名前です。)

これをもっと難読化したバージョンを自由に構築して、自分の功績を称えてください。

3
Nathan Friedly

クロムでは、式_([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])_は"function test() { [native code] }"に評価され、_[1^11<<1]_は23に評価されます(ビット演算子は変数を32ビットに切り捨てます)

2
enhzflep