This is going to document my journey into V8 exploitation, and hopefully provide some tools to help you learn too.
To start with, we're going to go through *CTF's OOB-V8 challenge, mostly following Faith's brilliantly in-depth writeup. From there, well, we'll see.
Saelo's classic V8 paper is also a goldmine.
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.
Now let's grab the depot_tools
, which is needed for building v8, then add it to our PATH
:
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:
The next step is to checkout
the commit that the challenge is based on, then sync the local files to that:
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.
Now let's apply it then prepare and build the release version:
But there is small problem when it gets run:
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.
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.
Now we hope and pray that rerunning the ninja
command breaks nothing:
Ok, no ninja
. Let's follow this StackOverflow post and install it:
Then run it again:
And it starts working! The output release
version is found in v8/out.gn/x64.release/d8
. Now let's build debug.
And it's done. Epic!
I'm going to revert default Python to version 3.6 to minimise the possibility of something breaking.
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!).
Now we can move on to the challenge itself.