这个神奇的Javascript如何工作?

Tru*_*gDQ 65 javascript obfuscation deobfuscation

这是一个警告"Hello world"的小javascript:

????=/??´??~???//*´??*/['_'];o=(???)=_=3;c=(???)=(???)-(???);(???)=(???)=(o^_^o)/(o^_^o);(???)={???:'_',????:((????==3)+'_')[???],????:(????+'_')[o^_^o-(???)],????:((???==3)+'_')[???]};(???)[???]=((????==3)+'_')[c^_^o];(???)['c']=((???)+'_')[(???)+(???)-(???)];(???)['o']=((???)+'_')[???];(?o?)=(???)['c']+(???)['o']+(????+'_')[???]+((????==3)+'_')[???]+((???)+'_')[(???)+(???)]+((???==3)+'_')[???]+((???==3)+'_')[(???)-(???)]+(???)['c']+((???)+'_')[(???)+(???)]+(???)['o']+((???==3)+'_')[???];(???)['_']=(o^_^o)[?o?][?o?];(???)=((???==3)+'_')[???]+(???).????+((???)+'_')[(???)+(???)]+((???==3)+'_')[o^_^o-???]+((???==3)+'_')[???]+(????+'_')[???];(???)+=(???);(???)[???]='\\';(???).????=(???+???)[o^_^o-(???)];(o???o)=(????+'_')[c^_^o];(???)[?o?]='\"';(???)['_']((???)['_'](???+(???)[?o?]+(???)[???]+(???)+(???)+(???)+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+(???)+((???)+(???))+(???)[???]+(???)+((o^_^o)+(o^_^o))+((o^_^o)-(???))+(???)[???]+(???)+((o^_^o)+(o^_^o))+(???)+(???)[???]+((???)+(???))+(c^_^o)+(???)[???]+(???)+((o^_^o)-(???))+(???)[???]+(???)+(???)+(c^_^o)+(???)[???]+(???)+(???)+((???)+(???))+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+((???)+(???))+((???)+(o^_^o))+(???)[???]+(???)+(c^_^o)+(???)[???]+(???)+((o^_^o)-(???))+((???)+(o^_^o))+(???)[???]+(???)+((???)+(???))+((???)+(o^_^o))+(???)[???]+(???)+((o^_^o)+(o^_^o))+((o^_^o)-(???))+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+(???)+(???)+(???)[???]+(???)+((o^_^o)-(???))+(???)[???]+((???)+(???))+(???)+(???)[?o?])(???))('_');
Run Code Online (Sandbox Code Playgroud)

好看的版本:

???? = /??´??~???//*´??*/['_'];
o = (???) = _ = 3;
c = (???) = (???) - (???);
(???) = (???) = (o^_^o)/(o^_^o);
(???) = {
  ???:  '_',
  ????: ((????==3)+'_')[???],
  ????: (????+'_')[o^_^o-(???)],
  ????: ((???==3)+'_')[???]
};
(???)[???] = ((????==3)+'_')[c^_^o];
(???)['c'] = ((???)+'_')[(???)+(???)-(???)];
(???)['o'] = ((???)+'_')[???];
(?o?)=(???)['c'] + (???)['o'] + (???? + '_')[???] + ((????==3) + '_')[???] + ((???) + '_')[(???) + (???)] + ((???==3) + '_')[???] + ((???==3) + '_')[(???) - (???)] + (???)['c'] + ((???) + '_')[(???) + (???)] + (???)['o'] + ((???==3) + '_')[???];
(???)['_'] = (o^_^o)[?o?][?o?];
(???) = ((???==3) + '_')[???] + (???).???? + ((???) + '_')[(???) + (???)] + ((???==3) + '_')[o^_^o-???] + ((???==3) + '_')[???] + (????+'_')[???];
(???) += (???);
(???)[???] = '\\';
(???).???? = (???+???)[o^_^o-(???)];
(o???o) = (????+'_')[c^_^o];
(???)[?o?] = '\"';
(???)['_']((???)['_'](???+(???)[?o?]+(???)[???]+(???)+(???)+(???)+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+(???)+((???)+(???))+(???)[???]+(???)+((o^_^o)+(o^_^o))+((o^_^o)-(???))+(???)[???]+(???)+((o^_^o)+(o^_^o))+(???)+(???)[???]+((???)+(???))+(c^_^o)+(???)[???]+(???)+((o^_^o)-(???))+(???)[???]+(???)+(???)+(c^_^o)+(???)[???]+(???)+(???)+((???)+(???))+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+((???)+(???))+((???)+(o^_^o))+(???)[???]+(???)+(c^_^o)+(???)[???]+(???)+((o^_^o)-(???))+((???)+(o^_^o))+(???)[???]+(???)+((???)+(???))+((???)+(o^_^o))+(???)[???]+(???)+((o^_^o)+(o^_^o))+((o^_^o)-(???))+(???)[???]+(???)+((???)+(???))+(???)+(???)[???]+(???)+(???)+(???)+(???)[???]+(???)+((o^_^o)-(???))+(???)[???]+((???)+(???))+(???)+(???)[?o?])(???))('_');
Run Code Online (Sandbox Code Playgroud)

