Apa yang dimaksud dengan string bawaan JavaScript?

147

pertanyaan ini sulit untuk diringkas dalam judul pertanyaan

PEMBARUAN Saya membuat JSFiddle yang membangun string yang dikaburkan dari input Anda berdasarkan surat-surat yang diambil dari pertanyaan ini: Anda dapat mengaksesnya di sini , atau apakah intisari akan lebih mudah?

Baru-baru ini saya menemukan sedikit keceriaan JavaScript yang membingungkan di profil ini yang terlihat seperti ini:

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]

Maaf merusak kejutan tetapi ketika ini dievaluasi itu mengembalikan ini:

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

Cara ini berfungsi ketika pecah, adalah untuk menghasilkan serangkaian pesan dan menarik surat keluar seperti itu (menggunakan "I" sebagai contoh):

[]+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"

String lain yang dihasilkan termasuk:

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

Saya tertarik mencari pengganti untuk "n" dan "[" dan muncul dengan ini:

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

Yang saya rasakan dalam semangat menggunakan 1 dan 0, tetapi melanggar salah satu aspek yang lebih elegan dari kode asli yang merupakan penampilan yang tidak ada hubungannya dengan string sama sekali. Apakah ada orang lain yang memiliki ide tentang bagaimana menghasilkan "v" yang sesuai dengan kode asli yang dikaburkan?

Berikut adalah beberapa informasi tambahan yang ditemukan setelah banyak programmer JavaScript yang berbakat melihat lebih dalam

Firefox mengembalikan "I lone you" Karena baris ini:

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

[1^11<<1] memangkas karakter tertentu dari ini:

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

Yang mengevaluasi ini:

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

Yang sepertinya kita punya "V" kita !!!

Chrome mengembalikan "I love you", karena kode yang sama mengembalikan ini:

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

Sebelum pertanyaan ditutup untuk koneksi yang meragukan dengan "masalah pemrograman nyata", saya pikir saya akan menambahkan solusi terangkum yang dibangun di atas @ Supr , @ Cory's dan @ alpha123's , lihat:

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])

Mengingat kompleksitas kode dan pesan yang dihasilkannya, hampir seperti mesin JavaScript memberi tahu betapa istimewanya Anda membuatnya :)

Jason Sperske
sumber
9
Itu mengatakan "cinta" di konsol Chrome. i.imgur.com/rVyKMoP.png
bfavaretto
2
Bagaimana jika Anda menghapus non surat dari function test() { [native code] }, maka Anda dapat menormalkannya dan mengekstrak surat yang Anda inginkan
Jason Sperske
4
Mendasarkan kode pada string output non-standar yang ditetapkan untuk mencetak pesan menggunakan kode dikaburkan ... Saya menelepon ini salah satu cara terlalu lokal.
2
@Ian, benar. Jika orang-orang dalam hidup saya yang saya cintai benar-benar peduli pada saya, mereka akan menggunakan Chrome :)
Jason Sperske
4
Bagian terbaik tentang ini adalah peringatan yang diberikan oleh editor teks saya: "Penggunaan membingungkan '!'"
Jake Johnson

Jawaban:

83

Pertama-tama, saya ingin mengucapkan terima kasih kepada Jason dan semua kontributor untuk bermain dengan potongan lucu itu. Saya telah menulis kode itu hanya untuk bersenang-senang untuk mengirimkannya kepada istri saya pada tanggal 14 Februari :) Dengan hanya menginstal Chrome di laptop saya tidak punya pilihan untuk memeriksa cara kerjanya di Firefox dan IE. Selain itu, saya belum benar-benar berharap bahwa toString()representasi metode built-in mungkin terlihat berbeda di browser lain.

Sekarang, pindah ke masalah sebenarnya , mari kita lihat kodenya. Ya, "v"adalah "masalah" sebenarnya di sini. Saya tidak menemukan cara lain untuk mendapatkan surat ini kecuali [native code]string parsing , yang dapat diambil dari metode bawaan apa pun. Karena saya membatasi diri dengan tidak memiliki string dan tidak ada angka kecuali 1digunakan, saya perlu mengeksploitasi beberapa metode yang hanya memiliki karakter yang tersedia dalam namanya.

Karakter yang tersedia dapat diperoleh dari kata kunci yang ada dan representasi String, yaitu dari mulai kita punya NaN, null, undefined, Infinity, true, false, dan "[object Object]". Beberapa dari mereka dapat dengan mudah dikonversi menjadi string, misalnya 1/!1+[]memberi "Infinity".

