Tool Learning 1 - Use Fuzzilli on Real Target

Fuzzing on Real Target

In this post, I will begin to use fuzzilli and try on the present supported targets. Section 4 I took note of some information about some background knowledge of swift.

Fuzzing Preparation

My ubuntu environment is showed as below

Install Clang

The require version >=4.0, I installed clang-10. This part I installed before. But I did meet some problem after I installed swift.

The path of clang point to the path of the swift installed folder, which forced me to reinstall Clang again, and add clang into update-alternative --config. Using sudo ln may solve this issue but I did not try.

1
2
$ sudo apt-get install clang-10 #or just simply install clang
$ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 99 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-10 #the number larger will stand for higher priority

The llvm-dev is also needed:

1
$ sudo apt install llvm-dev

If want to swap to different clang version:

1
$ sudo update-alternatives --config clang

For remove the link (and its slave):

1
2
$ sudo update-alternatives --display clang #or clang++ or others
$ sudo update-alternatives --remove clang /usr/bin/clang-10 #depends on the message show in the commandline

Do not install like this (easier to make error)

1
2
3
$ sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 10000
$ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-10 10000
$ sudo update-alternatives --install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-10 10000

I guess clang may not need to install since swift it has it. But I am not sure so I note down this part of installing clang here.

Install Swift

Ensure that the package index and installed packages are up to date

1
$ sudo apt update && sudo apt upgrade

Install the dependency of swift (I did not execute this, but for new docker container or new installed system, this could be needed)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ sudo apt install binutils git gnupg2 libc6-dev libcurl4 libedit2 libgcc-9-dev libpython2.7 libsqlite3-0 libstdc++-9-dev libxml2 libz3-dev pkg-config tzdata zlib1g-dev

#or try this (from https://swift.org/getting-started/#installing-swift)

$ sudo apt-get install \
binutils \
git \
libc6-dev \
libcurl4 \
libedit2 \
libgcc-5-dev \
libpython2.7 \
libsqlite3-0 \
libstdc++-5-dev \
libxml2 \
pkg-config \
tzdata \
zlib1g-dev

Download toolchains from the swift download page. For example, I choose swift-5.4.2-RELEASE-ubuntu18.04.tar.gz to download. Then, extract the file into a folder (home/user_name/):

1
$ tar -xvzf swift-5.4.2-RELEASE-ubuntu18.04.tar.gz -C ~

Add the path into ~/.bashrc and source it (restart the environment)

1
2
$ echo "PATH=~/swift-5.4.2-RELEASE-ubuntu18.04/usr/bin:$PATH" >> ~/.bashrc
$ source ~/.bashrc

To verify the swift, can enter:

1
$ swift --version

if the output is as below, that means swift has been instlled.

Test Swift

To test the swift in commandline, enter swift, and terminal will launch an shell called REPL or Read Eval Print Loop. Here I met some error when enter REPL:

After remove libc6-dbg, the error message just gone.

1
$ sudo apt remove libc6-dbg

Type in the following code to see whether swift works or not.

1
2
3
4
let name = "LinuxConfig"
import Glibc // imports GNU C Library
var ln = random() % 100
print("hello,",name,"your lucky number is", ln)

After testing, can use ctrl + d or :quit or :q to exit.

Build Fuzzilli

1
2
3
$ git clone https://github.com/googleprojectzero/fuzzilli.git
$ cd fuzzilli
$ swift build -c release -Xlinker='-lrt'

If build sucessfully, we can begin to fuzz the JavaScript Engine.

Begin Fuzzing

After establish the environment of swift and clang, fuzzilli can be tried on the following JSE (JavaScript Engine).

Fuzzing on JavaScriptCore

JavaScriptCore is the JSE implemented in Safari. Firstly, download the source code, and patch it by using fuzzilli's patch.

