Quali sono le stringhe integrate di JavaScript?


147

questa domanda è difficile da riassumere in un titolo di domanda

AGGIORNAMENTO Ho creato un JSFiddle che costruisce una stringa offuscata dal tuo input in base alle lettere estratte da questa domanda: puoi accedervi qui , o sarebbe più semplice una sintesi ?

Recentemente ho trovato un po 'di JavaScript offuscato in questo profilo che assomiglia a questo:

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]

Mi dispiace rovinare la sorpresa, ma quando viene valutato restituisce questo:

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

Il modo in cui funziona quando viene scomposto è generare una serie di messaggi e tirarne fuori le lettere in questo modo (usando l'io come esempio):

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

Altre stringhe che vengono generate includono:

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

Ero interessato a trovare un sostituto per "n" e "[" e ho pensato a questo:

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

Che mi sento nello spirito di usare 1 e 0, ma viola uno degli aspetti più eleganti del codice originale che sembra non avere nulla a che fare con le stringhe. Qualcun altro ha idea di come generare una "v" in linea con il codice offuscato originale?

Ecco alcune informazioni extra che sono state trovate dopo che molti talentuosi programmatori JavaScript hanno dato un'occhiata più approfondita a questo

Firefox restituisce "I lone you" A causa di questa riga:

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

[1^11<<1] taglia un carattere specifico da questo:

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

Che valuta questo:

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

Sembra che potremmo avere la nostra "V" !!!

Chrome restituisce "Ti amo", perché lo stesso codice restituisce questo:

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

Prima che la domanda fosse chiusa per una discutibile connessione con "un vero problema di programmazione", ho pensato di aggiungere una soluzione riepilogativa che si basa su @ Supr , @ Cory e @ alpha123 , ecco:

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

Data la complessità del codice e del messaggio che produce, è quasi come se il motore JavaScript stia dicendo quanto lo rendi speciale :)


9
Dice "amore" nella console di Chrome. i.imgur.com/rVyKMoP.png
bfavaretto

2
Che cosa succede se togli le lettere non dalla function test() { [native code] }, quindi potresti normalizzarle ed estrarre la lettera che desideri
Jason Sperske,

4
Basare il codice su un output di stringa non definito per standard al fine di stampare un messaggio usando un codice offuscato ... Lo sto chiamando in un modo troppo localizzato.

2
@Ian, true. Se le persone della mia vita che amo davvero si interessassero a me, userebbero Chrome :)
Jason Sperske,

4
La parte migliore di questo è l'avvertimento che il mio editor di testo dà: "Uso confuso di '!'"
Jake Johnson

Risposte:


83

Prima di tutto, vorrei ringraziare Jason e tutti i collaboratori per aver giocato con quel divertente frammento. Ho scritto quel pezzo di codice solo per divertimento per inviarlo a mia moglie il 14 febbraio :) Avendo installato solo Chrome sul laptop, non avevo opzioni per controllare come funziona in Firefox e IE. Inoltre, non mi aspettavo davvero che la toString()rappresentazione dei metodi integrati potesse apparire diversamente in altri browser.

Ora, passando al vero problema , diamo un'occhiata al codice. Sì, è "v"stato il vero "problema" qui. Non ho trovato altri modi per ottenere questa lettera se non l'analisi della [native code]stringa, che può essere presa da qualsiasi metodo incorporato. Dato che mi sono limitato a non avere stringhe e numeri se non 1utilizzati, avevo bisogno di sfruttare un metodo che avesse solo caratteri disponibili nel suo nome.

Caratteri disponibili possono essere ottenuti da parole chiave esistenti e rappresentazioni di stringa, cioè fin dall'inizio abbiamo avuto NaN, null, undefined, Infinity, true, false, e "[object Object]". Alcuni di essi possono essere facilmente convertiti in stringhe, ad esempio, 1/!1+[]"Infinity".

