# V8基础环境配置 ## 基础环境 ### 网络环境 环境配置在VmWare16下的Ubuntu20.04,过程需要代理或者使用[github actions](https://zhuanlan.zhihu.com/p/159646912),原文传网盘的操作已失效,可以结合腾讯云的`coscmd`​工具,这种方法在要编译新的`commit`​时需要重新执行,一次代码生成及下载耗时约三十分钟。 ```workflow name: BUILD v8 on: push: branches: [ master ] # watch: # types: started env: PATCH_FLAG: true COMMIT: 6dc88c191f5ecc5389dc26efa3ca0907faef3598 DEPOT_UPLOAD: true SRC_UPLOAD: true BINARY_UPLOAD: false # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: # The type of runner that the job will run on runs-on: ubuntu-20.04 if: github.event.repository.owner.id == github.event.sender.id steps: - name: Checkout uses: actions/checkout@master # init ubuntu2004 environment - name: init env run: | sudo apt-get update sudo apt-get -y install pkg-config git subversion curl wget build-essential python xz-utils zip p7zip-full pip install coscmd coscmd config -a *** -s ***-b v8-***-r ap-*** # get depot_tools - name: depot_tools run: | git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git echo export PATH=\"\$PATH:`pwd`/depot_tools/\" >> ~/.bash_profile # fetch v8 source code - name: fetch v8 run: | source ~/.bash_profile fetch v8 cd v8 # patch source code - name: patch v8 if: env.PATCH_FLAG == 'true' && !cancelled() run: | cd v8 git reset --hard $COMMIT cd .. - name: build v8 run: | source ~/.bash_profile gclient sync -f # compress this file - name: zip depot_tools if: env.DEPOT_UPLOAD == 'true' && !cancelled() run: | zip -q -r depot_tools.zip depot_tools # 7zip v8 src - name: 7zip v8_src run: | zip -q -r v8.zip v8 # upload depot_tools.zip to cowtransfer - name: upload depot_tools if: env.DEPOT_UPLOAD == 'true' && !cancelled() run: | coscmd -d -s upload depot_tools.zip / # upload v8.zip to cowtransfer - name: upload v8_src if: env.SRC_UPLOAD == 'true' && !cancelled() run: | coscmd -d -s upload v8.zip / ``` ### 安装 首先下载用于 `Chromium`​ 开发的工具 `depot_tools`​: ```js git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git ``` 利用bash启动脚本,将 `depot_tools`​ 添加到环境变量 `PATH`​ : ```sh echo "export PATH=$PATH:/path/to/depot_tools" > ~/.bashrc source ~/.bashrc ``` 安装`ninja`​用于编译`v8`​: ```sh sudo apt install ninja-build ``` 运行`fetch`​命令将`v8`​源码下载到当前工作路径并同步: ```sh fetch v8 cd v8 gclient sync -D ``` 下载完v8源代码后,为gdb添加v8提供的调试工具,需要在`~/.gdbinit`​中添加: ```gdb source /path/to/v8/tools/gdbinit source /path/to/v8/tools/gdb-v8-support.py ``` ### 编译 以[StarCTF OOB](https://github.com/sixstars/starctf2019/tree/master/pwn-OOB)为例,题目提供一个`oob.diff`​文件和`commit`​号: > Yet another off by one > > $ nc 212.64.104.189 10000 > the v8 commits is 6dc88c191f5ecc5389dc26efa3ca0907faef3598 编译时往往会结合某一具体的`commit`​号,以[starctf OOB](https://github.com/sixstars/starctf2019/tree/master/pwn-OOB)为例,题目提供一个`oob.diff`​文件和`commit:6dc88c191f5ecc5389dc26efa3ca0907faef3598`​: ```sh Yet another off by one $ nc 212.64.104.189 10000 the v8 commits is 6dc88c191f5ecc5389dc26efa3ca0907faef3598 ``` 执行以下命令即可完成编译,编译后的可执行文件保存在`out.gn/x64.debug/d8`​和`out.gn/x64.release/d8`​ ```sh # 进入v8工作路径 cd v8 git reset --hard 6dc88c191f5ecc5389dc26efa3ca0907faef3598 gclient sync -D git apply < oob.diff # 编译debug版本 tools/dev/v8gen.py x64.debug ninja -C out.gn/x64.debug d8 # 编译release版本 tools/dev/v8gen.py x64.release ninja -C out.gn/x64.release d8 ``` 另一种方式是通过版本号分支进行chekcout: ```js #!/bin/bash VER=$1 if [ -z $2 ]; then NAME=$VER else NAME=$2 fi cd /home/v8/v8 git reset --hard $VER gclient sync -D gn gen out/x64_$NAME.release --args='v8_monolithic=true v8_use_external_startup_data=false is_component_build=false is_debug=false target_cpu ="x64" use_goma=false goma_dir="None" v8_enable_backtrace=true v8_enable_disassembler=true v8_enable_object_print=true v8_enable_verify_heap=true' ninja -C out/x64_$NAME.release d8 ``` ### 安装turbolizer 在查看turbofan的优化代码时,需要使用到`turbolizer`​工具, ```sh curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash sudo apt install nodejs cd /path/to/v8/tools/turbolizer sudo npm install n -g sudo n latest # 升级 nodejs 到最新版 sudo npm i sudo npm run-script build ``` 使用`--trace-turbo`​参数运行d8: ```sh ./d8 --trace-turbo --allow-natives-syntax ./test.js ``` 用python启动一个web服务器: ```sh python -m SimpleHTTPServer 8000 ``` 访问目录`http://127.0.0.1:8000/path/to/v8/tools/turbolizer/`​即可。 V8提供在线的[turbolizer](https://v8.github.io/tools/head/turbolizer/index.html),其他版本见:https://v8.github.io/tools/ ### 调试 v8对调试提供一些支持,以此`test.js`​代码为示例进行后续步骤的演示: ```js var alist = [1, 2, 3, 4]; %DebugPrint(alist); %SystemBreak(); ``` 在目录`out.gn/x64.debug`​目录运行`gdb ./d8`​,在`gdb`​终端指定运行参数`r --allow-natives-syntax --shell ./test.js`​启动,`d8`​会断点在第三行代码的位置,并打印`JSArray`​对象`alist`​的内存信息: ![image](assets/image-20240905105855-y44eqll.png) 使用`job addr`​命令打印出某地址处变量的内存信息: ![image](assets/image-20240905110348-3dymsw1.png) 如果在`release`​版本下则只会打印对象的地址和类型,因为`release`​版默认不包含调试符号,使用`job`​命令会提示缺少`_v8_internal_Print_Object`​符号,如果需要开启调试符号支持,则需要在`out.gn/x64.release/args.gn`​添加如下参数后重新编译 ```js v8_enable_backtrace = true v8_enable_disassembler = true v8_enable_object_print = true v8_enable_verify_heap = true ``` 重新编译后的`release`​版本则会包含`_v8_internal_Print_Object`​。需要注意的是在`debug`​版本下进行漏洞利用的调试可能会在触发漏洞时被`debug`​的某种机制阻断,后续的题目`obb`​就会出现这类问题: ![image](assets/image-20240905104134-qga8hab.png) ‍