【Chrome V8系列01】初识V8漏洞

PS:本系列会先介绍一些前置知识,在前言中我会列出学习资料(参考rjk师傅仓库以及其他博客),文章后半部分会结合pwncollege进行练习。

[*]在学习本系列前,你应该对JS语法介绍 - JavaScript | MDN和二进制PWN堆栈漏洞原理和利用栈介绍 - CTF Wiki有基本认识。
[*]本系列将基于pwn.college中的V8 Exploitation以及rjk师傅V8仓库https://github.com/bjrjk/pwn-learning/tree/main/PwnCollege/V8Exploitation进行学习,建议先尝试自己做一下,有任何问题请通过评论或QQ进行讨论。

[*]学完本篇文章后,你将掌握如何使用浮点数制作V8 shellcode。


 

一、V8漏洞挖掘价值

V8是Google用 C++ 编写的开源高性能 JavaScript 引擎,由于它广泛应用于Chrome浏览器和Node.js,所以使用Chrome内核或V8的内置浏览器都将受到V8漏洞的影响(如微信、支付宝和Electron应用等)。

二、初识JS引擎

1.JS引擎发展历史

众所周知,JavaScript是一种解释型脚本语言,早些年的JS执行工具只有解释执行,JS引擎会逐行读取源代码,解析每一行并直接执行。随着Web应用和动态内容的迅速增长,对JavaScript的执行需求急剧增加,传统的解释执行模式无法满足性能要求,所以在2000年代初引入了JIT(即时编译)技术。

2.V8引擎运行基本流程

V8引擎的五个基本步骤:

① 解析器(Parser):将JavaScript源代码转换为抽象语法树(AST)。

② 抽象语法树(AST):表示源代码的语法结构。

③ Ignition(解释器):将AST转换为字节码并执行,解释器逐行执行字节码。

④ TurboFan(编译器):对热点代码进行优化,将字节码编译为高度优化的机器码。

⑤ 执行:执行生成的机器码以提高代码的执行效率。

我这里画了一个流程图便于大家了解:

209f45be81d9464c847e842f419e2e21.png

 

3.解析器(parser)

解析器是将源代码转换为更易于处理的结构(通常是AST)的程序部分。解析过程主要分为两个阶段:

① 词法分析(Lexical Analysis)

  • 词法分析的主要任务是将源代码字符串分解成一系列称为“记号”(tokens)的基本元素。每个记号代表源代码中的一个基本组成部分,如关键字、标识符、运算符、数字等。

  • 词法分析器会忽略空白字符和注释,聚焦于提取有效的代码元素。

② 语法分析(Syntax Analysis)

  • 在这个阶段,解析器根据语言的语法规则将记号组合成更复杂的结构,通常是抽象语法树(AST)。

  • 语法分析会检查记号的排列是否符合语言的语法规则,如果不符合,解析器会抛出语法错误。

4.抽象语法树(AST)

AST是一种树状数据结构,表示源代码的语法结构。每个节点代表代码的一个组成部分(如表达式、语句、操作符等),可以使用https://astexplorer.net/来查看AST结构。

5722118097bf4d449c1c48f0145ed800.png

 

5.解释器(Ignition)

在V8 JavaScript引擎中,Ignition是其解释器,它承担了将JavaScript代码转换为字节码并执行的任务。以下是Ignition的工作原理:

① 解析并生成字节码

        当V8接收到JavaScript源代码时,解析器首先将其解析为抽象语法树(AST),然后Ignition将AST转换为字节码。字节码是一种轻量级的中间表示,方便执行。

② 字节码的执行

        Ignition直接执行生成的字节码,它使用一种虚拟机机制逐行解释和执行这些字节码指令。

③ 动态优化

        Ignition会监测代码执行的频率,如果发现某段代码被频繁执行,它会标记为“热代码”。这种热代码之后可能会由V8的优化编译器(TurboFan)进一步优化,并转换为机器码以提高执行速度。

6.编译器(TurboFan)

① 优化编译:

        当 Ignition 解释器执行字节码时,它会持续监测代码的执行情况。如果某段代码被多次调用,V8会将其标记为热代码。一旦代码被标记为热代码,TurboFan 编译器会接管,并对字节码进行优化编译。

② 生成本地机器码:

        经过优化之后,TurboFan将生成本地机器码(native machine code)。这段机器码是直接针对CPU架构的,能够在硬件上高效执行。

③ 本地机器码执行:

        V8引擎会将生成的本地机器码缓存起来,并在后续执行时直接调用这些机器码,而不是通过解释器逐行执行字节码。因为本地机器码已经是针对硬件的低级指令,执行效率极高。

