了解 Arm 中的缓冲区溢出

逆向工程 缓冲区溢出
2021-06-15 18:43:03

假设我有一个函数 (vuln),它有一个大小为 0x20 字节的本地缓冲区。在这个函数的开头,有push r4-r7,lr.

是否正确,堆栈看起来像:

缓冲区:((0x20)...r4(0x4)...r5(0x4)...r6(0x4)...r7(0x4)...lr用于返回地址0x4...fp(前一帧指针0x4)...然后是调用者函数的堆栈帧。

这意味着,如果我想跳转到 address 中的函数0xabcd,我需要放入 buffer AA* 0x32+ 0xabcd ( 0x32= buffer +r4-r7) 。

是这样吗?lr 的位置将被替换,但 fp 的位置保持正确?

现在,如果我真的会跳转到 0xabcd 的地址。此功能 ( 0xabcd) 将完成后。该函数将尝试恢复 fp 并且会崩溃,因为它是易受攻击函数的帧指针。

那是对的吗?

1个回答

你的理解似乎大部分是正确的。但是缓冲区加上四个 32 位寄存器组成了 0x30,而不是 0x32 字节。另请注意,您的目标地址是 32 位,因此它看起来更像是 0xABCD1234 或 0x0000ABCD,而只是 0xABCD。

您没有提供任何证据来证明或反驳旧的 fp 值高于推送的链接寄存器。不过,我不希望堆栈上有 ARM 寄存器 FP 的副本:您引用的是拇指代码。Thumb 要么根本不使用帧指针,要么使用 R7 作为帧指针,因为(大多数)thumb 指令无法访问 ARM 帧指针寄存器。如果按照惯例使用 R7 作为拇指帧指针,则旧帧指针是 r7 的值,它低于返回地址(推入 LR),而不是高于。

如果您设法覆盖返回地址,那么您将在不使用 BL 的情况下跳转到目标函数,这是“非常规”的。所有 ARM 函数都希望它们的返回地址在 LR 中传递,这正是 BL(或 BLX)所做的。返回不会设置 LR,因此您无意中返回的目标函数将跳转到存在漏洞的函数退出时恰好存储在 LR 中的(过时的)地址。很可能是在执行易受攻击的函数期间发生的(可能是嵌套的)函数调用的返回地址。该代码不准备从“外部”返回,并且会发现堆栈处于错误状态,因此程序将崩溃。