V8 Bug Hunting之V8引擎编译及调试环境的搭建
2019-10-18 11:02:30 Author: www.4hou.com(查看原文) 阅读量:150 收藏

免责声明:这个只是我做的学习记录,内容可能有点混乱,如果你发现了错误请指出来。

相关介绍

到目前为止,我一直在挖掘web漏洞,但是我做的越多,我就越觉得我只是停留在表面上。我想深入挖掘软件层漏洞并深入了解二进制文件。

在观察一段时间后,我认为我需要专注于某些事情。为了达到这一点,我选择了Web浏览器作为挖掘对象,或者更确切地说是选择了Javascript引擎。

大约在同一时间,LiveOverflow开始发布有关该主题的精彩视频:

https://www.youtube.com/watch?v=5tEdSoZ3mmE(部分0x00)

https://www.youtube.com/watch?v=yJewXMwj38s(部分0x01)

我的目标是挖掘出可用漏洞,没有选择JavaScriptCore,而是选择了V8引擎,我将使用Windows / WinDbg作为环境。

编译V8

第一步是在我们的机器上安装V8。以下链接会提供帮助:

https://blog.angularindepth.com/how-to-build-v8-on-windows-and-not-go-mad-6347c69aacd4

http://www.lfdm.net/development/5-how-to-compile-v8-on-windows.html

这个需要一些时间,这两个教程都使用is_debug = false对其进行编译,但是你应该将其设置为true,因为我们需要调试版本。

使用use_jumbo_build = true和is_compoment_build = false将加快构建过程。

现在我编译的是最新版本,但是学习编译旧版本以便在某些时候分析过去的漏洞也是有用的。

运行V8

V8 shell/debugger名为D8,它位于:

 [path_to_v8_folder] \ out.gn \ [build_name] \ d8.exe

你应该使用–allow-natives-syntax flag运行它,以便访问DebugPrint等本机函数:

1567000589039.png

与JavaScript Core相比,V8中对象的内存布局和内部概念完全不同,V8的垃圾回收机制似乎也有不同的工作方式。

内部类型似乎也被不同地调用,即只有整数的数组是PACKED_SMI_ELEMENTS,而具有整数和双精度的数组是PACKED_DOUBLE_ELEMENTS,如果其中有空格,则数组将变为HOLEY而不是PACKED:

1567000675914.png

调试V8

我使用WinDbg作为调试器

第一步相对简单。运行D8并从WinDbg连接到该进程,也可以直接从WinDbg运行D8可执行文件。完成后,可以按F5继续运行该程序。

让我们尝试创建一个包含几个字符串的数组,并在其上执行DebugPrint:

1567000753695.png

在“elements”下,看到了存储数组元素的地址 ,在这种情况下,元素是指向字符串的两个指针。我们可以尝试查看WinDbg中数组元素的地址。

1567000803422.png

我们将看到指向第一个字符串的指针,这是小端存储的,如果我们去那个地址,会找到字符串:

1567000861010.png

如果用整数数组做相同操作,数组不会由指针组成,而是由我们定义的整数组成:

1567000907995.png

如果转到“元素”地址会看到它们:

1567000936167.png

有意思的是,LiveOverflow示例中的整数在他的0x01视频中展示了一些高字节设置为FFFF。那是因为JS Core使用的是NaN-boxing,而V8则没有使用,存储数组的方式似乎有些不同,没有提到结构ID。

看起来这些是JS Core的概念,但我们仍然需要了解V8内部的工作原理。

在结束第一部分之前还有一件事要尝试:可以在Math.max上设置一个断点,首先,我们需要找到该函数以设置断点,可以在WinDbg中搜索这样的符号:

 X v8!* Mathmax *

得到结果:

1567001060791.png

然后设置一个断点:

 bp v8!Builtins_MathMax

然后在D8中运行Math.max并且命中断点:

1567001097595.png

1567001120767.png

打开调用堆栈窗口,我可以看到用于调用堆栈中的大多数函数的源代码。

谷歌搜索了一下后,我遇到了这个:

https://v8.dev/docs/csa-builtins

事实证明,许多内置函数不是在C ++中完成的,而是在汇编中硬编码或使用CodeStubAssembler基础结构实现。但有些仍然是用C ++编写的。通过浏览源代码,我发现Math.hypot应该是这样的函数之一。所以我尝试在bp v8上设置一个断点!我再次运行触发断点,但结果仍然相同。

我已经在源代码中直接设置了断点,当我点击它时,我能够逐步查看源代码!我也注意到我之前的错误是我在v8上设置了一个断点是在Builtin_MathHypot而不是v8 :: internal :: Builtin_MathHypot。

1567001266819.png

我对目前的进展还算满意,后面会继续学习JS类型的内存表示。


文章来源: https://www.4hou.com/technology/20268.html
如有侵权请联系:admin#unsafe.sh