Suponga que tengo una cadena y quiero usar la función "reemplazar" (ignore console.log y los caracteres blancos en su cabeza)

console.log( 
    "truefalse"["replace"]("true") 
)

Y quiero reducir los caracteres usados de este código usando jsfuck (más información < a href = "https://github.com/aemkei/jsfuck" rel = "nofollow noreferrer"> aquí ) que hago a mano de la siguiente manera (ignorar el registro, comentarios, caracteres blancos, nuevas líneas)

console.log(
    // "truefalse"[
    ([]+!![]+![])[

    // long 'replace' word:
    []+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]

    // ]("true") 
    ]([]+!![])
);

Como puede ver, convierto el primer código a un código que usa solo 6 caracteres: [] {}! + (esta es la idea de jsfuck)

Pregunta: Es posible llamar a la función reemplazar con 2 argumentos - Así: "truefalse"["replace"]("true","1") y escribirlo de manera similar en JSF (sin ningún tipo de 'eval' que interprete la cadena como código) ? Tengo / veo un problema con la coma que separa los argumentos ... :(

PD: doy un enlace a mi bifurcación de jsfuck (que está actualizado, y produce una salida mucho menor que el sitio antiguo de jsfuck.com)

1
Kamil Kiełczewski 26 ago. 2020 a las 18:56

2 respuestas

La mejor respuesta

Puede pasar 2 argumentos a una función jugando con Array.prototype.reduce.

La idea es llamar a reduce en una matriz con 2 valores, y pasarle solo un argumento (devolución de llamada) (es decir, ningún argumento para el valor inicial de reducción). De esa manera, el primer y segundo valor de esa matriz servirán como argumentos para la devolución de llamada, que solo se llamará una vez.

En su ejemplo, la matriz con 2 valores tendría que ser:

["true", "1"]

Que se puede formar usando concat:

["true"]["concat"]("1")

Luego llame a reduce en eso, y pase replace como la función de devolución de llamada:

["true"]["concat"]("1")["reduce"]("truefalse"["replace"])

El único problema a resolver ahora es asegurarse de que la devolución de llamada se llame con el this - vinculante correcto, porque "truefalse" no juega un papel en la invocación real de la llamada de devolución de llamada ahora. Podemos resolver esto con una llamada de .bind:

Entonces la expresión a evaluar es esta

console.log(
    ["true"]["concat"]("1")["reduce"](""["replace"]["bind"]("truefalse"))
);
1
Kamil Kiełczewski 26 ago. 2020 a las 21:59

La pregunta 2 tiene una solución simple: prefiera el constructor new RegExp; p.ej. /e/g se convierte en new RegExp('e', 'g');

Lo siguiente resolvería la pregunta 1 si no dependiera del operador ...:

Nosotras podemos reemplazar:

console.log('a', 'b', 'c');

Con:

console.log(...[ 'a' ].concat([ 'b' ]).concat([ 'c' ]));

El uso de .concat nos permite agrupar valores sin usar comas.

Estoy cerca de decir que la pregunta 1 no se puede resolver correctamente sin interpretar una cadena como código js (editar: ¡refutado por trincot!):

  • Los argumentos deberán mantenerse en una matriz (los argumentos directos no se pueden usar ya que siempre requieren comas; la matriz es el único tipo de datos que se puede convertir en argumentos)
  • Deberá usar Function.prototype.apply para consumir argumentos de matriz
  • Function.prototype.apply siempre requerirá el uso de una coma, para separar el valor this de la matriz de argumentos
  • La única forma de evitar múltiples argumentos a Function.prototype.apply es aplicar alguna forma de curry
  • Todo el curry será facilitado por Function.prototype.(apply|bind|call)
  • ¡Los tres métodos de curación requieren múltiples argumentos y, por lo tanto, necesitan comas!
1
Gershom 26 ago. 2020 a las 18:39