作者:Hcamael@知道創宇404實驗室

最近因為某些原因開始學V8的漏洞利用,所以打算寫一個系列的文章來記錄一下我的學習過程。

概述

在開始研究V8之前肯定得有相應版本的環境,搭建v8環境的教程網上挺多的。在國內搭建環境,因為眾所周知的原因,我們會遇到第一個瓶頸,網絡瓶頸。不過也挺好解決的,把環境搭在vps上,網速是最快的。不過隨后就會遇到第二個瓶頸,性能瓶頸,自用的vps一般性能都是1c1g左右,編譯一次將近1h吧。

我是打算學V8的漏洞利用,不用的漏洞版本基本都會有區別,總不可能研究一個就花1h左右的時間在編譯上吧。所以我就考慮是否有現成的docker環境,這樣就不需要花時間在編譯上了,不過并沒有找到合適的docker,只找到一個叫docker-v8的項目,不過只有很少的幾個版本,這個Dockerfile和Makefile寫的也不對,只能編譯最新版的,沒法編譯任意一個版本。所以我對這個項目進行了一些改編,打算在我的mbp上來編譯,自己構建相關的docker。但是沒想到i9的CPU也不太行,挺垃圾的,一熱就降頻,10s左右就可以煮雞蛋了。編譯一次差不多半小時吧,再加上網絡因素,完整跑一趟流程也差不多1h。

隨后想起前段時間給女朋友配了個AMD 5950x的臺式機,隨后又研究了一波WOL,但是發現在斷電一段時間后,WOL會失效,最后使用小米智能插座,臺式機設置通電自動開機,來讓我遠程訪問。

這個臺式機是買來給女朋友打游戲,所以裝的是windows,也沒裝虛擬機。不過裝了WSL,直接在WSL上編譯,路由器是openwrt,讓臺式機走全局代理,這樣又解決了網絡瓶頸,最后一整套流程下了,只需要5分鐘左右就能生成任意版本的v8環境。然后把d8拖到本地,就能構建好相應版本的docker了。

環境搭建

下面就來詳細說明我在WSL編譯v8環境的過程:

  1. 首先裝好相關依賴: sudo apt install bison cdbs curl flex g++ git python vim pkg-config
  2. 獲取depot_tools: git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
  3. 設置depot_tools的環境變量: echo "export PATH=$(pwd)/depot_tools:${PATH}" >> ~/.zshrc
  4. 運行fetch v8, 這個命令會把v8克隆下來,v8挺大的,所以這個命令的速度視網絡情況而定
  5. 安裝v8相關的依賴,字體依賴就算用代理也會遇到一些網絡問題,但是我目前沒有研究字體類的漏洞,我就沒有去解決這個問題,所以直接不裝字體的依賴:./v8/build/install-build-deps.sh --no-chromeos-fonts

以上算通用步驟,也就是不管什么版本,上面的命令執行一次就好了。

網上的環境搭建的教程里面,之后應該就是執行:

$ cd v8
$ gclient sync
$ gn gen out/x64.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.release d8

如果編譯出來的v8環境需要遷移,建議設置v8_monolithic=true,這樣只需要遷移一個d8程序就好了。要不然還得遷移其他(snapshot)依賴。

上面是編譯最新版環境運行的命令,不過我是需要編譯任意版本的,所以我把第二階段的內容寫成了一個build.sh腳本:

$ cat build.sh
#!/bin/bash
VER=$1
if [ -z $2 ];then
        NAME=$VER
else
        NAME=$2
fi
cd 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

以下是我運行一次該腳本的時間:

$ time ./build.sh "9.6.180.6"
HEAD is now at 67eacd3dce Version 9.6.180.6
Syncing projects: 100% (29/29), done.
Running hooks: 100% (27/27), done.
Done. Made 178 targets from 98 files in 244ms
ninja: Entering directory `out/x64_9.6.180.6.release'
[1839/1839] LINK ./d8
./build.sh "9.6.180.6"  4581.36s user 691.20s system 1586% cpu 5:32.41 total

然后是我修改過后的Makefile:

$ cat Makefile 
TAG:=$(tag)
IMAGE:=hcamael/v8

default: help

help:
    @echo 'V8/D8 ${TAG} Docker image build file'
    @echo
    @echo 'Usage:'
    @echo '    make clean           Delete dangling images and d8 images'
    @echo '    make build           Build the d8 image using local Dockerfile'
    @echo '    make push            Push an existing image to Docker Hub'
    @echo '    make deploy          Clean, build and push image to Docker Hub'
    @echo '    make github          Tag the project in GitHub'
    @echo

build:
    docker build --build-arg V8_VERSION=${TAG} -t ${IMAGE}:${TAG} .

clean:
    # Remove containers with exited status:
    docker rm `docker ps -a -f status=exited -q` || true
    docker rmi ${IMAGE}:latest || true
    docker rmi ${IMAGE}:${TAG} || true
    # Delete dangling images
    docker rmi `docker images -f dangling=true -q` || true

push:
    docker push docker.io/${IMAGE}:${TAG}
    docker tag ${IMAGE}:${TAG} docker.io/${IMAGE}:latest
    docker push docker.io/${IMAGE}:latest

deploy: clean build push

github:
    git push
    git tag -a ${TAG} -m 'Version ${TAG}'
    git push origin --tags


.PHONY: help build clean push deploy github

然后是修改過后的Dockerfile

$ cat Dockerfile
FROM debian:stable-slim

RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update && apt-get upgrade -yqq && \
    DEBIAN_FRONTEND=noninteractive apt-get install curl rlwrap vim -yqq gdb && \
    apt-get clean
ARG V8_VERSION=latest
ENV V8_VERSION=$V8_VERSION

LABEL v8.version=$V8_VERSION \
      maintainer="test@admin.com"
WORKDIR /v8

COPY /v8_$V8_VERSION/d8 ./

COPY vimrc /root/.vimrc

COPY entrypoint.sh /

RUN chmod +x /entrypoint.sh && \
    mkdir /examples && \
    ln -s /v8/d8 /usr/local/bin/d8

ENTRYPOINT ["/entrypoint.sh"]

參考

  1. https://github.com/andreburgaud/docker-v8

Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1820/