• 主页
友链

  • 主页

语言Tricks系列之一

2020-04-13

0x0 序

最近遇到了不少各种语言的trick,于是想尝试作为一个系列记录下来。一般来说,并不提倡在生产环境中使用任何一种trick,好的代码应该是清晰的、无二义性的。部分trick更属于Undefined Behavior,这些trick在不同环境、不同版本的引擎中甚至会有截然不同的表现,在生产环境中应该避免这种情况。但是安全研究、渗透的过程中,利用这样的特性完成攻击的案例并不少见,所以仅作为研究还是有一定的意义。

0x1 代码与输出

于是开始此系列的第一篇:

1
2
3
4
5
6
7
8
9
10
11
12
var a = 0;
console.log(1, a);
if (true) {
console.log(2, a);
a = 1;
console.log(3, a);
function a() { }
console.log(4, a);
a = 21;
console.log(5, a);
}
console.log(6, a);

以上代码在最新版nodejs的输出会是

1
2
3
4
5
6
1 0
2 [Function: a]
3 1
4 1
5 21
6 1

这里是这个结果是这样出现的:

  1. 第一次输出 0
  2. function a() 的定义提升 a 到全局,输出 [Function: a]
  3. 全局的 a 被赋值为 1 ,在console中输出两次
  4. 局部的 a 被赋值为 21 并在console中输出
  5. 全局的 a 在console中输出

0x2 调试过程

以上的整个过程可以通过两种方式确定,一种方式是 node -print-bytecode ,打印出对应的字节码进行参考,具体的字节码如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
StackCheck
LdaZero
Star r1
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [7]
Star r2
CallProperty1 r2, r3, r1, [3]
CreateClosure [2], [9], #2
Star r0
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [12]
Star r2
CallProperty1 r2, r3, r0, [10]
LdaSmi [1]
Star r0
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [16]
Star r2
CallProperty1 r2, r3, r0, [14]
Mov r0, r1
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [20]
Star r2
CallProperty1 r2, r3, r1, [18]
LdaSmi [21]
Star r0
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [24]
Star r2
CallProperty1 r2, r3, r0, [22]
LdaGlobal [0], [5]
Star r3
LdaNamedProperty r3, [1], [28]
Star r2
CallProperty1 r2, r3, r1, [26]
LdaUndefined
Return

一种方式是可以在Chrome中开启调试,可以清晰的看到局部与全局两种作用域。

Chrome调试

0x3 参考链接

  • v8 interpreter-generator.cc
  • 深入理解JS中声明提升、作用域(链)和this关键字
  • Tricks
  • Misc

扫一扫,分享到微信

微信分享二维码
基于QEMU和binfmt-misc透明运行不同架构程序
命令注入成因小谈
© 2024 Lyle
Hexo Theme Yilia by Litten
  • 友链
  • rebirth