Ответ 1
Если вы заметили, что сразу после назначения значения $
($
становится целым числом), jquery фактически не используется в этом коде.
// ~ is bitwise not, so this set $ = -1
$ = ~ [];
Следующий код создает объект javascript. Поскольку ![]
- false
, (![] + "")
преобразует логическое значение в строку, "false"
. Каждый [$]
захватывает букву в указанном индексе, $
, в строке, "false"
или других других возвращаемых значениях. Код хранит целые числа и буквы в объекте, а затем присваивает его $
.
$ = {
___: ++$, // 0 since $ was -1
$$$$: (![] + "")[$], // "f"
__$: ++$, // 1
$_$_: (![] + "")[$], // "a"
_$_: ++$, // 2
$_$$: ({} + "")[$],
$$_$: ($[$] + "")[$], // "b"
_$$: ++$, // see the patter when ++$ is assigned?
$$$_: (!"" + "")[$], // see the pattern with the letters?
$__: ++$,
$_$: ++$,
$$__: ({} + "")[$],
$$_: ++$,
$$$: ++$,
$___: ++$,
$__$: ++$
};
Приведенные выше идеи аналогичны изложенным выше. Каждая часть (разделенная символом +) возвращает букву на основе возвращаемого значения, которые затем объединяются для формирования строки.
// "constructor"
$.$_ = ($.$_ = $ + "")[$.$_$] + ($._$ = $.$_[$.__$]) + ($.$$ = ($.$ + "")[$.__$]) + ((!$) + "")[$._$$] + ($.__ = $.$_[$.$$_]) + ($.$ = (!"" + "")[$.__$]) + ($._ = (!"" + "")[$._$_]) + $.$_[$.$_$] + $.__ + $._$ + $.$;
Приведенный ниже код присваивает "return"
и function Function() { [native code] }
.
// "return"
$.$$ = $.$ + (!"" + "")[$._$$] + $.__ + $._ + $.$ + $.$$;
// function Function() { [native code] }
$.$ = ($.___)[$.$_][$.$_];
В заключительных строках
$.$$ + "\"" + $.$_$_ + (![] + "")[$._$_] + $.$$$_ + "\\" + $.__$ + $.$$_ + $._$_ + $.__ + "(\\\"\\" + $.__$ + $.__$ + $.___ + "\\" + $.__$ + $.$_$ + $.__$ + "!\\\");" + "\""`
эквивалентно
"return"ale\162t(\"\110\151!\");""
При передаче в $.$()
он становится функцией
function anonymous() { return "alert(\"Hi!\");"; }
Затем окончательный оператор, который фактически выполняет предупреждение.
$.$($.$($.$$ + "\"" + $.$_$_ + (![] + "")[$._$_] + $.$$$_ + "\\" + $.__$ + $.$$_ + $._$_ + $.__ + "(\\\"\\" + $.__$ + $.__$ + $.___ + "\\" + $.__$ + $.$_$ + $.__$ + "!\\\");" + "\"")())();
Чтобы облегчить понимание всей концепции, я также предоставил полудеоббащенный код.
obj = {
___: ++index, // = 0
$$$$: (![] + "")[index], // = "f" from 'f'alse
__$: ++index, // = 1
$_$_: (![] + "")[index], // = "a" from f'a'lse
_$_: ++index, // = 2
$_$$: ({} + "")[index], // = "b" from [o'b'ject Object]
$$_$: (index[index] + "")[index], // = "d" from un'd'efined
_$$: ++index, // = 3
$$$_: (!"" + "")[index], // = "e" from tru'e'
$__: ++index, // = 4
$_$: ++index, // = 5
$$__: ({} + "")[index], // = "c" from [obje'c't Object]
$$_: ++index, // = 6
$$$: ++index, // = 7
$___: ++index, // = 8
$__$: ++index // = 9
};
// obj.$_ = "c" + "o" + "n" + "s" + "t" + "r" + "u" + "c" + "t" + "o" + "r";
obj.$_ = (obj.$_ = obj + "")[obj.$_$] + (obj._$ = obj.$_[obj.__$]) + (obj.$$ = (obj.$ + "")[obj.__$]) + ((!obj) + "")[obj._$$] + (obj.__ = obj.$_[obj.$$_]) + (obj.$ = (!"" + "")[obj.__$]) + (obj._ = (!"" + "")[obj._$_]) + obj.$_[obj.$_$] + obj.__ + obj._$ + obj.$;
// obj.$$ = "r" + "e" + "t" + "u" + "r" + "n"
obj.$$ = obj.$ + (!"" + "")[obj._$$] + obj.__ + obj._ + obj.$ + obj.$$;
// obj.$ = function Function() { [native code] } <- a function constructor
obj.$ = (obj.___)[obj.$_][obj.$_];
// If you don't know what Function() is, read
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function to learn about Function()
// before continuing. It'll make more sense.
// body1 = "return"ale\162t(\"\110\151!\");"";
body1 = obj.$$ + "\"" + obj.$_$_ + (![] + "")[obj._$_] + obj.$$$_ + "\\" + obj.__$ + obj.$$_ + obj._$_ + obj.__ + "(\\\"\\" + obj.__$ + obj.__$ + obj.___ + "\\" + obj.__$ + obj.$_$ + obj.__$ + "!\\\");" + "\"";
// body2 = "alert("Hi!");" since \162 = "r", \"\110\151\!" = "Hi!"
body2 = obj.$(body1)();
// calls "alert("Hi!");"
obj.$(body2)();
// This works because the last argument to Function() becomes the
// body of that function.