Search code examples
javascriptjsfuck

It is possible to call function with 2 params or more using JSFuck convention?


Suppose I have some string and I want to use function "replace" (ignore console.log and white chars in your head)

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

And I want to reduce used characters of this code using jsfuck (more info here) which I do by hand as follows (ignore log, comments, white chars, new lines )

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

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

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

As you can see I convert first code, to code which use only 6 characters: []{}!+ (this is idea of jsfuck)

Question: It is possible to call function replace with 2 arguments - Like that: "truefalse"["replace"]("true","1") and write it in similar way in JSF (without any kind of 'eval' which interpret string as code)? I have/see problem with comma which separate arguments... :(

PS: I give link to my fork of jsfuck (which is up to date - and produce much smaller output than jsfuck.com old site)


Solution

  • You can pass 2 arguments to a function by playing with Array.prototype.reduce.

    The idea is to call reduce on an array with 2 values, and pass only one argument (callback) to it (i.e. no argument for the reducing starting value). That way the first and second value of that array will serve as arguments to the callback, which will only be called once.

    In your example, the array with 2 values would have to be:

    ["true", "1"]
    

    which can be formed using concat:

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

    Then call reduce on that, and pass replace as the callback function:

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

    The only issue to resolve now is to ensure that the callback is called with the right this-binding, because "truefalse" does not play a role in the actual invocation of the callback call now. We can solve this with a call of .bind:

    So the expression to evaluate is this one

    console.log(
        ["true"]["concat"]("1")["reduce"](""["replace"]["bind"]("truefalse"))
    );