¿Cuáles son las cadenas incorporadas de JavaScript?


147

esta pregunta es difícil de resumir en un título de pregunta

ACTUALIZACIÓN creé una jsFiddle que construye una cadena ofuscado de su entrada en función de las cartas extraídas de esta pregunta: ¿Se puede acceder a él aquí , o habría un GIST ser más fácil?

Recientemente me encontré con un poco de JavaScript ofuscado en este perfil que se ve así:

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]

Lamento arruinar la sorpresa, pero cuando se evalúa esto devuelve esto:

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

La forma en que esto funciona cuando se divide es generar una serie de mensajes y extraer letras de ellos de esta manera (usando la "I" como ejemplo):

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

Otras cadenas que se generan incluyen:

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

Estaba interesado en encontrar un reemplazo para la "n" y "[" y se me ocurrió esto:

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

Lo que siento en el espíritu de usar 1 y 0, pero viola uno de los aspectos más elegantes del código original, que es la apariencia de no tener nada que ver con las cadenas. ¿Alguien más tiene una idea de cómo generar una "v" que esté de acuerdo con el código ofuscado original?

Aquí hay información adicional que se encontró después de que muchos programadores de JavaScript con talento le echaran un vistazo más profundo a esto

Firefox devuelve "I Ione you" debido a esta línea:

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

[1^11<<1] recorta un carácter específico de esto:

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

Lo que se evalúa a esto:

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

¡Lo que parece que podríamos tener nuestra "V"!

Chrome devuelve "Te amo", porque el mismo código devuelve esto:

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

Antes de cerrar la pregunta por una conexión cuestionable con "un problema de programación real", pensé que agregaría una solución resumida que se basa en @ Supr , @ Cory y @ alpha123 , he aquí:

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

Dada la complejidad del código y el mensaje que produce, es casi como si el motor de JavaScript dijera lo especial que lo hace sentir :)


9
Sí dice "amor" en la consola de Chrome. i.imgur.com/rVyKMoP.png
bfavaretto

2
¿Qué pasa si quita las letras que no son del function test() { [native code] }, entonces podría normalizarlo y extraer la letra que desea
Jason Sperske

44
Basando el código en una salida de cadena no definida por estándares para imprimir un mensaje usando código ofuscado ... Llamo a esto de una manera demasiado localizada.

2
@ Ian, cierto. Si las personas que amo en mi vida realmente se preocuparan por mí, usarían Chrome :)
Jason Sperske

44
La mejor parte de esto es la advertencia que da mi editor de texto: "Uso confuso de '!'"
Jake Johnson

Respuestas:


83

En primer lugar, me gustaría agradecer a Jason y a todos los colaboradores por jugar con ese fragmento divertido. He escrito ese código solo por diversión para enviárselo a mi esposa el 14 de febrero :) Teniendo solo Chrome instalado en la computadora portátil, no tenía opciones para verificar cómo funciona en Firefox e IE. Además, realmente no esperaba que la toString()representación de los métodos incorporados se vea diferente en otros navegadores.

Ahora, pasando al problema real , echemos un vistazo al código. Sí, "v"fue el verdadero "problema" aquí. No encontré otras formas de obtener esta carta, excepto analizar la [native code]cadena, que se puede tomar de cualquier método incorporado. Como me limité a no tener cadenas ni números excepto los 1utilizados, necesitaba explotar algún método que solo tenga caracteres disponibles en su nombre.

Los caracteres disponibles se pueden obtener de las palabras clave existentes y las representaciones de cadena, es decir, desde el principio tuvimos NaN, null, undefined, Infinity, true, false, y "[object Object]". Algunos de ellos se pueden convertir fácilmente en cadenas, por ejemplo, 1/!1+[]da "Infinity".

He analizado diferentes métodos incorporados para matrices [], objetos {}, expresiones regulares /(?:)/, números 1.1, cadenas "1", y descubrí un hermoso método de RegExpobjeto llamado test(). Su nombre puede ser montado a partir de todos los caracteres disponibles, por ejemplo, "t"y "e"de truey "s"de false. Creé una cadena "test"y abordé este método usando la notación de corchetes para la expresión regular de expresiones regulares /-/, identificada correctamente en esta línea:

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

Como ya se discutió, este fragmento de código se evalúa en Chrome como:

function test() { [native code] }

en Firefox como:

function test() {
    [native code]
}

y en IE como:

 function test() {     [native code] }  

(en este último, preste especial atención al espacio antes de la functionpalabra clave)

Entonces, como puede ver claramente, mi código estaba obteniendo el carácter 24 de la cadena presentada, que en Chrome era "v"(como estaba planeado), pero desafortunadamente en Firefox e IE, "n"y "["respectivamente.

Para hacer la misma salida en todos los navegadores, he usado un enfoque diferente al ilustrado en las otras respuestas. Ahora la versión modificada se ve así:

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]

Sin embargo, para intrigar a los lectores, no proporcionaré una solución para eso. Sinceramente, creo que comprenderá fácilmente cómo funciona ... y algunos incluso pueden sorprender a sus seres queridos de manera cruzada;)

PD: otro ofuscador

Inspirado por la idea de Jason de crear una herramienta de ofuscación universal, he escrito una más. Puede encontrarlo en JSBin: http://jsbin.com/amecoq/2 . Puede ofuscar cualquier texto que contenga números [0-9], letras latinas pequeñas [a-z]y espacios. La longitud de la cadena está limitada principalmente con su RAM (al menos el cuerpo de mi respuesta se ofuscó con éxito). La salida es compatible con Chrome, Firefox e IE.

Sugerencia: la herramienta utiliza un enfoque de ofuscación diferente al presentado anteriormente.