1
2
3
4
5
$ git clone https://github.com/WebKit/webkit
$ git checkout xxxxx #This is optional if needed
$ patch -p1 < /The/Path/to/webkit.patch #Patch on the current folder
$ cp /The/Path/to/fuzzilli/Targets/JavaScriptCore/fuzzbuild.sh ./
$ ./fuzzbuild.sh #Begin to build

After this, we can begin to run fuzzilli

1
2
$ sysctl -w 'kernel.core_pattern=|/bin/false' #Run this if this is first time to use fuzzilli to fuzz
$ swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=jsc /The/Path/to/webkit/FuzzBuild/Debug/bin/jsc #See also swift run FuzzilliCli --help

In the commandline, the error may be generate:

1
$ error: root manifest not found

Thus, shoule execute this command at first:

1
$ swift package init --type executable

However, sometimes it does not work, so the problem of show "root manifest not found" error is because the project lack of package.swift. Thus, I found the solution finally, that is clone the whole project in fuzzilli instead of any else where! So all the source code of sepcific JSE (Here is JavaScriptCore) should under /Path/to/fuzzilli/Targets/xxx, this ensure that they have package.swift exists in the root folder of fuzzilli.

Thus, I git clone the webkit under ~/coding_env/fuzzilli/Targets/JavaScriptCore, and execute the following command under ~/coding_env/fuzzilli/Targets/JavaScriptCore/webkit:

1
$ swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=jsc FuzzBuild/Debug/bin/jsc #under fuzzilli's folder, in .../fuzzilli/Targets/JavaScriptCore/webkit

Fuzzing begin! This will take some time to initialize.

Begin to fuzz, let's look at the console.

After fuzzing, we can conduct crash analysis by using gdb.

Fuzzing on QJS

QuickJS is a embeddable JS engine. Using the follow command to build this. Or enter this link to download the code from the version in Targets/QJS/REVISION.

1
2
3
4
5
6
7
$ cd fuzzilli/Targets/QJS #Make sure under the fuzzilli directory
$ git clone https://github.com/bellard/quickjs.git
$ cd quickjs
$ git checkout xxx -b fuzz #This depends! Refer to the REVISION under fuzzilli/Targets
$ cp ../Patches/Fuzzilli-instrumentation-for-QJS.patch ./
$ patch -p1 < Fuzzilli-instrumentation-for-QJS.patch #Patch the current project, this may take some time to patch
$ make #official repo say we should use "make qjs" here

I encountered some issues here, so I think this should be build on MacOS (which set default to use clang to compiler):