的jsfiddle

取自这里:https://codegolf.stackexchange.com/a/24041/17049

任何人都知道它是如何工作的?我甚至没有看到该alert代码.

Gum*_*mbo 110

在仔细研究代码之前,您必须知道,因为JavaScript 1.5 标识符不仅包含ASCII字符,还包含Unicode字符.

在这种情况下,许多这些有趣的序列只是标识符.通过更简单的标识符交换这些标识符并删除不必要的注释和括号后,代码如下所示:

a = /??´??~???/['_'];
o = b = _ = 3;
c = d = b-b;
e = d = o^_^o/o^_^o;
e = {
  d: '_',
  a: ((a==3)+'_')[d],
  h: (a+'_')[o^_^o-d],
  i: ((b==3)+'_')[b]
};
e[d]   = ((a==3)+'_')[c^_^o];
e['c'] = (e+'_')[b+b-d];
e['o'] = (e+'_')[d];
f      = e['c']+e['o']+(a+'_')[d]+((a==3)+'_')[b]+(e+'_')[b+b]+((b==3)+'_')[d]+((b==3)+'_')[b-d]+e['c']+(e+'_')[b+b]+e['o']+((b==3)+'_')[d];
e['_'] = (o^_^o)[f][f];
g      = ((b==3)+'_')[d]+e.i+(e+'_')[b+b]+((b==3)+'_')[o^_^o-d]+((b==3)+'_')[d]+(a+'_')[d];
b      += d;
e[g]   = '\\';
e.j    = (e+b)[o^_^o-d];
obo    = (a+'_')[c^_^o];
e[f]   = '\"';
e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');
Run Code Online (Sandbox Code Playgroud)

现在我们可以一次评估每个语句:

  • a = /??´??~???/['_'] 评估为 a = undefined
  • o = b = _ = 3分配o,b_整数3
  • c = d = b-b分配cd整数0
  • e = d = o^_^o/o^_^o赋值ed整数1(o^_^o计算结果为3 XOR 3 XOR 3,产生3)
  • e = { d: '_', a: ((a==3)+'_')[d], h: (a+'_')[o^_^o-d], i: ((b==3)+'_')[b] }分配e对象{ d: '_', a: 'a', h: 'd', i: 'e' }
  • e[d] = ((a==3)+'_')[c^_^o]分配e[1]字符串'f'
  • e['c'] = (e+'_')[b+b-d]分配e['c']字符串'c'
  • e['o'] = (e+'_')[d]分配e['o']字符串'o'

这只是设置,并设置了以下变量:

a = undefined
b = 3
c = 0
d = 1
e = {
    1: "f",
    a: "a",
    c: "c",
    d: "_",
    h: "d",
    i: "e",
    o: "o"
}
Run Code Online (Sandbox Code Playgroud)

下一个语句是第一个构造东西的语句:

f = e['c'] +             // => "c"
    e['o'] +             // => "o"
    (a+'_')[d] +         // => "undefined_"[1] = "n"
    ((a==3)+'_')[b] +    // => "false_"[3]     = "s"
    (e+'_')[b+b] +       // => "object_"[6]    = "t"
    ((b==3)+'_')[d] +    // => "true_"[1]      = "r"
    ((b==3)+'_')[b-d] +  // => "true_"[2]      = "s"
    e['c'] +             // => "c"
    (e+'_')[b+b] +       // => "object_"[6]    = "t"
    e['o'] +             // => "o"
    ((b==3)+'_')[d];     // => "true"[1]       = "r"
Run Code Online (Sandbox Code Playgroud)

所以f = "constructor".在下一个语句中,这"constructor"用于检索函数:

e['_'] = (o^_^o)[f][f]
Run Code Online (Sandbox Code Playgroud)