44
"constructor" ... wow, eso es increíble y mantuviste el rectángulo perfecto con saltos de línea válidos Eres bueno
Jason Sperske

1
Creé un Obfuscator que crea una cadena de acuerdo con sus reglas de estilo: jsfiddle.net/w9rFF/8
Jason Sperske

@JasonSperske ¡Ese fue un buen truco! ¡Buen trabajo! Intentaré contribuir a ello.
VisioN

26

¿Por qué no native codese usa la parte de la pregunta? Este da un 'v'tanto en Chrome como en 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]

Edite para admitir IE y hágalo sin el operador ternario: este funciona en Chrome, IE y FF. Crea una matriz y la usa ==para determinar el navegador.

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

Legible:

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

Eso es interesante. Originalmente se descartó que la ubicación de las palabras "código nativo" fuera impredecible entre Firefox y Chrome. Esto resuelve eso pero no funciona en IE10 (donde devuelve "i"). Aún así, me pregunto si esta opción podría ofrecer algunas ideas nuevas
Jason Sperske

La idea es simplemente seleccionar tanto ny vy sólo debes elegir el que sea más grande: str[23]>str[27]?str[23]:str[27]. En otras palabras, el operador terciario es el truco. También se podría ampliar para admitir IE:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)]
Supr

1
Su respuesta fue primero (antes del creador del código original), pero sentí que su respuesta podría considerarse lógicamente la correcta. Aún gran trabajo (y de un merecido hasta 13 votos)
Jason Sperske

1
Nitpick menor: un operador terciario es el tercer operador más importante, después del primario y secundario. Un operador que toma tres operandos es ternario.
Eric Lippert

1
@EricLippert, gah, incluso lo busqué en Google para asegurarme de que estaba usando el término correcto, ¡pero aún así terminé con el incorrecto! Gracias, corregido.
Supr

8

Esto es lo más cerca que pude llegar, desafortunadamente viola la convención de la ofuscación original al hacer una llamada a unescape():

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

Demoler:

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

Otras ideas:

  1. De alguna manera llegar a unescape("\x76")
  2. Convertir de alguna manera 118sin llamarString.fromCharCode()
  3. Obtenga el texto de una excepción con la palabra "Inválido"

Actualizaciones:

Empecé a jugar golf de código y lo he hecho más corto, reemplazando partes con más 1s, etc.


Tambien, me gusta este. Estoy un poco desgarrado en seleccionar una respuesta "correcta", ya que tanto la suya como la de @ alpha123 se ven extremadamente ofuscadas y ocultan hábilmente la intención original.
Jason Sperske

Y el soporte de IE10 sella el trato (con sinceras disculpas @ alpha123 por la excelente respuesta)
Jason Sperske

Puede reemplazar eso '%'con la (/%/+[[]+1/!1])[1]eliminación de las comillas. También he agregado el l=unescape;uso de minúsculas Lpara ocultar la referencia unescape. Esto ha sido divertido :)
Jason Sperske

@JasonSperske: Aún más corto:(/%/+[])[1]
Cᴏʀʏ

1
O podrías nombrar tu variable $1;
Cᴏʀʏ

4

Aquí está la parte que genera el n / v:

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

En Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])evalúa a

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

mientras que en Chrome es

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

1^11<<1 es igual a 23. Entonces, debido al espacio en blanco adicional de Firefox, esto no es suficiente para llegar a la 'v', sino que es 'n'.

Y esta es la razón por la que no debe confiar en el comportamiento de Function # toString. ;)

EDITAR: Finalmente encontré una versión de navegador cruzado razonablemente ofuscada:

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

Esto reemplaza la sección 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)]

que explota las diferencias en parseInt (aparentemente Firefox analiza los números que comienzan con 0 como octal, mientras que Chrome no lo hace) para agregar 4 en el caso de Firefox, obteniendo así 'v' de 'nativo' en ambos casos (no puedo encontrar otro 'v ' :PAGS).
El análisis parece un poco fuera de lugar, pero eso es lo mejor que puedo hacer por ahora.


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

Gracias. Ahora estoy tratando de encontrar una manera de hacerlo
Peter C

@ Ian - bueno, entonces presumiblemente, [(1 ^ 11 << 1) + 1 + 1 + 1 + 1] lo haría?
enhzflep

@ JanDvorak - No tengo FF en este momento. ¿A qué se evalúa? Si puedo ser tan presuntuoso como para preguntar, eso es.
enhzflep

@enhzflep lo siento, quise decir "eso no funcionaría en Chrome, por otro lado"
John Dvorak

4

Para el caso de uso general , si la carcasa del personaje no es una gran preocupación, podría estar inclinado a hacer un poco de trampa.

Cree la función "c" que convierte un número 0 .. 25 en un carácter.

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

Por razones de rendimiento, pre-cachee las letras, si lo desea.

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

En la consola de Chrome, la matriz resultante se ve así:

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

Entonces ... tu v podría ser l[10+10+1].

Alternativamente, una solución general como esta:

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

O, para este problema específico , tal vez solo:

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

3

Esto le da av en Chrome:

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

Y esto lo hace en Firefox:

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

Ambos lo sacan Object.prototype.preventExtensions(), por lo que probablemente pueda encontrar una forma de navegador cruzado para hacer referencia a ese método. (Es el único nombre de 17 caracteres en Object.Prototype para empezar).

Siéntase libre de construir una versión más ofuscada de esto y tomar todo el crédito por usted mismo, estoy fuera de tiempo;)


2

En Chrome, la expresión se ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])evalúa como "function test() { [native code] }", se [1^11<<1]evalúa como 23 (los operadores bit a bit hacen que la variable se trunca a 32 bits)


La pregunta esDoes anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Ian
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.