Saya telah menganalisis berbagai metode build-in untuk array [], objek {}, ekspresi reguler /(?:)/, angka 1.1, string "1", dan menemukan satu metode RegExpobjek yang indah yang disebut test(). Namanya dapat dikumpulkan dari semua karakter yang tersedia, misalnya "t"dan "e"dari true, dan "s"dari false. Saya telah membuat string "test"dan membahas metode ini menggunakan notasi tanda kurung siku untuk regex literal /-/, yang diidentifikasi dengan benar di baris ini:

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

Seperti yang sudah dibahas, kode ini dievaluasi di Chrome sebagai:

function test() { [native code] }

di Firefox sebagai:

function test() {
    [native code]
}

dan di IE sebagai:

 function test() {     [native code] }  

(di kedua membayar khusus memperhatikan ruang sebelum functionkata kunci)

Jadi, seperti yang Anda lihat dengan jelas, kode saya mendapatkan karakter ke-24 dari string yang disajikan, yang di Chrome "v"(seperti yang direncanakan), tetapi sayangnya di Firefox dan IE - "n"dan "["masing - masing.

Untuk membuat output yang sama di semua browser, saya telah menggunakan pendekatan yang berbeda dari yang diilustrasikan dalam jawaban lain. Sekarang versi yang dimodifikasi terlihat seperti itu:

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]

Namun, untuk membangkitkan minat para pembaca saya tidak akan memberikan solusi untuk itu. Jujur saya percaya bahwa Anda akan dengan mudah memahami cara kerjanya ... dan beberapa bahkan dapat mengejutkan kekasih mereka dengan cara lintas-browser;)

PS Yet Another Obfuscator

Terinspirasi oleh ide Jason untuk membuat alat mengaburkan universal, saya telah menulis satu lagi. Anda dapat menemukannya di JSBin: http://jsbin.com/amecoq/2 . Itu dapat mengaburkan teks apa pun yang berisi angka [0-9], huruf latin kecil [a-z], dan spasi. Panjang string dibatasi sebagian besar dengan RAM Anda (setidaknya badan jawaban saya berhasil dikaburkan). Outputnya didukung oleh Chrome, Firefox, dan IE.

Petunjuk: alat ini menggunakan pendekatan kebingungan yang berbeda dari yang disajikan di atas.

Penglihatan
sumber
4
"constructor" ... wow itu luar biasa dan kamu menyimpan segi empat sempurna dengan jeda baris yang valid. Anda baik
Jason Sperske
1
Saya membuat Obfuscator yang menciptakan string sesuai dengan aturan gaya Anda: jsfiddle.net/w9rFF/8
Jason Sperske
@JasonSperske Itu trik yang bagus! Kerja bagus! Saya akan mencoba berkontribusi untuk itu.
VisioN
26

Mengapa tidak native codesedikit dari pertanyaan yang digunakan? Yang ini memberi 'v'di Chrome dan Firefox:

