The MOVAPS issue
mango

The MOVAPS issue

在做一道ret2libc的时候被这个问题困住了好久

为什么使用下面这个payload程序会崩溃,但是逻辑没有问题呀!

1
2
3
4
p.sendafter(
b"Show me your magic again\n",
b"\x00" * 0x20 + flat(bss,pop_rdi_ret, binsh_addr,system_addr,main_addr),
)

使用这个在system前加了一个ret的payload就可以了?!

1
2
3
4
p.sendafter(
b"Show me your magic again\n",
b"\x00" * 0x20 + flat(bss,pop_rdi_ret, binsh_addr,ret,system_addr,main_addr),
)

经过大佬指点了解到在Ubuntu18版本及以上(还有一部分的Ubuntu16版本)64位程序调用system时是需要栈对齐的。

根本原因是64位的system命令有个movaps指令,这条指令是:

1
movaps xmmword ptr [rsp + 0x50], xmm0

https://www.felixcloutier.com/x86/movaps 处我们可以知道,这条指令的功能是: 将xmm0中保存的单精度浮点数从xmm0移动至地址[rsp + 0x50]处

当然,更重要的是这条指令的执行条件,这直接关系到程序报错的原因。原文中对执行条件的描述如下:

When the source or destination operand is a memory operand, the operand must be aligned on a 16-byte (128-bit version), 32-byte (VEX.256 encoded version) or 64-byte (EVEX.512 encoded version) boundary or a general-protection exception (#GP) will be generated.

此时报错的原因就显而易见了:当内存地址作为操作数时,内存地址必须对齐 16Byte32Byte64Byte 。这里所说的对齐 xByte,就是指地址必须是 x 的倍数。

这时又出现了一个问题:到底是对齐多少字节呢?我们可以找到这样一段描述:

This instruction can be used to load an XMM, YMM or ZMM register from an 128-bit, 256-bit or 512-bit memory location, to store the contents of an XMM, YMM or ZMM register into a 128-bit, 256-bit or 512-bit memory location, or to move data between two XMM, two YMM or two ZMM registers.

基于此,我们可以推测:使用 XMM 时,需要 16Byte 对齐;使用 YMM 时,需要 32Byte 对齐;使用 ZMM 时,需要 64Byte 对齐。

而此处出错的指令使用了 XMM 寄存器,因此我们需要确保在执行这一指令时,rsp + 0x5016 的倍数。直观地说,就是该地址必须以数字 0 结尾。

(调用printf时也需要对齐)

目前了解到有两种办法可以解决这个问题(但也不是每次都行,实在不行就换成execve吧…

第一种办法:

在system前加个ret

第二种办法:

在system的地址上加1-16,尝试,这是为了跳过一个栈操作

参考:

https://zhuanlan.zhihu.com/p/611961995

由 Hexo 驱动 & 主题 Keep
访客数 访问量