三、V8漏洞种类

其实V8也是一种应用程序,所以也会有常见的二进制漏洞,根据漏洞占比主要可以分为以下三种类型:

① 越界访问(Out-of-Bounds, OOB):

        访问数组或对象时,尝试读取或写入不在有效范围内的内存。比如data[]的长度为10,但在读取或写入data数组时,下标大于9或小于0,导致写入了data数组外的内存区域。

② 类型混淆(Type Confusion):

        V8的类型混淆漏洞占了相当大的比例,这要归功于JavaScript是弱类型语言。在弱类型语言中,变量的类型是动态的,可以在运行时改变。例如,上边我们讲到编译器负责将热代码优化转换为机器码,当代码被优化时,类型信息的推断可能会不准确。如果优化器假设某个变量始终是特定类型,而实际上在某些情况下它是另一种类型,就可能会导致类型混淆漏洞。

③ 其他漏洞:

        使用后释放(Use-After-Free, UAF),双重释放(Double Free),数据竞争(Data Race)等等。(这里简单了解一下即可,后边会有针对性讲解和练习)。

四、练习题

题目名称:PwnCollege V8 Exploitation Level 1

题目链接:pwn.college

知识点:    转换浮点数为机器码执行shellcode

1.PwnCollege的使用

        打开题目链接后来到level1,这里提供了“Start”和“Practice”两种模式。Start模式是正式环境,在该环境中我们只有普通shell权限,要利用对应的漏洞才能获取flag;Practice模式是练习环境,允许我们提升到root权限,从而使用gdb等工具调试V8,不过在这里获取flag是没用的,打通后要在正式环境中利用才能获取到Real Flag。

2ace16fd359c40d1aeddba818b3f04cf.png

        这里使用VSCode或GUI Desktop交互都可以,看个人习惯。纯新手建议GUI Desktop。进入工作环境后,打开challenge文件夹,这里包含了题目所有文件。

879079cf46994e86beba2fef84c39ef5.png

2.题目文件的用法

        题目提供了七个文件,catflag、d8、patch和run这四个文件是和解题有关的,通过./run /path/exp.js来执行getflag获取flag。脚本run调用d8(d8 是 V8 JavaScript 引擎的命令行工具,用于执行 JavaScript 代码)来执行我们的exp.js文件,利用漏洞getflag。

        那么漏洞在哪呢?本系列的练习题都是人为添加的漏洞,所以我们通过分析patch文件,就可以知道增加删除了哪些代码,漏洞就在其中。

3.分析patch文件

        打开patch文件,总体分析一下,发现主要逻辑在43~55行,主要是使用mmap函数分配一段内存,循环遍历elements数组,并将获取到元素的值转换为double类型,同时复制到mmap分配的内存中,最后执行这段内存中的代码。

b13dc60dd37240ab9a2920a494af0ac2.png

        最后run一下创建的double数组,即可触发ArrayRun。

a9f76dd83a414cb4a76ca4aef8df145a.png

6d95ccf5d2384db39d2754febf592055.png

4.利用思路

        这道题主要帮助大家初步认识V8漏洞的一种利用手段,虽然真实V8中不会有这么明显的漏洞,但实际V8漏洞利用真的会用到double类型构造shellcode,所以这是非常好的入门利用练习。

        本题利用思路就是先将shellcode(16进制)转换为double类型,当double数字被写入内存中时也就相当于写入了shellcode(因为两者二进制相同)。rjk师傅推荐了一个在线转换工具可以在学习初期使用Double (IEEE754 Double precision 64-bit) Converter感受转换过程,在下方Binary处填入对应的Hexadecimal,点击convert to decimal即可。

35294b16ca5b457ab54e9701f03ca2e5.png

5.构造EXP

        rjk师傅编写了类型转换脚本pwn-learning/PwnCollege/V8Exploitation/ShellCode at main · bjrjk/pwn-learning · GitHub,同时给出了第一题的构造脚本,当然还是希望读者自己从头写一下。

PS:有师傅疑惑64位如果参数较多,使用push+mov的方式会影响调用,这里提一下,{shellcraft.amd64.push(0)},{shellcraft.amd64.mov("rdx", "rsp")}也可以使用{shellcraft.amd64.setregs({'rdx': 0})}代替。

cae59634ba584f1aade9c57c2932e006.png

06a2139b15f14ab4b184f7a5d3f85f9d.png

ed98f538629b4dc99a56e97d3177e097.png


总结

恭喜你入门V8漏洞利用啦!感谢rjk师傅对我的指导,计划在两个月内完成10个练习,感兴趣的师傅可以点个关注。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值