Ho analizzato diversi metodi incorporati per array [], oggetti {}, espressioni regolari /(?:)/, numeri 1.1, stringhe "1"e ho scoperto un bellissimo metodo di RegExpoggetto chiamato test(). Il suo nome può essere assemblato da tutti i caratteri disponibili, ad esempio, "t"e "e"da truee "s"da false. Ho creato una stringa "test"e indirizzato questo metodo usando la notazione tra parentesi quadre per regex letterale /-/, identificato correttamente in questa riga:

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

Come già discusso, questo pezzo di codice viene valutato in Chrome come:

function test() { [native code] }

in Firefox come:

function test() {
    [native code]
}

e in IE come:

 function test() {     [native code] }  

(in quest'ultimo caso presta particolare attenzione allo spazio prima della functionparola chiave)

Quindi, come vedi chiaramente, il mio codice stava ottenendo il 24 ° carattere dalla stringa presentata, che in Chrome era "v"(come previsto), ma sfortunatamente in Firefox e IE - "n"e "["rispettivamente.

Per ottenere lo stesso risultato in tutti i browser, ho utilizzato un approccio diverso rispetto a quello illustrato nelle altre risposte. Ora la versione modificata appare così:

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]

Tuttavia, al fine di incuriosire i lettori non fornirò una soluzione per questo. Sinceramente credo che capirai facilmente come funziona ... e alcuni possono persino sorprendere la loro amata in modo cross-browser;)

PS Ancora un altro offuscatore

Ispirato dall'idea di Jason di creare uno strumento offuscante universale, ne ho scritto uno in più. Puoi trovarlo su JSBin: http://jsbin.com/amecoq/2 . Può offuscare qualsiasi testo che contenga numeri [0-9], piccole lettere latine [a-z]e spazi. La lunghezza della stringa è limitata principalmente con la RAM (almeno il corpo della mia risposta è stato offuscato con successo). L'output è supportato da Chrome, Firefox e IE.

Suggerimento: lo strumento utilizza un approccio di offuscamento diverso da quello presentato sopra.


4
"costruttore" ... wow, è fantastico e hai mantenuto il rettangolo perfetto con interruzioni di riga valide. Sei bravo
Jason Sperske il

1
Ho creato un Obfuscator che crea una stringa in linea con le tue regole di stile: jsfiddle.net/w9rFF/8
Jason Sperske

@JasonSperske È stato un bel trucco! Ottimo lavoro! Proverò a contribuire ad esso.
VisioN,

26

Perché la native codeparte della domanda non viene utilizzata? Questo dà un 'v'in Chrome e 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]

Modifica per supportare IE e farlo senza l'operatore ternario: questo funziona in Chrome, IE e FF. Crea un array e lo utilizza ==per determinare il 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)]

Leggibile:

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

È interessante. Inizialmente è stato respinto che il posizionamento delle parole "codice nativo" era imprevedibile tra Firefox e Chrome. Questo risolve questo problema ma non funziona in IE10 (dove restituisce "i"). Mi chiedo comunque se questa opzione possa offrire alcune nuove idee
Jason Sperske,

L'idea è quella di selezionare solo sia ne ve solo scegliere a seconda di quale è più grande: str[23]>str[27]?str[23]:str[27]. In altre parole, l'operatore terziario è il trucco. Potrebbe essere esteso anche per supportare IE:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr

1
La tua risposta è stata la prima (davanti al creatore del codice originale), ma ho sentito che la sua risposta poteva essere logicamente considerata corretta. Ottimo lavoro (e ben meritato 13 voti in più)
Jason Sperske,

1
Minore nitpick: un operatore terziario è il terzo operatore più importante, dopo quello primario e secondario. Un operatore che accetta tre operandi è ternario.
Eric Lippert,

1
@EricLippert, Dio, l'ho persino cercato su Google per assicurarmi di usare il termine giusto, eppure ho ancora finito con quello sbagliato! Grazie, corretto.
Supr

8

