# 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="stack-canaries/bf-forked-stack-canaries" %}
[bf-forked-stack-canaries](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries)
{% endcontent-ref %}

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

{% content-ref url="stack-canaries/print-stack-canary" %}
[print-stack-canary](https://hacktricks.xsx.tw/binary-exploitation/common-binary-protections-and-bypasses/stack-canaries/print-stack-canary)
{% endcontent-ref %}

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

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

{% content-ref url="../stack-overflow/pointer-redirecting" %}
[pointer-redirecting](https://hacktricks.xsx.tw/binary-exploitation/stack-overflow/pointer-redirecting)
{% 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>