([]+/-/[(!!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]

Edit untuk mendukung IE dan melakukannya tanpa operator ternary: Yang ini berfungsi di Chrome, IE, dan FF. Membuat array dan menggunakan ==untuk menentukan browser.

[([]+/-/[(!!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)]

Dapat dibaca:

[
    //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)
]
Supr
sumber
Itu menarik. Awalnya telah ditolak bahwa penempatan kata "kode asli" tidak dapat diprediksi antara Firefox dan Chrome. Ini mengatasi itu tetapi tidak berfungsi di IE10 (di mana ia mengembalikan "i"). Masih saya bertanya-tanya apakah opsi ini mungkin menawarkan beberapa ide segar
Jason Sperske
Idenya adalah untuk hanya memilih kedua ndan vdan hanya memilih mana yang terbesar: str[23]>str[27]?str[23]:str[27]. Dengan kata lain, operator tersier adalah triknya. Dapat diperluas untuk mendukung IE juga:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr
1
Jawaban Anda adalah yang pertama (di depan pencipta kode asli), tetapi saya merasa jawabannya secara logis dapat dianggap sebagai yang benar. Pekerjaan masih bagus (dan 13 suara yang layak)
Jason Sperske
1
Nitpick minor: operator tersier adalah operator terpenting ketiga, setelah primer dan sekunder. Operator yang mengambil tiga operan adalah ternary.
Eric Lippert
1
@EricLippert, gah, saya bahkan googled untuk memastikan saya menggunakan istilah yang tepat, namun saya masih berakhir dengan yang salah! Terima kasih sudah dikoreksi.
Supr
8

Ini hampir sedekat yang saya dapat, sayangnya itu melanggar konvensi kebingungan asli dengan membuat panggilan ke unescape():

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

Menangis:

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

Ide lain:

  1. Entah bagaimana caranya unescape("\x76")
  2. Entah bagaimana mengkonversi 118tanpa meneleponString.fromCharCode()
  3. Dapatkan teks dari pengecualian dengan kata "Tidak Valid" di dalamnya

Pembaruan:

Saya mulai bermain golf kode dan membuatnya lebih pendek, mengganti bagian dengan lebih banyak 1, dll.

Cᴏʀʏ
sumber
Saya suka yang ini juga. Saya agak bingung memilih jawaban yang "benar", karena jawaban Anda dan @ alpha123 terlihat sangat membingungkan dan secara cerdik menyembunyikan niat awal.
Jason Sperske
Dan dukungan IE10 menyegel kesepakatan (dengan permintaan maaf yang tulus @ alpha123 untuk jawaban yang sangat baik)
Jason Sperske
Anda bisa menggantinya '%'dengan (/%/+[[]+1/!1])[1]menghapus sembarang kutipan. Saya juga menambahkan l=unescape;menggunakan huruf kecil Luntuk menyembunyikan referensi unescape. Ini menyenangkan :)
Jason Sperske
@JasonSperske: Bahkan lebih pendek:(/%/+[])[1]
Cᴏʀʏ
1
Atau Anda bisa memberi nama variabel Anda $1;
Cᴏʀʏ
4

Inilah bagian yang menghasilkan n / v:

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

Di Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])evaluasikan ke

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

sementara di Chrome itu

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

1^11<<1 sama dengan 23. Jadi karena spasi tambahan Firefox, ini tidak cukup untuk sampai ke 'v', dan sebaliknya 'n'.

Dan inilah mengapa Anda tidak harus mengandalkan perilaku Function # toString. ;)

EDIT: Akhirnya saya menemukan versi cross-browser yang cukup dikaburkan:

[[]+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]

Ini menggantikan bagian n / v dengan:

([]+/-/[(!!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)]

yang mengeksploitasi perbedaan parseInt (tampaknya Firefox mem-parsing angka dimulai dengan 0 sebagai oktal, sementara Chrome tidak) untuk menambahkan 4 dalam kasus Firefox, sehingga mendapatkan 'v' dari 'asli' dalam kedua kasus (saya tidak dapat menemukan yang lain 'v ': P).
ParseInt terlihat agak tidak pada tempatnya, tapi itu yang terbaik yang bisa saya lakukan untuk saat ini.

Peter C
sumber
1
Pertanyaannya adalahDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian
Terima kasih. Sekarang saya mencoba mencari cara lintas-browser untuk melakukannya ... 'V' adalah huruf yang tidak biasa ....
Peter C
@Ian - nah kalau begitu, [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] akan melakukannya?
enhzflep
@JanDvorak - Saya tidak punya FF saat ini. Apa yang dievaluasi untuk? Jika saya mungkin terlalu lancang untuk bertanya, itu.
enhzflep
@enhzflep maaf, maksud saya "itu tidak akan bekerja di Chrome, di sisi lain"
John Dvorak
4

Untuk kasus penggunaan umum , jika casing karakter bukan masalah besar, saya mungkin cenderung sedikit curang.

Buat fungsi "c" yang mengubah angka 0 .. 25 menjadi karakter.

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]}}}};

Untuk alasan kinerja, pra-cache surat-surat, jika Anda mau.

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

Di konsol Chrome, array yang dihasilkan terlihat seperti ini:

> 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"]

Jadi ... v Anda mungkin l[10+10+1].

Atau, solusi umum seperti ini:

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);

Atau, untuk masalah khusus ini , mungkin hanya:

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

Ini memberi av di Chrome:

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

Dan ini dilakukan di Firefox:

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

Mereka berdua mengeluarkannya Object.prototype.preventExtensions(), jadi Anda mungkin bisa menemukan cara lintas-browser untuk referensi metode itu. (Ini satu-satunya nama 17 karakter di Object.Prototype sebagai permulaan.)

Merasa bebas untuk membangun versi yang lebih membingungkan ini dan mengambil semua pujian untuk diri Anda sendiri, saya kehabisan waktu;)

Nathan Friedly
sumber
2

Dalam chrome, ekspresi ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])dievaluasi menjadi "function test() { [native code] }", [1^11<<1]dievaluasi ke 23 (operator bitwise menyebabkan variabel terpotong menjadi 32 bit)

enhzflep
sumber
Pertanyaannya adalahDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian