*CTF 2019 - oob-v8

Setting Up

Most of what is written from here is courtesy of Faith and their fantastic writeup for this challenge. Please go check them out!

Ok so first off, we're gonna need an old VM. Why? It's an old challenge with an old version of v8. Back then, the v8 version compilation steps required the python command to point at python2 instead of python3 like on my ParrotOS VM, and there is the odd number of other steps. Long story short, there is a very real possibility for needing to jerry-rig a bunch of stuff, and I don't want to break a VM I actually use. Whoops.

So, we're gonna use a Ubuntu 18.04 VM. You can get the ISO file directly from here (amd64 version), and then set up a VM in VMware Workstation or your preferred virtualisation program.

Now we want to set up the system we're actually attacking. Instead of building v8 itself, we're going to build d8, the REPL (read–eval–print loop) for v8. It's essentially the command-line of v8, meaning we can compile less.

First off, install useful stuff.

$ sudo apt update
$ sudo apt install git vim

Now let's grab the depot_tools, which is needed for building v8, then add it to our PATH:

$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
$ echo "export PATH=/tools/depot_tools:$PATH" >> ~/.bashrc

Restart terminal for PATH to update. Then in folder of choice (I am in ~/Desktop/oob-v8), we fetch v8 and install all the dependencies needed to build it:

$ fetch v8
$ cd v8
v8$ ./build/install-build-deps.sh

The next step is to checkout the commit that the challenge is based on, then sync the local files to that:

v8$ git checkout 6dc88c191f5ecc5389dc26efa3ca0907faef3598
v8$ gclient sync

Now we want to apply the diff file we get given. The challenge archive can be found here, and we'll extract it. The oob.diff file defines the changes made to the source code since the commit we checked out, which includes the vulnerability.

$ 7z x Chrome.tar.gz
$ tar -xvf Chrome.tar
$ cp Chrome/oob.diff .

Now let's apply it then prepare and build the release version:

v8$ git apply ../oob.diff
v8$ ./tools/dev/v8gen.py x64.release
v8$ ninja -C ./out.gn/x64.release

But there is small problem when it gets run:

Traceback (most recent call last):
  File "/tools/depot_tools/ninja.py", line 14, in <module>
    import gclient_paths
  File "/tools/depot_tools/gclient_paths.py", line 24, in <module>
    def FindGclientRoot(from_dir, filename='.gclient'):
  File "/usr/lib/python3.6/functools.py", line 477, in lru_cache
    raise TypeError('Expected maxsize to be an integer or None')
TypeError: Expected maxsize to be an integer or None

According to this GitHub issue in NVIDIA, this is because in python 3.8+ lru_cache has gotten a user_function argument. We can try and update to python3.8, but the fear is that it will break something. Oh well! Let's try anyway.

$ sudo apt install python3.8

Now we have Python 3.8 installed in /usr/bin/python3.8, we can try and overwrite the symlink /usr/bin/python3 to point here instead of the default 3.6.9 version that came with the ISO.

$ sudo ln -sf /usr/bin/python3.8 /usr/bin/python3

Now we hope and pray that rerunning the ninja command breaks nothing:

$ ninja --version
depot_tools/ninja.py: Could not find Ninja in the third_party of the current project, nor in your PATH.
Please take one of the following actions to install Ninja:
- If your project has DEPS, add a CIPD Ninja dependency to DEPS.
- Otherwise, add Ninja to your PATH *after* depot_tools.

Ok, no ninja. Let's follow this StackOverflow post and install it:

$ sudo apt install ninja-build

Then run it again:

v8$ ninja -C ./out.gn/x64.release

And it starts working! The output release version is found in v8/out.gn/x64.release/d8. Now let's build debug.

v8$ ./tools/dev/v8gen.py x64.debug
v8$ ninja -C ./out.gn/x64.debug

And it's done. Epic!

I'm going to revert default Python to version 3.6 to minimise the possibility of something breaking.

$ sudo ln -sf /usr/bin/python3.6 /usr/bin/python3

I'm also going to install gef, the GDB extension. gef is actively maintained, and also actually supports Ubuntu 18.04 (which pwndbg does not officially, although that's due to requiring Python 3.8+ which we have technically set up in a roundabout way - use at your own risk!).

$ bash -c "$(curl -fsSL https://gef.blah.cat/sh)"

Now we can move on to the challenge itself.

Last updated