> For the complete documentation index, see [llms.txt](https://hacktricks.xsx.tw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacktricks.xsx.tw/binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md).

# BROP - Blind Return Oriented Programming

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS红队专家）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[NFT](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 基本信息

此攻击的目标是能够**利用ROP通过缓冲区溢出而无需有关易受攻击的二进制文件的任何信息**。\
此攻击基于以下情景：

* 存在堆栈漏洞并且知道如何触发它。
* 一个在崩溃后重新启动的服务器应用程序。

## 攻击

### **1. 查找易受攻击的偏移量**，发送一个额外字符直到检测到服务器发生故障

### **2. 暴力破解canary** 以泄漏它

### **3. 暴力破解存储的RBP和RIP**地址以泄漏它们

您可以在[这里（BF分叉和线程化堆栈Canaries）](/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)和[这里（BF地址在堆栈中）](/binary-exploitation/common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md)找到有关这些过程的更多信息。

### **4. 查找停止gadget**

这个gadget基本上允许确认通过ROP gadget执行了一些有趣的操作，因为执行没有崩溃。通常，这个gadget将是一些**停止执行**的内容，并且当寻找ROP gadget以确认特定ROP gadget已执行时，它将位于ROP链的末尾。

### **5. 查找BROP gadget**

此技术使用[**ret2csu**](/binary-exploitation/rop-return-oriented-programing/ret2csu.md) gadget。这是因为如果在一些指令中访问此gadget，则可以获得控制\*\*`rsi`**和**`rdi`\*\*的gadgets：

<figure><img src="/files/14onVS4yiC5ngKbfdNtF" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>

这些将是gadgets：

* `pop rsi; pop r15; ret`
* `pop rdi; ret`

请注意，使用这些gadgets可以**控制函数的2个参数**。

还要注意，ret2csu gadget具有**非常独特的签名**，因为它将从堆栈中弹出6个寄存器。因此，发送如下链：

`'A' * 偏移量 + canary + rbp + ADDR + 0xdead * 6 + STOP`

如果**执行STOP**，这基本上意味着使用了一个从堆栈中弹出6个寄存器的地址。或者使用的地址也是一个STOP地址。

为了**排除这种可能性**，执行一个新链如下，它不应执行STOP gadget以确认先前的链确实弹出了6个寄存器：

`'A' * 偏移量 + canary + rbp + ADDR`

知道ret2csu gadget的地址后，就可以**推断出控制`rsi`和`rdi`的gadgets的地址**。

### 6. 查找PLT

PLT表可以从0x400000或从堆栈中的**泄漏的RIP地址**（如果使用**PIE**）开始搜索。表的**条目**以16B（0x10B）分隔，当调用一个函数时，即使参数不正确，服务器也不会崩溃。此外，检查**PLT + 6B中的条目地址也不会崩溃**，因为这是第一个执行的代码。

因此，可以通过检查以下行为来找到PLT表：

* `'A' * 偏移量 + canary + rbp + ADDR + STOP` -> 无崩溃
* `'A' * 偏移量 + canary + rbp + (ADDR + 0x6) + STOP` -> 无崩溃
* `'A' * 偏移量 + canary + rbp + (ADDR + 0x10) + STOP` -> 无崩溃

### 7. 查找strcmp

**`strcmp`函数将寄存器`rdx`设置为要比较的字符串的长度。请注意，`rdx`是第三个参数，我们需要它大于0**，以便稍后使用`write`泄漏程序。

可以根据其行为在PLT中找到\*\*`strcmp`\*\*的位置，利用我们现在可以控制函数的前两个参数的事实：

* strcmp(<非读取地址>, <非读取地址>) -> 崩溃
* strcmp(<非读取地址>, <读取地址>) -> 崩溃
* strcmp(<读取地址>, <非读取地址>) -> 崩溃
* strcmp(<读取地址>, <读取地址>) -> 无崩溃

可以通过调用PLT表的每个条目或使用**PLT慢路径**来检查这一点，该慢路径基本上包括调用PLT表中的一个条目 + 0xb（调用\*\*`dlresolve`**），然后在堆栈中跟随希望探测的**条目编号\*\*（从零开始）以扫描所有PLT条目：

* strcmp(<非读取地址>, <读取地址>) -> 崩溃
* `b'A' * 偏移量 + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> 将崩溃
* strcmp(<读取地址>, <非读取地址>) -> 崩溃
* `b'A' * 偏移量 + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
* strcmp(<读取地址>, <读取地址>) -> 无崩溃
* `b'A' * 偏移量 + 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的值。

{% hint style="success" %}
请注意，通常`rdx`将已经包含大于0的值，因此此步骤可能不是必需的。
{% endhint %}

\### 8. 寻找Write函数或等效函数

最后，需要一个用于外泄数据的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

## 自动化利用

* <https://github.com/Hakumarachi/Bropper>

## 参考资料

* 原始论文: <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>