Questo è il più vicino possibile, purtroppo viola la convenzione dell'offuscamento originale chiamando a unescape():

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

Demolire:

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

Altre idee:

  1. In qualche modo arrivare a unescape("\x76")
  2. In qualche modo convertire 118senza chiamareString.fromCharCode()
  3. Ottieni il testo da un'eccezione con la parola "Non valido" in esso

aggiornamenti:

Ho iniziato a giocare a code golf e l'ho reso più breve, sostituendo parti con più 1s, ecc.


Mi piace anche questo. Sono un po 'lacerato nel selezionare una risposta "corretta", dato che sia il tuo che il look di @ alpha123 sono estremamente offuscati e nascondono abilmente l'intenzione originale.
Jason Sperske,

E il supporto IE10 sigilla l'affare (con scuse sincere @ alpha123 per l'eccellente risposta)
Jason Sperske,

Si potrebbe sostituire quella '%'con (/%/+[[]+1/!1])[1]la rimozione di eventuali citazioni. Ho anche aggiunto l' l=unescape;uso di lettere minuscole Lper nascondere il riferimento a unescape. È stato divertente :)
Jason Sperske il

@JasonSperske: Ancora più breve:(/%/+[])[1]
Cᴏʀʏ

1
Oppure potresti nominare la tua variabile $1;
Cᴏʀʏ

4

Ecco la parte che genera n / v:

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

In Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])valuta

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

mentre in Chrome lo è

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

1^11<<1 è uguale a 23. Quindi, a causa dello spazio bianco extra di Firefox, questo non è abbastanza per arrivare alla "v", ed è invece "n".

Ed è per questo che non dovresti fare affidamento sul comportamento della funzione # a Stringa. ;)

EDIT: Finalmente ho trovato una versione cross-browser ragionevolmente offuscata:

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

Questo sostituisce la sezione n / v con:

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

che sfrutta le differenze di parseInt (apparentemente Firefox analizza i numeri che iniziano con 0 come ottale, mentre Chrome non lo fa) per aggiungere 4 nel caso di Firefox, ottenendo così 'v' da 'native' in entrambi i casi (non riesco a trovare un altro 'v ': P).
L'analisi sembra un po 'fuori posto, ma è il meglio che posso fare per ora.


1
La domanda èDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian,

Grazie. Ora sto cercando di trovare un modo cross-browser per farlo ... "V" è una lettera sorprendentemente insolita ...
Peter C

@Ian - beh, presumibilmente, [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] lo farebbe?
enhzflep,

@JanDvorak - Non ho FF al momento. Cosa valuta? Se posso essere così presuntuoso da chiedere, è così.
enhzflep,

@enhzflep scusa, volevo dire "che non avrebbe funzionato in Chrome, d'altra parte"
John Dvorak,

4

Per il caso d'uso generale , se il case del personaggio non è una grande preoccupazione, potrei essere incline a imbrogliare un po '.

Crea la funzione "c" che trasforma un numero 0 .. 25 in un carattere.

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

Per motivi di prestazioni, pre-cache le lettere, se lo si desidera.

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

Nella console di Chrome, l'array risultante è simile al seguente:

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

Quindi ... potrebbe essere la tua vl[10+10+1] .

In alternativa, una soluzione generale come questa:

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

Oppure, per questo problema specifico , forse solo:

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

3

Questo dà av in Chrome:

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

E questo lo fa in Firefox:

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

Entrambi lo estraggono Object.prototype.preventExtensions(), quindi potresti probabilmente trovare un modo cross-browser per fare riferimento a quel metodo. (È l'unico nome di 17 caratteri in Object.Prototype per i principianti.)

Sentiti libero di costruire una versione più offuscata di questo e prenditi tutto il merito per te, sono fuori tempo;)


2

In Chrome, l'espressione ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])restituisce "function test() { [native code] }", la [1^11<<1]valuta in 23 (gli operatori bit a bit fanno sì che la variabile venga troncata a 32 bit)


La domanda èDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.