Stack Pivoting - EBP2Ret - EBP chaining
Last updated
Last updated
学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)
该技术利用操控 基指针 (EBP) 的能力,通过仔细使用 EBP 寄存器和 leave; ret
指令序列来链接多个函数的执行。
作为提醒,leave
基本上意味着:
And as the EBP is in the stack before the EIP it's possible to control it controlling the stack.
这个技术在你可以更改 EBP 寄存器但没有直接方法更改 EIP 寄存器时特别有用。它利用了函数执行完毕后的行为。
如果在 fvuln
执行期间,你设法在栈中注入一个指向内存中你 shellcode 地址的假 EBP(加上 4 字节以考虑 pop
操作),你可以间接控制 EIP。当 fvuln
返回时,ESP 被设置为这个构造的位置,随后的 pop
操作将 ESP 减少 4,有效地使其指向攻击者在其中存储的地址。
注意你需要知道 2 个地址:ESP 将要去的地址,以及你需要在 ESP 指向的地方写入的地址。
首先,你需要知道一个可以写入任意数据/地址的地址。ESP 将指向这里并运行第一个 ret
。
然后,你需要知道 ret
使用的地址,这将执行任意代码。你可以使用:
一个有效的 ONE_GADGET 地址。
system()
的地址,后面跟 4 个垃圾字节 和 "/bin/sh"
的地址(x86 位)。
一个 jump esp;
gadget 的地址(ret2esp),后面跟要执行的 shellcode。
一些 ROP 链
请记住,在受控内存的任何这些地址之前,必须有**4
字节**,因为 pop
部分的 leave
指令。可以利用这 4B 设置一个第二个假 EBP,并继续控制执行。
这个技术有一个特定的变体,称为“Off-By-One Exploit”。当你只能修改 EBP 的最低有效字节时使用。在这种情况下,存储要跳转到的地址的内存位置与 ret
必须共享前 3 个字节,从而允许在更受限的条件下进行类似的操作。
通常会修改字节 0x00t 以尽可能远地跳转。
此外,通常在栈中使用 RET sled,并将真实的 ROP 链放在末尾,以使新的 ESP 更有可能指向 RET SLED 内部,并执行最终的 ROP 链。
因此,将一个受控地址放入栈的 EBP
条目中,并在 EIP
中放入一个 leave; ret
的地址,可以将 ESP
移动到栈中受控的 EBP
地址。
现在,ESP
被控制,指向一个期望的地址,下一条要执行的指令是 RET
。为了利用这一点,可以在受控的 ESP 位置放置以下内容:
&(next fake EBP)
-> 由于 leave
指令中的 pop ebp
加载新的 EBP
system()
-> 由 ret
调用
&(leave;ret)
-> 在 system 结束后调用,它将 ESP 移动到假 EBP 并重新开始
&("/bin/sh")
-> system
的参数
基本上,这种方式可以链接多个假 EBP 来控制程序的流程。
这就像一个 ret2lib,但更复杂,没有明显的好处,但在某些边缘情况下可能会很有趣。
此外,这里有一个 挑战示例,使用这个技术与 stack leak 来调用一个获胜函数。这是页面的最终有效载荷:
正如 在这篇文章中解释的,如果一个二进制文件是使用某些优化编译的,EBP 永远无法控制 ESP,因此,任何通过控制 EBP 的漏洞利用基本上都会失败,因为它没有任何实际效果。 这是因为如果二进制文件经过优化,前言和尾声会发生变化。
未优化:
优化:
pop rsp
gadget在此页面 你可以找到使用此技术的示例。对于这个挑战,需要调用一个带有两个特定参数的函数,并且有一个 pop rsp
gadget 和一个 来自栈的泄漏:
查看 ret2esp 技术:
64 位,使用以 ret sled 开头的 rop 链进行越界利用
64 位,无 relro、canary、nx 和 pie。该程序提供了堆栈或 pie 的泄漏和一个 qword 的 WWW。首先获取堆栈泄漏,然后使用 WWW 返回获取 pie 泄漏。然后使用 WWW 创建一个利用 .fini_array
条目 + 调用 __libc_csu_fini
的永恒循环(更多信息在这里)。利用这个“永恒”的写入,在 .bss 中写入一个 ROP 链并最终调用它,通过 RBP 进行 pivoting。
在 ARM64 中,函数的 前言和尾声 不在堆栈中存储和检索 SP 寄存器。此外,RET
指令不会返回到 SP 指向的地址,而是 返回到 x30
内的地址。
因此,默认情况下,仅仅利用尾声你 无法通过覆盖堆栈中的某些数据来控制 SP 寄存器。即使你设法控制了 SP,你仍然需要一种方法来 控制 x30
寄存器。
前言
尾声
在 ARM64 中执行类似于堆栈 pivoting 的方法是能够 控制 SP
(通过控制某个寄存器的值传递给 SP
,或者因为某种原因 SP
从堆栈获取其地址并且我们有一个溢出),然后 利用尾声 从 受控的 SP
加载 x30
寄存器并 RET
到它。
在以下页面中,你可以看到 ARM64 中的 Ret2esp 等价物:
学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)