这相当于(3).constructor.constructor产生函数Function,因此:

e['_'] = Function
Run Code Online (Sandbox Code Playgroud)

这个Function函数很特殊,因为可以通过参数传递函数体代码来动态构造函数:

f = Function("alert(1)")
// equivalent to
f = function() { alert(1) }
Run Code Online (Sandbox Code Playgroud)

我将跳过接下来的几个语句,然后编写结果变量和值:

a = undefined
b = 4
c = 0
d = 1
e = {
    1: "f",
    _: Function,
    a: "a",
    c: "c",
    constructor: "\"",
    d: "_",
    h: "d",
    i: "e",
    j: "b",
    o: "o",
    return: "\\"
}
f = "constructor"
obo = "u"
Run Code Online (Sandbox Code Playgroud)

最后一个陈述完成了最后的工作:

e['_'](e['_'](g+e[f]+e[g]+d+b+d+e[g]+d+(b+d)+b+e[g]+d+b+(b+d)+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+((o^_^o)+(o^_^o))+b+e[g]+(b+d)+(c^_^o)+e[g]+b+((o^_^o)-d)+e[g]+d+d+(c^_^o)+e[g]+d+b+(b+d)+e[g]+d+(b+d)+b+e[g]+d+(b+d)+b+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+b+(c^_^o)+e[g]+d+((o^_^o)-d)+(b+(o^_^o))+e[g]+d+(b+d)+(b+(o^_^o))+e[g]+d+((o^_^o)+(o^_^o))+((o^_^o)-d)+e[g]+d+(b+d)+b+e[g]+d+b+b+e[g]+b+((o^_^o)-d)+e[g]+(b+d)+d+e[f])(d))('_');
Run Code Online (Sandbox Code Playgroud)

这相当于:

Function(Function( … )(1))('_')
Run Code Online (Sandbox Code Playgroud)

long表达式构建以下字符串:

return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"
Run Code Online (Sandbox Code Playgroud)

转义字符串计算:

alert("Hello World")
Run Code Online (Sandbox Code Playgroud)

return代码传递给Function,它创建一个匿名函数,如:

function anonymous() {
    return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51";
}
Run Code Online (Sandbox Code Playgroud)

我们知道,相当于:

function anonymous() {
    return"alert(\"Hello World\")";
}
Run Code Online (Sandbox Code Playgroud)

然后使用1as参数执行此函数,该参数返回结果字符串:

alert("Hello World")
Run Code Online (Sandbox Code Playgroud)

然后Function再次传递给它,这将创建一个新的匿名函数:

function anonymous() {
    alert("Hello World");
}
Run Code Online (Sandbox Code Playgroud)

