BROP - Blind Return Oriented Programming
Reading time: 9 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
基本信息
此攻击的目标是能够通过缓冲区溢出滥用ROP,而无需了解易受攻击的二进制文件。
此攻击基于以下场景:
- 一个堆栈漏洞和触发它的知识。
- 一个在崩溃后重新启动的服务器应用程序。
攻击
1. 找到易受攻击的偏移 发送一个字符,直到检测到服务器故障
2. 暴力破解canary 以泄露它
3. 暴力破解存储的RBP和RIP 地址以泄露它们
您可以在这里 (BF Forked & Threaded Stack Canaries)和这里 (BF Addresses in the Stack)找到有关这些过程的更多信息。
4. 找到停止小工具
这个小工具基本上允许确认ROP小工具执行了某些有趣的内容,因为执行没有崩溃。通常,这个小工具将是停止执行的内容,并且在寻找ROP小工具以确认特定ROP小工具被执行时,它位于ROP链的末尾。
5. 找到BROP小工具
此技术使用ret2csu小工具。这是因为如果您在某些指令中间访问此小工具,您将获得控制**rsi
和rdi
**的工具:
这些将是小工具:
pop rsi; pop r15; ret
pop rdi; ret
注意,使用这些小工具可以控制函数的2个参数。
此外,请注意,ret2csu小工具具有非常独特的签名,因为它将从堆栈中弹出6个寄存器。因此,发送一个链如:
'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP
如果STOP被执行,这基本上意味着使用了一个从堆栈中弹出6个寄存器的地址。或者使用的地址也是一个停止地址。
为了消除这个最后的选项,执行一个新的链,如下所示,并且它必须不执行停止小工具以确认前一个确实弹出了6个寄存器:
'A' * offset + canary + rbp + ADDR
知道ret2csu小工具的地址,可以推断出控制rsi
和rdi
的小工具的地址。
6. 找到PLT
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
-> 没有崩溃
7. 找到strcmp
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的值。
tip
请注意,通常rdx
将已经包含一个大于0的值,因此这一步可能不是必要的。
8. 找到Write或等效函数
最后,需要一个小工具来外泄数据,以便外泄二进制文件。在此时,可以控制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
自动利用
参考文献
- 原始论文: https://www.scs.stanford.edu/brop/bittau-brop.pdf
- https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。