# Stack Canaries

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</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>

## **StackGuard和StackShield**

**StackGuard**在**EIP（扩展指令指针）之前插入一个特殊值，称为canary**，具体为`0x000aff0d`（表示空值、换行符、EOF、回车），以防止缓冲区溢出。然而，像`recv()`、`memcpy()`、`read()`和`bcopy()`这样的函数仍然容易受到攻击，它不保护**EBP（基指针）**。

**StackShield**采用比StackGuard更复杂的方法，维护一个**全局返回堆栈**，存储所有返回地址（**EIPs**）。这种设置确保任何溢出都不会造成伤害，因为它允许对存储的和实际的返回地址进行比较，以检测溢出事件。此外，StackShield可以将返回地址与边界值进行比较，以检测**EIP**是否指向预期数据空间之外。然而，这种保护可以通过Return-to-libc、ROP（Return-Oriented Programming）或ret2ret等技术绕过，这表明StackShield也不保护本地变量。

## **栈破坏保护器（ProPolice）`-fstack-protector`：**

此机制在**EBP**之前放置一个**canary**，并重新组织本地变量，将缓冲区定位在更高的内存地址，防止它们覆盖其他变量。它还安全地复制传递在本地变量上方堆栈上传递的参数，并使用这些副本作为参数。然而，它不保护少于8个元素的数组或用户结构中的缓冲区。

**canary**是从`/dev/urandom`派生的随机数，或者默认值为`0xff0a0000`。它存储在**TLS（线程本地存储）中，允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制，子进程可以修改它们的数据而不影响父进程或同级进程。然而，如果在不创建新canary的情况下使用`fork()`**，所有进程（父进程和子进程）共享相同的canary，使其容易受到攻击。在**i386**架构上，canary存储在`gs:0x14`，在**x86\_64**上存储在`fs:0x28`。

此本地保护识别容易受攻击的缓冲区的函数，并在这些函数的开头注入代码以放置canary，并在结尾验证其完整性。

当Web服务器使用`fork()`时，可以通过逐字节猜测canary来进行暴力攻击。然而，在`fork()`后使用`execve()`会覆盖内存空间，从而抵消攻击。`vfork()`允许子进程执行而不复制，直到尝试写入时创建副本，提供了一种不同的进程创建和内存处理方法。

### 长度

在`x64`二进制文件中，canary cookie是一个\*\*`0x8`**字节qword。前七个字节是随机的，最后一个字节是**空字节\*\*。

在`x86`二进制文件中，canary cookie是一个\*\*`0x4`**字节dword。前三个字节是随机的，最后一个字节是**空字节\*\*。

{% hint style="danger" %}
两个canary的最低有效字节是空字节，因为它将是来自较低地址的栈中的第一个字节，因此**读取字符串的函数将在读取它之前停止**。
{% endhint %}

## 绕过

**泄露canary**，然后用其自身的值覆盖它（例如缓冲区溢出）。

* 如果**canary在子进程中被fork**，可能可以**逐字节暴力破解**：

{% content-ref url="/pages/Ltdyz7aZqirRFXPIRi9D" %}
[BF Forked & Threaded Stack Canaries](/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md)
{% endcontent-ref %}

* 如果二进制文件中存在一些有趣的**泄漏或任意读取漏洞**，可能可以泄漏它：

{% content-ref url="/pages/Ku9GhhnJVXURmq3DZr2B" %}
[Print Stack Canary](/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary.md)
{% endcontent-ref %}

* **覆盖存储在栈中的指针**

易受栈溢出攻击的栈可能**包含可以被覆盖的字符串或函数地址**，以便利用漏洞而无需达到栈canary。查看：

{% content-ref url="/pages/2JV5HgvbkeQHd5RLGKcq" %}
[Pointer Redirecting](/binary-exploitation/stack-overflow/pointer-redirecting.md)
{% endcontent-ref %}

* **修改主canary和线程canary**

受canary保护的线程函数中的缓冲区**溢出**可用于**修改线程的主canary**。结果，该缓解措施无效，因为检查使用两个相同的canary（尽管已修改）。

此外，受canary保护的线程函数中的缓冲区**溢出**可用于**修改存储在TLS中的主canary**。这是因为可能可以通过线程的栈中的**缓冲区溢出**到达存储TLS的内存位置（因此，canary）。\
结果，该缓解措施无效，因为检查使用两个相同的canary（尽管已修改）。\
此攻击在以下文档中执行：<http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads>

还请查看<https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015>的演示文稿，其中提到通常**TLS**由\*\*`mmap`**存储，当创建**线程**的**栈\*\*时也是由`mmap`生成的，根据这一点，可能允许如前述文档中所示的溢出。

* **修改`__stack_chk_fail`的GOT表项**

如果二进制文件具有Partial RELRO，则可以使用任意写入来修改\*\*`__stack_chk_fail`的GOT表项\*\*，使其成为一个虚拟函数，如果canary被修改，则不会阻止程序。

此攻击在以下文档中执行：<https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/>

## 参考资料

* <https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html>
* <http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads>
* <https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/>

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</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)，我们的独家[**NFTs**](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>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
