BROP - Blind Return Oriented Programming
Last updated
Last updated
学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)
此攻击的目标是能够通过缓冲区溢出滥用 ROP,而无需任何关于易受攻击二进制文件的信息。 此攻击基于以下场景:
一个堆栈漏洞和触发它的知识。
一个在崩溃后重启的服务器应用程序。
您可以在 这里 (BF Forked & Threaded Stack Canaries) 和 这里 (BF Addresses in the Stack) 找到有关这些过程的更多信息。
这个 gadget 基本上允许确认 ROP gadget 执行了某些有趣的内容,因为执行没有崩溃。通常,这个 gadget 将是停止执行的内容,并且在寻找 ROP gadget 时位于 ROP 链的末尾,以确认特定的 ROP gadget 被执行。
此技术使用 ret2csu gadget。这是因为如果您在某些指令中间访问此 gadget,您将获得控制**rsi
和rdi
**的 gadget:
这些将是 gadget:
pop rsi; pop r15; ret
pop rdi; ret
注意,通过这些 gadget 可以控制 2 个参数的函数调用。
另外,请注意 ret2csu gadget 具有非常独特的特征,因为它将从堆栈中弹出 6 个寄存器。因此,发送一个链如:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
如果STOP 被执行,这基本上意味着使用了一个从堆栈中弹出 6 个寄存器的地址。或者使用的地址也是一个 STOP 地址。
为了消除这个最后的选项,执行一个新的链,如下所示,并且它必须不执行 STOP gadget 以确认之前的确弹出了 6 个寄存器:
'A' * offset + canary + rbp + ADDR
知道 ret2csu gadget 的地址,可以推断出控制 rsi
和 rdi
的 gadget 的地址。
PLT 表可以从 0x400000 或从堆栈中泄露的 RIP 地址进行搜索(如果PIE正在使用)。表的条目是每 16B 分隔(0x10B),当调用一个函数时,即使参数不正确,服务器也不会崩溃。此外,检查PLT + 6B 的条目地址也不会崩溃,因为这是执行的第一段代码。
因此,可以通过检查以下行为找到 PLT 表:
'A' * offset + canary + rbp + ADDR + STOP
-> 不崩溃
'A' * offset + canary + rbp + (ADDR + 0x6) + STOP
-> 不崩溃
'A' * offset + canary + rbp + (ADDR + 0x10) + STOP
-> 不崩溃
strcmp
函数将寄存器 rdx
设置为正在比较的字符串的长度。请注意,rdx
是第三个参数,我们需要它大于 0,以便稍后使用 write
来泄露程序。
可以基于其行为找到 strcmp
在 PLT 中的位置,利用我们现在可以控制函数的前两个参数的事实:
strcmp(<非读取地址>, <非读取地址>) -> 崩溃
strcmp(<非读取地址>, <读取地址>) -> 崩溃
strcmp(<读取地址>, <非读取地址>) -> 崩溃
strcmp(<读取地址>, <读取地址>) -> 不崩溃
可以通过调用 PLT 表的每个条目或使用PLT 慢路径来检查这一点,慢路径基本上是调用 PLT 表中的一个条目 + 0xb(这会调用**dlresolve
),然后在堆栈中跟随希望探测的条目编号**(从零开始)以扫描所有 PLT 条目:
strcmp(<非读取地址>, <读取地址>) -> 崩溃
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
-> 将崩溃
strcmp(<读取地址>, <非读取地址>) -> 崩溃
b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
strcmp(<读取地址>, <读取地址>) -> 不崩溃
b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP
请记住:
BROP + 0x7 指向 pop RSI; pop R15; ret;
BROP + 0x9 指向 pop RDI; ret;
PLT + 0xb 指向对 dl_resolve 的调用。
找到 strcmp
后,可以将 rdx
设置为大于 0 的值。
请注意,通常 rdx
会已经包含一个大于 0 的值,因此这一步可能不是必要的。
最后,需要一个 gadget 来外泄数据,以便外泄二进制文件。在此时,可以控制 2 个参数并将 rdx
设置为大于 0。
有 3 个常见函数可以被滥用:
puts(data)
dprintf(fd, data)
write(fd, data, len(data)
然而,原始论文只提到**write
**,所以让我们谈谈它:
当前的问题是我们不知道write 函数在 PLT 中的位置,也不知道发送数据到我们套接字的 fd 号码。
然而,我们知道PLT 表的位置,并且可以根据其行为找到 write。我们可以与服务器创建多个连接,并使用一个高 FD,希望它与我们的一些连接匹配。
找到这些函数的行为特征:
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> 如果有数据打印,则找到了 puts
'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> 如果有数据打印,则找到了 dprintf
'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP
-> 如果有数据打印,则找到了 write
学习与实践 AWS 黑客技术:HackTricks 培训 AWS 红队专家 (ARTE) 学习与实践 GCP 黑客技术:HackTricks 培训 GCP 红队专家 (GRTE)