Skip to content

Fix typos #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions FreeBSD/PS4 5.05 BPF Double Free Kernel Exploit Writeup.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The process of heap spraying is fairly simple - allocate a bunch of memory and f
By extension, it's useful to do this for a double free() as well, because once we have a stale reference, we can use a heap spray to control the data. Since the object will be marked "free" - the allocator will eventually provide us with control over this memory, even though something else is still using it. That is, unless, something else has already stolen the pointer from you and corrupts it - then you'll likely get a system crash, and that's no fun. This is one factor that adds to the variance of exploits, and typically, the smaller the object, the more likely this is to happen.

# A Tale of Two Free()'s
Via `ioctl()` command, a user can set a filter program on a given descriptor via commands such as `BIOSETWF`. There are other commands to set other filters, however the write filter is the only one interesting to us for this writeup. An important part of the previous exploit was the power to free() an older filter once a new one has been allocated, via `bpf_setf()`, which is called directly by `BIOSETWF`'s command handler. This allowed us to free() a filter while it was in use. This free() in itself is also a bug that can be exploited, and is leveraged in the newer exploit. Let's take a look at `bpf_setf()` again.
Via `ioctl()` command, a user can set a filter program on a given descriptor via commands such as `BIOCSETWF`. There are other commands to set other filters, however the write filter is the only one interesting to us for this writeup. An important part of the previous exploit was the power to free() an older filter once a new one has been allocated, via `bpf_setf()`, which is called directly by `BIOCSETWF`'s command handler. This allowed us to free() a filter while it was in use. This free() in itself is also a bug that can be exploited, and is leveraged in the newer exploit. Let's take a look at `bpf_setf()` again.

[src](http://fxr.watson.org/fxr/source/net/bpf.c?v=FREEBSD90#L1523)
```c
Expand Down Expand Up @@ -81,7 +81,7 @@ static int bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
}
```

We can see that there are variables on the stack to hold filter pointers, including one for the `old` filter which eventually gets free()'d. If the ioctl command is set to `BIOSETWF`, the pointer from `d->bd_wfilter` is copied to the `old` stack variable.
We can see that there are variables on the stack to hold filter pointers, including one for the `old` filter which eventually gets free()'d. If the ioctl command is set to `BIOCSETWF`, the pointer from `d->bd_wfilter` is copied to the `old` stack variable.

Later on, we can see that they lock the BPF descriptor, and null the references to the filters. They lock the reference clearing, but what about the pointer of `d->bd_wfilter` being copied to the stack? As we've seen in previous exploits, multiple threads can run and use the same `bpf_d` object. If we were to race setting two filters in parallel, there's a chance that both threads will copy the same pointer to their kernel stacks, eventually resulting in a double free as both pointers will be processed.

Expand Down Expand Up @@ -159,6 +159,7 @@ At some point in 5.0x, it seems Sony added some mitigation into the scheduler to
To avoid this, we need to get our ROP chain into kernel memory. To do this, qwerty decided to go with the method he used on the iPhone 7 - essentially using JOP to push a bunch of stack frames onto the kernel stack, and `memcpy()`'ing the chain into `RSP`.

You can find a detailed annotation of the exploit [here](https://github.com/kpwn/PS4-5.05-Kernel-Exploit/blob/9e97c398342ed6499a00fce0c081f7bf1efaaef1/kernel.js) to assist in understanding it, as it does get quite complex.

# JOP Explained
Software engineers have started getting wise to stack pivot techniques, and preventing the attacker from the ability to stack pivot into user-controlled memory is a pretty decent counter-measure, however, like everything, it is bypassable. JOP (jump oriented programming) is a way. You could use JOP to implement a full chain, or use it as a method of getting to ROP via getting your ROP chain into kernel memory. The latter is preferred, because implementing logic in JOP (while possible) can be a nightmare.

Expand Down