最后,还使用'_'as参数调用此函数.

  • 谢谢,等待这个答案.写这篇文章的家伙很精彩,我从这个答案和[他的博客](http://utf-8.jp/)中学到了很多东西. (2认同)

sab*_*bof 15

这里有很多东西.变量附近的括号不起作用.

基本上他构造了这个字符串:

return"\141\154\145\162\164\50\42\110\145\154\154\157\40\127\157\162\154\144\42\51"
Run Code Online (Sandbox Code Playgroud)

这是一个转义版本

return "alert(\"Hello World\")"
Run Code Online (Sandbox Code Playgroud)

最后这样做:

Function(Function('return "alert(\\"Hello World\\")"')())()
Run Code Online (Sandbox Code Playgroud)

双重Function似乎是一件随意的事情,但事实并非如此.Function()将字符串中的反斜杠解释为转义字符.所以第一个调用解码,第二个调用执行.

Function("return '\\110\\145\\154\\154\\157'")()
// => "Hello"
Run Code Online (Sandbox Code Playgroud)

这是相同的代码,更好的格式化,以及"正常"变量名称;

var1=/??´??~???//*´??*/['_'];
three=(threeThenFour)=_=3;
c=(one)=(threeThenFour)-(threeThenFour);
(anObject)=(one)=(three)/(three);
(anObject)={
  one:'_',
  var1:((var1==3)+'_')[one],
  var2?:(var1+'_')[three-(one)],
  var4?:((threeThenFour==3)+'_')[threeThenFour]
};
(anObject)[one]=((var1==3)+'_')[c ^ _ ^ three];
(anObject)['c']=((anObject)+'_')[(threeThenFour)+(threeThenFour)-(one)];
(anObject)['three']=((anObject)+'_')[one];
(theConstructor)=(anObject)['c']+
  (anObject)['three']+
  (var1+'_')[one]+
  ((var1==3)+'_')[threeThenFour]+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  ((threeThenFour==3)+'_')[one]+
  ((threeThenFour==3)+'_')[(threeThenFour)-(one)]+
  (anObject)['c']+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  (anObject)['three']+
  ((threeThenFour==3)+'_')[one];

// theConstructor => "constructor" 

(anObject)['_']=(three)[theConstructor][theConstructor];
(theReturn)=((threeThenFour==3)+'_')[one]+
  (anObject).var4?+
  ((anObject)+'_')[(threeThenFour)+(threeThenFour)]+
  ((threeThenFour==3)+'_')[three-one]+
  ((threeThenFour==3)+'_')[one]+
  (var1+'_')[one];

// theReturn => "return"

(threeThenFour)+=(one);
(anObject)[theReturn]='\\';
(anObject).var3?=(anObject+threeThenFour)[three-(one)];
(ovar2o)=(var1+'_')[c ^ _ ^ three];
(anObject)[theConstructor]='\"';

// (anObject)['_'] => Function

(anObject)['_'](
  (anObject)['_'](theReturn+
                 (anObject)[theConstructor]+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 (one)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+(
                   threeThenFour)+
                 ((threeThenFour)+(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 ((threeThenFour)+(one))+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (threeThenFour)+((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+(one)+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 ((threeThenFour)+(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (threeThenFour)+
                 (c ^ _ ^ three)+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)-(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 ((threeThenFour)+(three))+
                 (anObject)[theReturn]+
                 (one)+
                 ((three)+(three))+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 (one)+
                 ((threeThenFour)+(one))+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (one)+
                 (threeThenFour)+
                 (threeThenFour)+
                 (anObject)[theReturn]+
                 (threeThenFour)+
                 ((three)-(one))+
                 (anObject)[theReturn]+
                 ((threeThenFour)+(one))+
                 (one)+
                 (anObject)[theConstructor]
                )
  (one)
)('_');
Run Code Online (Sandbox Code Playgroud)

  • @RoyiNamir没有.我将仲裁重命名为`var1`.它运行JavaScript,而不是"最佳实践"JavaScript.你在这里找不到任何`var`. (2认同)

Shi*_*hah 9

让我解释一下关键步骤:

代码创建一个名为Д的对象,然后添加一个'_'具有魔术JavaScript 函数构造函数值的属性.在JavaScript中,您可以将任何字符串作为代码执行,方法是将其传递给Function构造函数.

如何(???)['_']包含Function构造函数?这是通过以下方式完成的巧妙技术:

(???)['_'] = (o^_^o)[?o?][?o?];
Run Code Online (Sandbox Code Playgroud)

这里o和_设置为3.所以o^_^o返回3.显然作者可能刚刚使用o因为o^_^o返回相同的值,但我猜他对混淆有很好的品味:).所以上面的表达现在变成了(3)[?o?][?o?].

的值?o?在方括号设置为字符串"构造",是由串联在前面的语句建.它使用一种非常聪明的方法来构建字符串"constructor",方法是从内置的JavaScript字符串中删除单个字符,例如"object","true","false"和"undefined",它们是从转换为字符串的JavaScript表达式生成的.显然作者找不到字符"c"来从这些内置字符串中删除,所以他必须明确地写出这个字符串.请注意,方括号中的字符是゚o゚,它是Unicode字符,而不是圆括号中使用的简单o,尽管两者看起来非常相似.执行(3)("constructor")此操作时,返回Number构造函数.Number构造函数的构造函数是Function构造函数.所以通过(3)("constructor")("constructor")你得到函数构造函数,现在你可以最终传递一个任意字符串来执行它.

最后一行构建字符串"alert(\"Hello World\")"并将其传递给Function构造函数以执行.

问题是如何在"alert(\"Hello World\")"不输入实际字母的情况下获取该字符串?聪明的技术是使用\xxxxxx是八进制数并转换为字符的位置.要获得此字符串,您需要的数字是0,1,2,3,4,5,6,7和8.但实际上并不需要所有这些,而是​​可以通过三个数字0的简单算法生成它们例如,要生成'a'"警报"中的字符,您需要ASCII十进制97或八进制141,即\141.如果只有0,1和4存储在上面对象的某个属性中,则可以将它们连接起来生成'a'.这样你就可以生成任何字符串,即使你拥有的所有字符串都是0,1和4存储在Д对象的某些属性中.聪明?你打赌!