JavaScript 混淆代码解析:利用原型链与类型转换实现 alert(1)

作者:函数茶馆时间:2026-10-25 20:49:37浏览:248

本文深入解析一段看似混乱的 JavaScript 混淆代码,揭示其如何利用数组原型链、类型强制转换及位运算构造字符串。通过拆解变量赋值与索引操作,逐步还原代码如何从空数组和对象中提取字符,最终组合成 sort 和 alert 方法并执行弹窗。

JavaScript 混淆代码解析:利用原型链与类型转换实现 alert(1)

代码如下:

 
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+ 
($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__ 
[_+~$]+$_[_]+$$](_/_) 

请注意,上述代码虽然视觉上显得杂乱无章,但这并非由自动换行导致,而是刻意编写的三行代码(当然,将其写在一行也是合法的)。在浏览器中运行该页面(注:部分旧版 IE 浏览器可能无法执行),你会发现这段代码的实际功能等价于:


alert(1)


代码拆解与变量推导

为何会产生这样的结果?我们将这段代码拆解为多个部分进行详细分析。


$=[] // 将 $ 赋值为空数组,因此 !$ 的布尔值为 false。


__ = !$ + $ // 加法运算符会将 !$ 和 $ 强制转换为字符串,因此 __ 的值变为字符串 "false"。


_ = -~-~-~$ // 此处涉及 ~ 按位取反运算符,其逻辑为 -($+1)。因此 -~$ 的值为 1,进而 _ 的值为 3。


基于上述推导,我们可以得出以下中间结果:


代码如下:

 
(__ = !$ + $ )[ _ = -~-~-~$] => ("false")[_] => ("false")[3] => "false"[3] = "s"
({} + $)[_/_] => ("[object Object]")[_/_] => ("[object Object]")[1] => "[object Object]"[1] = "o"

接下来继续拆解子表达式 $$=($_=!''+$)[_/_]+$_[+$] :


$_=!''+$ // 注意,!'' 中包含两个单引号,即对空字符串进行非运算。因此变量 $_ 被赋值为字符串 "true"。


由此可进一步推导:


$$=($_=!''+$)[_/_]+$_[+$] => $$ = ( "true")[1] + "true"[0] => "r" + "t" = "rt"


因此,表达式 (__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$]) 的组合结果为 "s" + "o" + "rt",即字符串 "sort"。


表达式简化与执行流程

所以,原始的复杂表达式:


代码如下:

 
($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+ 
($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__ 
[_+~$]+$_[_]+$$](_/_) 

可以被简化替换为:


代码如下:

 
($=[[]]["sort"])()[__[_/_]+__
[_+~$]+$_[_]+$$](_/_) 

接下来我们分析 [__[_/_]+__[_+~$]+$_[_]+$$](_/_) 这部分代码的含义。


前文我们已经确认了以下变量值:


__ = "false"


_ = 3


~$ = -1


$_ = "true"


$$ = "rt"


因此,[__[_/_]+__[_+~$]+$_[_]+$$](_/_) 的推导过程为:["false"[1] + "false"[3-1] + "true"[3] + "rt"](3/3) => ["a" + "l" + "e" + "rt"](1) => ["alert"](1)。


所以,原始表达式最终可以替换为:


($=[[]]["sort"])()["alert"](1)


这段代码的具体执行流程如下:


a = [[]] // 创建一个包含空数组的数组


b = a["sort"] // 获取数组的 sort 方法引用


c = b() // 调用数组的 sort 方法,此处 b() 返回 window 对象


d = c["alert"] // 获取 window.alert 方法


d(1) // 调用 window.alert 方法。


综上所述,这堆复杂的表达式最终执行结果等同于 window.alert(1)。


更多详细信息请参阅原文及 Reddit 上的相关讨论。


原文评论区中,也有开发者分享了一个日本开发者编写的小工具,可将 JavaScript 代码编码为各种表情符号并执行,供爱好者参考。


此外,上述代码除了可能用于 XSS 攻击测试外,实际业务价值有限,但通过分析此代码,可以学习数据类型转换的相关知识,并领略 JavaScript 语言的灵活性。


详细代码逐行解析

详细代码解析:


代码如下:

 
( 
$=[$=[]] // $ = [] 
[ 
(__= !$ + $) // __ = "false"
[_=-~-~-~$] // _ = 3
// (__)[3] = "s"
+ 
({} + $) // ({} + $) = [object Object]
[_/_] // _/_ = 1
+ // ([object Object])[1] = "o"
($$ = // 
($_=!'' + $) // !''+ $ = "true" ; $_ = "true"
[_/_] // _/_ = 1;
// $_[1] = "r"
+ 
$_[+$] // +$ = 0; $_[0] = "t"
) // $$= "rt"
] // ["sort"]
// []["sort"] = [].sort = function sort() { [native code] }
// $ = []["sort"]
)() // ($)() = [object Window]
[ 
__[_/_] // __ = "false";
// __[1] = "a"
+ 
__ [_+~$] //_ = 3; ~$ = -1; _ + ~$ = 2
// __[2] = "l"
+ 
$_[_] // $_ = "true" ; _ = 3;
// $_[3] = "e"
+ 
$$ // $$ = "rt"
](_/_); // _ / _ = 1
// window["alert"](1)

关键知识点总结

这里需要注意的几点:


1. javascript 里面 $, _ 均可以作为合法的变量名


2. 函数调用还可以采用方括号语法:比如 [1,2,4,1,9,1].sort() 可以写成 [1,2,4,1,9,1]["sort"]();


3. ~ 运算符对数字进行按位取反操作


4. javascript 中在对不同类型的变量使用 + 运算符时的类型转换规则


5. 最后一个针对某些 native code 编写的方法,执行时会返回 window 对象,例如


var s = [].sort ; t=s(); 则 t 是 window

作者最新文章