本文介绍了JSFuck:调用具有2个(或更多)参数的函数序列,而无需嵌套的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是此问题的延续,但情况更为复杂.假设我想使用2个参数调用字符串函数,例如

  console.log("truefalse" .replace("true",1)) 

第一步,我减少设置为 jsfuck 约定的字符6个可用字符: []()!+ ,并带有以'' chars包围的z字母和数字-JS字符串(易于转换为这6个字符):

  console.log("truefalse" [替换"]("true","1")) 

这里的问题是逗号(禁止字符),但是我们可以通过使用 trincot 发现的聪明技巧来解决此问题.:

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

但是出现了新问题:

可以调用具有两个(或多个)参数的函数序列而不嵌套它们(由上述技术强加),而是以流"形式进行.我们在右侧调用下一个函数的方式,例如:"truefalse" .replace("true",1).replace("false",0).. (不使用"eval"之类的将字符串解释为代码的解决方案)?(对于具有一个参数的函数,可能例如:"truefalse" [["replace"]]("true")["replace"]("false")))

解决方案

是的,有可能.

因此,我们从省略逗号的表达式开始,它仅由字符串文字和JSF字符组成:

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

有一会儿,我将使用更易读的点表示法来表达该表达式,然后返回逗号分隔符以获取数组文字:

  ["true","1"].reduce(.replace.bind("truefalse"))) 

这具有位于末尾的替换输入,即"truefalse".另一方面,参数位于左侧,即真"位置.和"1".我们可以尝试使"truefalse"成为可能.也是一个参数,以便我们可以将其移到左侧.

为此,我们可以使用.".replace.apply 代替.".replace 作为 reduce 的回调. apply 的第一个参数是 replace 调用的 this 绑定.第二个参数应该是要传递给 replace 的参数数组,因此,这是我们当前位于左侧的数组.

然后 apply 方法本身也应获得 this 绑定.我们得到以下表达式:

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

NB:".replace.apply 可以引用任何其他函数,而不是 replace ,只要它是一个函数即可.我们只需要一种方法来引用 Function.prototype.apply 函数.

因此,我们成功地将"truefalse"移动到了表情更多地放在最前面.但是,如果我们要实现非嵌套链接,它实际上不应放在数组文字中.

我们可以在此处使用功能" split 方法的方法:如果不传递任何参数,它将返回带有原始字符串的数组.正是我们需要的.

所以:

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

现在我们可以连锁了!

最后,下面是删除点和逗号的相同表达式:

  console.log("truefalse" [" split]()[" concat]([[[" true] [" concat](" 1)])[减少"](" [替换"] [应用"] [绑定"](" [替换"])));  

...并且要进行链接,您只需使用 [" split]() ... etc.

继续表达式.

This is continuation of this question with more difficult case. Suppose I want to call string function with 2 parameters e.g.

console.log(
  "truefalse".replace("true",1)
)

In first step I reduce characters set to jsfuck convention where we have 6 available characters: []()!+ and with a-z letters and numbers surrounded by " chars - JS strings (which are easy to convert to those 6 chars):

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

The problem here was comma (forbidden character) but we can overcome this problem by use following clever technique discovered by trincot:

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

But the new question arise:

It is possible to call sequence of functions with 2 (or more) parameters without nesting them (which is imposed by above technique) but in "flow" way where we call next function in right side eg.: "truefalse".replace("true",1).replace("false",0)..(without using 'eval' like solution where string is interpreted as code) ? (for function with one parameter it is possible e.g.: "truefalse"["replace"]("true")["replace"]("false") )

解决方案

Yes, it is possible.

So we start with the expression that omits the comma, and only consists of string literals and the JSF characters:

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

For a moment, I will phrase this expression using the more readable dot notation, and go back to the comma separator for array literals:

["true", "1"].reduce("".replace.bind("truefalse"))

This has the input of the replacement, i.e. "truefalse", sitting at the end. The parameters, on the other hand, are located at the left, i.e. "true" and "1". We could try to make "truefalse" also an argument, so that we could move it to the left.

For that purpose we can use "".replace.apply instead of "".replace as callback to reduce. The first argument of apply is the this-binding for the replace call. The second argument should be the array of arguments to pass to replace, so that is the array we currently have at the left.

And then the apply method itself should also get a this-binding. We get this expression:

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

NB: "".replace.apply could reference any other function instead of replace, as long as it is a function. We just need a way to reference the Function.prototype.apply function.

So, we have succeeded to move the "truefalse" expression more to the front. But it really should not sit in an array literal if we want to achieve non-nested chaining.

Here we can use a "feature" of the split method: if you don't pass any argument, it returns an array with the original string. Exactly what we need.

So:

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

Now we can chain!

So, to finalise, here is the same expression with the dots and commas removed:

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

...and to chain, you just continue the expression with ["split"]() ...etc.

这篇关于JSFuck:调用具有2个(或更多)参数的函数序列,而无需嵌套的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 16:01