Build on Ubuntu failed, I am still figuring why and how to fix this. It seems not supported to use clang to build QuickJS on Ubuntu (set default to use gcc, but gcc not support -fsanitize-coverage=trace-pc-guard, and only clang supports this.

On ubuntu, if make by using make qjs (follow the instruction on here), the error is different.

It seems very near to the success, but I stuck on here.

Fuzzing on V8

V8 is the open source JSE used in chrome. First, we need to fetch the source code. so install depot_tools at first.

1
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git

Add depot_tools to the front of your PATH (you will probably want to put this in your ~/.bashrc or ~/.zshrc). Assuming you cloned depot_tools to /path/to/depot_tools:

1
$ export PATH=/path/to/depot_tools:$PATH

Update depot_tools by executing the following into your terminal/shell.

1
$ gclient

Now, get the V8 source code, including all branches and dependencies:

1
2
3
4
5
$ cd fuzzilli/Targets/V8 #Make sure under the fuzzilli directory
$ mkdir ~/v8
$ cd ~/v8
$ fetch v8 #This may take some time, grasp a coffee and wait
$ cd v8

If want to update the code, could use the following command:

1
2
$ git pull
$ gclient sync

Done! Let's go to the directory of v8 and copy a fuzzbuild.sh script in the v8 root directory. Then try to execute fuzzbuild.sh in the v8 root directory.

We successfully built it! Let's type in this command to begin fuzzing

1
2
3
4
$ cd .. 
$ mkdir out #make a directory to store output
$ cd v8
$ swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=v8 --storagePath=../out out/fuzzbuild/d8 #The storagePath used to store the fuzzing result

Now it works well!

Note: sanitizer coverage for v8 is currently not supported on macOS as it is missing from v8's custom clang toolchain.

Fuzzing on Duktape

Duktape is a embeddable Javascript engine. First, fetch the code from github:

1
2
3
4
$ cd fuzzilli/Targets/duktape #Make sure under the fuzzilli directory
$ git clone https://github.com/svaarala/duktape
$ cd duktape
$ make duk-fuzzilli

The executable will be named duk-fuzzilli, in the duktape directory. However, I stuck after I type in make duk-fuzzilli

Fuzzing on Spidermonkey

Spidermonkey is a opensource JSE implemented in firefox. First, clone the repo and run the script in Fuzzilli.

1
2
$ cd fuzzilli/Targets/Spidermonkey #Make sure under the fuzzilli directory
$ git clone https://github.com/mozilla/gecko-dev #Need some time, take a nap

After copy the fuzzbuild.sh in Targets/Spidermonkey to the directory of gecko-dev/js/src, run it

1
2
3
4
5
$ cd Targets/Spidermonkey/gecko-dev
$ git checkout xxx #To firefox branch
$ cd gecko-dev/js/src
$ cp /The/Path/to/fuzzilli/Targets/Spidermonkey/fuzzbuild.sh ./
$ ./fuzzbuild.sh #In the root of gecko-dev, rustc may be needed in this phase. And this takes some time, have a rest!

fuzzbuild_OPT.OBJ/dist/bin/js will be the JavaScript shell for the fuzzer

1
2
$ mkdir out #In gecko-dev/js/src
$ swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=spidermonkey --storagePath=out/ fuzzbuild_OPT.OBJ/dist/bin/js

Happy hacking!

Fuzzing on Jerryscript

Jerryscript is a lightweight JavaScript engine for the Internet of Things. To fetch the code:

1
2
$ cd fuzzilli/Targets/Jerryscript #Make sure under the fuzzilli directory
$ git clone https://github.com/jerryscript-project/jerryscript

Then apply the patch and run the script (fuzzbuild.sh). Note that rustc may need in this part.

1
2
3
4
5
$ cd jerryscript #Ensure under fuzzilli/Targets/Jerryscript/jerryscript
$ git checkout 0f0041d720adfd83012e59435c2f1b555c1234d5 #This is optional if needed, check the REVISION in "Targets" folder
$ patch -p1 < /The/Path/to/jerryscript.patch #Patch on the current folder. If not checkout in the right commit, this will fail.
$ cp /The/Path/to/fuzzilli/Targets/Jerryscript/fuzzbuild.sh ./
$ ./fuzzbuild.sh #Begin to build

./build/bin/jerry will be the JavaScript shell for the fuzzer.

1
2
$ mkdir out #In Targets/Jerryscript/jerryscript
$ swift run -c release -Xlinker='-lrt' FuzzilliCli --profile=jerryscript --storagePath=out/ ./build/bin/jerry

Hah! Let's begin fuzzing!

Swift Basic Knowledge (Optional)

Swift use SPM (Swift Package Manager) to establish a new package project. Make a new folder called swift_test and use this command to initialize.

1
$ swift package init --type executable --name helloworld #swift build --init

So the executable swift package called helloworld will be generated in this folder.

We can execute this by build and run.

So this create a fundemental Command line tool.

Fuzzilli in Docker (Optional)

The part can be referred to this document, available docker image can be found here.

Install Rust (Optional)

1
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh #Choose 1 after this

Ouput message is showed as below:

All the tool included rustc, cargo and rustup will be located in ~/.cargo/bin. It can be added into PATH environment variable. try rustc --version to check rust has been installed or not. If want to uninstall, try rustup self uninstall.