mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 04:33:28 +00:00
Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc
This commit is contained in:
parent
4c3958f1c0
commit
51e97815ba
4 changed files with 325 additions and 307 deletions
|
@ -8,17 +8,17 @@
|
|||
|
||||
* 如果您想看到您的**公司在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)**。**
|
||||
* 探索[**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>
|
||||
|
||||
## **Malloc Hook**
|
||||
|
||||
正如您可以在[GNU官方网站](https://www.gnu.org/software/libc/manual/html\_node/Hooks-for-Malloc.html)中看到的,变量**`__malloc_hook`**是一个指针,指向**将在调用`malloc()`时调用的函数的地址**,存储在libc库的数据段中。因此,如果将此地址覆盖为例如**One Gadget**,并调用`malloc`,则将调用**One Gadget**。
|
||||
根据[GNU官方网站](https://www.gnu.org/software/libc/manual/html\_node/Hooks-for-Malloc.html)的说法,变量**`__malloc_hook`**是一个指针,指向**将在调用`malloc()`时调用的函数的地址**,存储在libc库的数据段中。因此,如果将此地址覆盖为例如**One Gadget**,并调用`malloc`,则将调用**One Gadget**。
|
||||
|
||||
要调用malloc,可以等待程序调用它,也可以通过**调用`printf("%10000$c")`**,这将分配太多字节,使`libc`调用malloc在堆中分配它们。
|
||||
要调用malloc,可以等待程序调用它,或者通过**调用`printf("%10000$c")`**,这将分配太多字节,使`libc`调用malloc在堆中分配它们。
|
||||
|
||||
有关One Gadget的更多信息,请参阅:
|
||||
|
||||
|
@ -27,58 +27,69 @@
|
|||
{% endcontent-ref %}
|
||||
|
||||
{% hint style="warning" %}
|
||||
请注意,对于GLIBC >= 2.34,挂钩**已禁用**。现代GLIBC版本可以使用其他技术。请参阅:[https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)。
|
||||
请注意,对于GLIBC >= 2.34,挂钩**已禁用**。现代GLIBC版本可以使用其他技术。请参见:[https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md)。
|
||||
{% endhint %}
|
||||
|
||||
## Free Hook
|
||||
|
||||
这在页面中滥用快速bin攻击后滥用未排序bin攻击的一个示例中被滥用:
|
||||
在滥用未排序bin攻击之后,滥用快速bin攻击的示例页面中曾经滥用过这一点:
|
||||
|
||||
{% content-ref url="../libc-heap/unsorted-bin-attack.md" %}
|
||||
[unsorted-bin-attack.md](../libc-heap/unsorted-bin-attack.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
一个很好的技巧(来自[**这里**](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html))是,如果二进制文件具有符号,可以**执行类似以下操作**来查找free hook的位置:
|
||||
如果二进制文件具有符号,可以使用以下命令找到`__free_hook`的地址:
|
||||
```bash
|
||||
gef➤ p &__free_hook
|
||||
```
|
||||
gef➤ set __free_hook = 0xfacade
|
||||
gef➤ search-pattern 0xfacade
|
||||
```
|
||||
在同一篇文章中,您可以找到有关如何在没有符号的情况下定位`__free_hook`地址的逐步指南。总结一下,在`free`函数中:
|
||||
[在这篇文章中](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html),您可以找到一个逐步指南,介绍如何在没有符号的情况下定位`__free_hook`的地址。总结一下,在free函数中:
|
||||
|
||||
```armasm
|
||||
gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
0xf75dedc1 <free+1>: call 0xf768f625
|
||||
0xf75dedc6 <free+6>: add ebx,0x14323a
|
||||
0xf75dedcc <free+12>: sub esp,0x8
|
||||
0xf75dedcf <free+15>: mov eax,DWORD PTR [ebx-0x98]
|
||||
0xf75dedd5 <free+21>: mov ecx,DWORD PTR [esp+0x10]
|
||||
0xf75dedd9 <free+25>: mov eax,DWORD PTR [eax]
|
||||
0xf75deddb <free+27>: test eax,eax ;<--- BREAK HERE
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
```
|
||||
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
|
||||
0xf75dedc0 <free>: push ebx
|
||||
0xf75dedc1 <free+1>: call 0xf768f625
|
||||
0xf75dedc6 <free+6>: add ebx,0x14323a
|
||||
0xf75dedcc <free+12>: sub esp,0x8
|
||||
0xf75dedcf <free+15>: mov eax,DWORD PTR [ebx-0x98]
|
||||
0xf75dedd5 <free+21>: mov ecx,DWORD PTR [esp+0x10]
|
||||
<strong>0xf75dedd9 <free+25>: mov eax,DWORD PTR [eax]--- 在此处中断
|
||||
</strong>0xf75deddb <free+27>: test eax,eax ;<
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
</code></pre>
|
||||
|
||||
在上述代码中的断点处,`$eax`中将会存储`__free_hook`的地址。
|
||||
在前面代码中提到的中断处,`$eax`中将会存储`__free_hook`的地址。
|
||||
|
||||
现在执行**快速bin攻击**:
|
||||
|
||||
- 首先发现可以在**`__free_hook`**位置使用大小为200的快速**块**:
|
||||
```c
|
||||
gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
</code></pre>
|
||||
- 如果我们成功在此位置获得大小为0x200的快速块,就可以覆盖一个将被执行的函数指针
|
||||
- 为此,创建一个大小为`0xfc`的新块,并使用该指针两次调用合并函数,这样我们就可以获得一个指向大小为`0xfc*2 = 0x1f8`的已释放块的指针在快速bin中。
|
||||
- 然后,在此块中调用编辑函数,将这个快速bin的**`fd`**地址修改为指向先前的**`__free_hook`**函数。
|
||||
- 接着,创建一个大小为`0x1f8`的块,从快速bin中检索先前无用的块,然后创建一个大小为`0x1f8`的块,以在**`__free_hook`**中获取一个快速bin块,该块被覆盖为**`system`**函数的地址。
|
||||
- 为此,创建一个大小为`0xfc`的新块,并使用该指针两次调用合并函数,这样我们就可以获得一个指向已释放大小为`0xfc*2 = 0x1f8`的快速块的指针。
|
||||
- 然后,在这个块中调用编辑函数,将这个快速块的**`fd`**地址修改为指向之前的**`__free_hook`**函数。
|
||||
- 接着,创建一个大小为`0x1f8`的块,从快速块中检索之前无用的块,然后创建一个大小为`0x1f8`的块,以在**`__free_hook`**中获取一个快速块块,将其覆盖为**`system`**函数的地址。
|
||||
- 最后,释放一个包含字符串`/bin/sh\x00`的块,调用删除函数,触发指向带有`/bin/sh\x00`参数的**`system`**函数的**`__free_hook`**函数。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
|
||||
* [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
|
||||
|
||||
<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>
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
支持HackTricks的其他方式:
|
||||
|
||||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 如果您想看到您的**公司在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)**。**
|
||||
* **加入** 💬 [**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>
|
||||
|
@ -18,15 +18,15 @@
|
|||
|
||||
### **GOT:全局偏移表**
|
||||
|
||||
**全局偏移表(GOT)**是在动态链接二进制文件中使用的机制,用于管理**外部函数的地址**。由于这些**地址直到运行时才知道**(由于动态链接),GOT提供了一种在这些外部符号解析后**动态更新这些地址**的方法。
|
||||
**全局偏移表(GOT)**是在动态链接二进制文件中使用的机制,用于管理**外部函数的地址**。由于这些**地址直到运行时才知道**(由于动态链接),GOT提供了一种在解析这些外部符号后**动态更新这些地址**的方法。
|
||||
|
||||
GOT中的每个条目对应于二进制文件可能调用的外部库中的符号。当**首次调用函数时,动态链接器会解析其实际地址并将其存储在GOT中**。随后对同一函数的调用使用GOT中存储的地址,从而避免再次解析地址的开销。
|
||||
GOT中的每个条目对应于二进制文件可能调用的外部库中的一个符号。当**首次调用函数时,动态链接器会解析其实际地址并将其存储在GOT中**。随后对同一函数的调用使用GOT中存储的地址,从而避免再次解析地址的开销。
|
||||
|
||||
### **PLT:过程链接表**
|
||||
|
||||
**过程链接表(PLT)**与GOT密切配合,作为处理对外部函数的调用的跳板。当二进制文件**首次调用外部函数时,控制会传递到与该函数相关联的PLT中的一个条目**。此PLT条目负责调用动态链接器以解析函数的地址(如果尚未解析)。地址解析后,将其存储在**GOT**中。
|
||||
**过程链接表(PLT)**与GOT密切配合,作为处理对外部函数的调用的跳板。当二进制文件**首次调用外部函数时,控制会传递到与该函数相关联的PLT条目**。此PLT条目负责调用动态链接器以解析函数的地址(如果尚未解析)。地址解析后,将其存储在**GOT**中。
|
||||
|
||||
**因此**,一旦外部函数或变量的地址解析完成,就直接使用GOT条目。**PLT条目用于通过动态链接器**便捷地解析这些地址的初始解析。
|
||||
**因此**,一旦解析外部函数或变量的地址,就直接使用GOT条目。**PLT条目用于通过动态链接器**便于这些地址的初始解析。
|
||||
|
||||
## 获取执行
|
||||
|
||||
|
@ -36,35 +36,41 @@ GOT中的每个条目对应于二进制文件可能调用的外部库中的符
|
|||
|
||||
![](<../../.gitbook/assets/image (121).png>)
|
||||
|
||||
观察在**GEF中加载**可执行文件后,您可以**看到**在**GOT**中的**函数**:`gef➤ x/20x 0xDIR_GOT`
|
||||
在GEF中**加载**可执行文件后,您可以**查看**GOT中的**函数**:`gef➤ x/20x 0xADDR_GOT`
|
||||
|
||||
![](<../../.gitbook/assets/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
|
||||
|
||||
使用GEF,您可以**开始**一个**调试**会话并执行**`got`**以查看got表:
|
||||
使用GEF,您可以**开始**调试会话并执行**`got`**以查看got表:
|
||||
|
||||
![](<../../.gitbook/assets/image (496).png>)
|
||||
|
||||
### GOT2Exec
|
||||
|
||||
在二进制文件中,GOT中有**函数的地址或**将加载函数地址的**PLT**部分的地址。此任意写入的目标是**覆盖将稍后执行的函数的GOT条目**,**使用**例如**`system`**函数的**PLT地址**。
|
||||
在二进制文件中,GOT中有**函数的地址或**将加载函数地址的**PLT**部分。此任意写入的目标是**覆盖将稍后执行的函数的GOT条目**,使其指向**`system`**函数的**PLT地址**。
|
||||
|
||||
理想情况下,您将**覆盖**将由您控制参数调用的**函数**的**GOT**(因此您将能够控制发送到系统函数的参数)。
|
||||
理想情况下,您将**覆盖**将由您控制参数调用的**将要调用的函数的GOT**(因此您将能够控制发送到system函数的参数)。
|
||||
|
||||
如果脚本**未使用**`system`**,则系统函数**将不会在PLT中有一个条目。在这种情况下,您将**需要首先泄漏**`system`函数的地址,然后覆盖GOT以指向此地址。
|
||||
如果二进制文件**未使用**`system`**,则系统函数**将不会在PLT中有一个条目。在这种情况下,您将**需要首先泄漏**`system`函数的地址,然后覆盖GOT以指向此地址。
|
||||
|
||||
您可以使用**`objdump -j .plt -d ./vuln_binary`**查看PLT地址。
|
||||
|
||||
## libc GOT条目
|
||||
|
||||
**libc的GOT**通常使用**部分RELRO**编译,如果可能找出其地址([**ASLR**](../common-binary-protections-and-bypasses/aslr/)),则成为此技术的一个不错的目标。
|
||||
**libc的GOT**通常使用**部分RELRO**编译,如果可能找出其地址([**ASLR**](../common-binary-protections-and-bypasses/aslr/)),则成为一个很好的目标。
|
||||
|
||||
libc的常见函数将调用**其他内部函数**,这些内部函数的GOT可以被覆盖以获取代码执行。
|
||||
libc的常见函数将调用**其他内部函数**,它们的GOT可以被覆盖以获取代码执行。
|
||||
|
||||
在[**此处找到更多关于此技术的信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)。
|
||||
在[**此处找到有关此技术的更多信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)。
|
||||
|
||||
## **Free2system**
|
||||
|
||||
在堆利用CTF中,通常可以控制块的内容,甚至在某个时刻覆盖GOT表。如果没有可用的one gadgets,一个简单的技巧是将`free`的GOT地址覆盖为指向`system`,并在一个块中写入`"/bin/sh"`。这样,当释放此块时,它将执行`system("/bin/sh")`。
|
||||
在堆利用CTF中,通常可以控制块的内容,甚至在某个时刻覆盖GOT表。如果没有可用的one gadgets,一个简单的技巧是将`free`的GOT地址覆盖为`system`,并在一个块中写入`"/bin/sh"`。这样,当释放此块时,将执行`system("/bin/sh")`。
|
||||
|
||||
## **Strlen2system**
|
||||
|
||||
另一种常见技术是将**`strlen`**的GOT地址覆盖为**`system`**,因此如果使用用户输入调用此函数,可以传递字符串`"/bin/sh"`并获得shell。
|
||||
|
||||
此外,如果使用用户输入调用`puts`,则可以将`puts`的GOT地址覆盖为`system`并传递字符串`"/bin/sh"`以获取shell,因为**`puts`将调用`strlen`处理用户输入**。
|
||||
|
||||
## **One Gadget**
|
||||
|
||||
|
@ -72,20 +78,20 @@ libc的常见函数将调用**其他内部函数**,这些内部函数的GOT可
|
|||
[one-gadget.md](../rop-return-oriented-programing/ret2lib/one-gadget.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## **滥用堆中的GOT**
|
||||
## **从堆滥用GOT**
|
||||
|
||||
从堆漏洞获取RCE的常见方法是滥用fastbin,以便将GOT表的一部分添加到fast bin中,因此每当分配该块时,将有可能**覆盖函数的指针,通常是`free`**。\
|
||||
然后,将`free`指向`system`,并释放写有`/bin/sh\x00`的块,将执行一个shell。
|
||||
|
||||
可以在[**此处找到一个示例**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk\_extend\_overlapping/#hitcon-trainging-lab13)**。**
|
||||
然后,将`free`指向`system`,并释放写有`/bin/sh\x00`的块,将执行shell。
|
||||
|
||||
可以在[**此处找到示例**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk\_extend\_overlapping/#hitcon-trainging-lab13)**。**
|
||||
## **保护**
|
||||
|
||||
**Full RELRO**保护旨在通过在二进制文件启动时解析所有函数的地址并在此后将**GOT表设为只读**来防止这种技术:
|
||||
**Full RELRO** 保护旨在通过在二进制文件启动时解析所有函数的地址并在此后将 **GOT 表设为只读** 来防止这种技术:
|
||||
|
||||
{% content-ref url="../common-binary-protections-and-bypasses/relro.md" %}
|
||||
[relro.md](../common-binary-protections-and-bypasses/relro.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## 参考资料
|
||||
|
||||
* [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
|
||||
|
@ -93,14 +99,14 @@ libc的常见函数将调用**其他内部函数**,这些内部函数的GOT可
|
|||
|
||||
<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>
|
||||
<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 的其他方式:
|
||||
|
||||
* 如果您想看到您的**公司在HackTricks中做广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
|
||||
* 探索[**PEASS Family**](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来分享您的黑客技巧。
|
||||
* 如果您想在 HackTricks 中看到您的 **公司广告** 或 **下载 PDF 版本的 HackTricks**,请查看 [**订阅计划**](https://github.com/sponsors/carlospolop)!
|
||||
* 获取 [**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
|
||||
* 探索 [**PEASS Family**](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>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
<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>
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS红队专家)</strong></a><strong>!</strong></summary>
|
||||
|
||||
其他支持HackTricks的方式:
|
||||
支持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)**。**
|
||||
* 探索[**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>
|
||||
|
@ -20,15 +20,15 @@
|
|||
现在很**奇怪找到一个带有.dtors部分的二进制文件!**
|
||||
{% endhint %}
|
||||
|
||||
析构函数是在程序结束之前(在`main`函数返回后)执行的函数。\
|
||||
这些函数的地址存储在二进制文件的**`.dtors`**部分中,因此,如果您设法**写入**一个**shellcode**的**地址**到**`__DTOR_END__`**,那么它将在程序结束之前被**执行**。
|
||||
析构函数是在程序结束之前(在`main`函数返回后)**执行**的函数。\
|
||||
这些函数的地址存储在二进制文件的**`.dtors`**部分中,因此,如果您设法**将**一个**shellcode的地址**写入**`__DTOR_END__`**,那么它将在程序结束之前**执行**。
|
||||
|
||||
使用以下命令获取此部分的地址:
|
||||
```bash
|
||||
objdump -s -j .dtors /exec
|
||||
rabin -s /exec | grep “__DTOR”
|
||||
```
|
||||
通常你会在值`ffffffff`和`00000000`之间找到**DTOR**标记。所以如果你只看到这些值,意味着**没有任何函数注册**。因此,**覆盖**`00000000`的**地址**为**shellcode**的地址以执行它。
|
||||
通常你会在值`ffffffff`和`00000000`之间找到**DTOR**标记。所以如果你只看到这些值,意味着**没有任何函数注册**。因此,**覆盖** **`00000000`** 为 **shellcode** 的地址以执行它。
|
||||
|
||||
{% hint style="warning" %}
|
||||
当然,你首先需要找到一个**存储shellcode的位置**,以便稍后调用它。
|
||||
|
@ -36,7 +36,7 @@ rabin -s /exec | grep “__DTOR”
|
|||
|
||||
## **.fini\_array**
|
||||
|
||||
本质上,这是一个包含在程序完成之前将被调用的**函数的结构**,就像**`.dtors`**一样。如果你可以通过**跳转到一个地址调用你的shellcode**,或者在需要**返回到`main`**以**第二次利用漏洞**的情况下,这就变得很有趣。
|
||||
基本上这是一个包含在程序结束前将被调用的**函数的结构**,就像**`.dtors`**一样。如果你可以通过**跳转到一个地址调用你的shellcode**,或者在需要**再次回到`main`**以**第二次利用漏洞**的情况下,这就变得很有趣。
|
||||
```bash
|
||||
objdump -s -j .fini_array ./greeting
|
||||
|
||||
|
@ -47,241 +47,32 @@ Contents of section .fini_array:
|
|||
|
||||
#Put your address in 0x8049934
|
||||
```
|
||||
请注意,当从 **`.fini_array`** 中的一个函数执行时,它会移动到下一个函数,因此不会被多次执行(防止无限循环),但它也只会给你提供一个在这里放置的 **函数执行**。
|
||||
请注意,当执行**`.fini_array`**中的一个函数时,它会移动到下一个函数,因此它不会被执行多次(防止无限循环),但它也只会给你提供一个在这里放置的**函数执行**。
|
||||
|
||||
请注意,`.fini_array` 中的条目按**相反**顺序调用,因此您可能希望从最后一个开始编写。
|
||||
请注意,`.fini_array`中的条目是以**相反的**顺序调用的,因此您可能希望从最后一个开始编写。
|
||||
|
||||
#### 无限循环
|
||||
#### 永久循环
|
||||
|
||||
为了滥用 **`.fini_array`** 以获得无限循环,您可以[**检查这里做了什么**](https://guyinatuxedo.github.io/17-stack\_pivot/insomnihack18\_onewrite/index.html)**:** 如果 **`.fini_array`** 中至少有2个条目,您可以:
|
||||
为了滥用**`.fini_array`**以获得永久循环,您可以[**查看这里完成的工作**](https://guyinatuxedo.github.io/17-stack\_pivot/insomnihack18\_onewrite/index.html)**:** 如果**`.fini_array`**中至少有2个条目,您可以:
|
||||
|
||||
* 使用第一个写入来再次调用**易受攻击的任意写入函数**
|
||||
* 然后,在由 **`__libc_csu_fini`** 存储的堆栈中计算 **返回地址**,并将 **`__libc_csu_fini`** 的地址放在那里
|
||||
* 这将使 **`__libc_csu_fini`** 再次调用自身,执行 **`.fini_array`** 函数,再次调用易受攻击的 WWW 函数2次:一次用于**任意写入**,另一次用于再次覆盖堆栈上 **`__libc_csu_fini`** 的**返回地址**,以再次调用自身。
|
||||
* 然后,在**`__libc_csu_fini`**(调用所有`.fini_array`函数的函数)中计算堆栈中存储的返回地址,并将**`__libc_csu_fini`**的地址放在那里
|
||||
* 这将使**`__libc_csu_fini`**再次调用自身,执行**`.fini_array`**函数,这将再次调用易受攻击的WWW函数2次:一次用于**任意写入**,另一次用于再次覆盖堆栈上**`__libc_csu_fini`**的返回地址以再次调用自身。
|
||||
|
||||
{% hint style="danger" %}
|
||||
请注意,使用[**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** **`.fini_array`** 部分被设置为**只读**。
|
||||
请注意,使用[**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,**`.fini_array`**部分被设置为**只读**。
|
||||
在更新的版本中,即使使用[**Partial RELRO**],`.fini_array`**部分也被设置为**只读**。
|
||||
{% endhint %}
|
||||
|
||||
## link\_map
|
||||
|
||||
如[**此帖子**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure)中所解释的,如果程序使用 `return` 或 `exit()` 退出,它将运行 `__run_exit_handlers()`,该函数将调用已注册的析构函数。
|
||||
|
||||
{% hint style="danger" %}
|
||||
如果程序通过 **`_exit()`** 函数退出,它将调用 **`exit` 系统调用**,退出处理程序将不会被执行。因此,要确认 `__run_exit_handlers()` 是否被执行,您可以在其上设置断点。
|
||||
{% endhint %}
|
||||
|
||||
重要代码为([源代码](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
```c
|
||||
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
|
||||
if (fini_array != NULL)
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the d_un structure
|
||||
ptype l->l_info[DT_FINI_ARRAY]->d_un
|
||||
type = union {
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
}
|
||||
```
|
||||
注意`map -> l_addr + fini_array -> d_un.d_ptr`是用来**计算** **要调用的函数数组** 的位置。
|
||||
|
||||
有**几种选择**:
|
||||
|
||||
* 覆盖`map->l_addr`的值,使其指向一个带有执行任意代码指令的**伪造`fini_array`**。
|
||||
* 覆盖`l_info[DT_FINI_ARRAY]`和`l_info[DT_FINI_ARRAYSZ]`条目(在内存中更或多少是连续的),使它们指向一个伪造的`Elf64_Dyn`结构,再次使**`array`指向攻击者控制的内存区域**。
|
||||
* [**这篇文章**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell)用受控内存中`.bss`中的地址覆盖了`l_info[DT_FINI_ARRAY]`,其中包含一个伪造的`fini_array`。这个伪造数组首先包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md)的地址,然后是这个**伪造数组**地址与`map->l_addr`值之间的**差异**,以便`*array`指向伪造数组。
|
||||
* 根据这种技术的主要帖子和[**这篇文章**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet),ld.so在栈上留下一个指向ld.so中的二进制`link_map`的指针。通过任意写入,可以覆盖它并使其指向由攻击者控制的伪造`fini_array`,其中包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md)的地址,例如。
|
||||
|
||||
在前面的代码之后,您可以找到另一个有趣的部分,其中包含以下代码:
|
||||
```c
|
||||
/* Next try the old-style destructor. */
|
||||
ElfW(Dyn) *fini = map->l_info[DT_FINI];
|
||||
if (fini != NULL)
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
}
|
||||
```
|
||||
在这种情况下,可以覆盖`map->l_info[DT_FINI]`的值,指向一个伪造的`ElfW(Dyn)`结构。在[**这里找到更多信息**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure)。
|
||||
|
||||
## 在**`__run_exit_handlers`**中覆盖TLS存储dtor_list
|
||||
|
||||
如[**这里解释的**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite),如果程序通过`return`或`exit()`退出,它将执行**`__run_exit_handlers()`**,该函数将调用任何已注册的析构函数。
|
||||
|
||||
来自`_run_exit_handlers()`的代码:
|
||||
```c
|
||||
/* Call all functions registered with `atexit' and `on_exit',
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
void
|
||||
attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
#ifndef SHARED
|
||||
if (&__call_tls_dtors != NULL)
|
||||
#endif
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
```
|
||||
**`__call_tls_dtors()`** 函数的代码:
|
||||
```c
|
||||
typedef void (*dtor_func) (void *);
|
||||
struct dtor_list //struct added
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
[...]
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
对于**`tls_dtor_list`**中的每个注册函数,它将从**`cur->func`**中解码指针并使用参数**`cur->obj`**调用它。
|
||||
|
||||
使用来自[**GEF的这个分支**](https://github.com/bata24/gef)中的**`tls`**函数,可以看到**`dtor_list`**实际上非常**接近****栈保护**和**PTR\_MANGLE cookie**。因此,通过对其进行溢出,可以**覆盖****cookie**和**栈保护**。\
|
||||
覆盖PTR\_MANGLE cookie,将有可能**绕过`PTR_DEMANLE`函数**,因为将其设置为0x00,将意味着用于获取真实地址的**`xor`**仅是配置的地址。然后,在**`dtor_list`**上写入,可以使用函数**地址**及其**参数**来**链接多个函数**。
|
||||
|
||||
最后请注意,存储的指针不仅会与cookie进行异或运算,还会旋转17位:
|
||||
```armasm
|
||||
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
|
||||
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
|
||||
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
|
||||
```
|
||||
在添加新地址之前,您需要考虑这一点。
|
||||
|
||||
在[**原始帖子**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite)中找一个例子。
|
||||
|
||||
## **`__run_exit_handlers`** 中的其他混淆指针
|
||||
|
||||
这种技术在[**这里解释**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite),再次取决于程序**通过调用 `return` 或 `exit()` 退出**,从而调用 **`__run_exit_handlers()`**。
|
||||
|
||||
让我们检查一下这个函数的更多代码:
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
|
||||
restart:
|
||||
cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
```
|
||||
变量`f`指向**`initial`**结构,根据`f->flavor`的值不同,将调用不同的函数。\
|
||||
根据数值不同,要调用的函数地址会在不同的位置,但它们始终会被**解码**。
|
||||
|
||||
此外,在选项**`ef_on`**和**`ef_cxa`**中,还可以控制一个**参数**。
|
||||
|
||||
可以在使用GEF运行**`gef> p initial`**的调试会话中检查**`initial`结构**。
|
||||
|
||||
要利用这一点,您需要**泄漏或擦除`PTR_MANGLE`cookie**,然后用`system('/bin/sh')`覆盖`initial`中的`cxa`条目。\
|
||||
您可以在[**有关该技术的原始博客文章**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure)中找到一个示例。
|
||||
|
||||
<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>
|
||||
<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),我们独家的[NFTs](https://opensea.io/collection/the-peass-family)收藏品
|
||||
* 发现[**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来分享您的黑客技巧。
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# WWW2Exec - atexit()
|
||||
# WWW2Exec - atexit(), TLS Storage & 其他混淆指针
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS红队专家)</strong></a><strong>!</strong></summary>
|
||||
<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来分享您的黑客技巧。
|
||||
- 如果您想看到您的**公司在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>
|
||||
|
||||
|
@ -20,23 +20,233 @@
|
|||
现在很**奇怪去利用这个!**
|
||||
{% endhint %}
|
||||
|
||||
**`atexit()`** 是一个函数,**其他函数被作为参数传递给它。** 这些**函数**将在执行**`exit()`**或**main**的**返回**时执行。\
|
||||
如果您可以**修改**其中任何一个**函数**的**地址**,使其指向一个shellcode,例如,您将**控制**该**进程**,但目前这更加复杂。\
|
||||
目前要执行的**函数的地址**被隐藏在几个结构后面,最终指向的地址不是函数的地址,而是使用**XOR加密**和**随机密钥**进行位移。因此,目前这种攻击向量在至少在x86和x64\_86上**不太有用**。\
|
||||
**加密函数**是**`PTR_MANGLE`**。其他架构,如m68k、mips32、mips64、aarch64、arm、hppa... **不实现**加密函数,因为它**返回**与输入相同的内容。因此,这些架构可以通过这种向量进行攻击。
|
||||
**`atexit()`** 是一个函数,**其他函数作为参数传递给它。** 这些**函数**将在执行**`exit()`**或**main**的**返回**时执行。\
|
||||
如果您可以**修改**这些**函数**中任何一个的**地址**,使其指向一个shellcode,那么您将**控制**该**进程**,但目前这更加复杂。\
|
||||
目前要执行的**函数地址**被隐藏在几个结构后面,最终指向的地址不是函数的地址,而是使用**XOR加密**和**随机密钥**进行位移。因此,目前这种攻击向量在至少在x86和x64\_86上**不太有用**。\
|
||||
**加密函数**是**`PTR_MANGLE`**。其他架构,如m68k、mips32、mips64、aarch64、arm、hppa... **不实现加密**函数,因为它**返回与输入相同**的内容。因此,这些架构可以通过这种向量进行攻击。
|
||||
|
||||
您可以在[https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)找到关于这个工作原理的深入解释。
|
||||
|
||||
## link\_map
|
||||
|
||||
如[**此帖子**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure)中所述,如果程序使用`return`或`exit()`退出,它将运行`__run_exit_handlers()`,该函数将调用已注册的析构函数。
|
||||
|
||||
{% hint style="danger" %}
|
||||
如果程序通过**`_exit()`**函数退出,它将调用**`exit`系统调用**,退出处理程序将不会被执行。因此,要确认`__run_exit_handlers()`是否被执行,您可以在其上设置断点。
|
||||
{% endhint %}
|
||||
|
||||
重要的代码是([源代码](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
|
||||
```c
|
||||
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
|
||||
if (fini_array != NULL)
|
||||
{
|
||||
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
|
||||
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
|
||||
|
||||
while (sz-- > 0)
|
||||
((fini_t) array[sz]) ();
|
||||
}
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
|
||||
// This is the d_un structure
|
||||
ptype l->l_info[DT_FINI_ARRAY]->d_un
|
||||
type = union {
|
||||
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
|
||||
Elf64_Addr d_ptr; // offset from l->l_addr of our structure
|
||||
}
|
||||
```
|
||||
注意`map -> l_addr + fini_array -> d_un.d_ptr`是如何用来**计算** **要调用的函数数组** 的位置。
|
||||
|
||||
有一些**选项**:
|
||||
|
||||
* 覆盖`map->l_addr`的值,使其指向一个带有执行任意代码指令的**伪造`fini_array`**
|
||||
* 覆盖`l_info[DT_FINI_ARRAY]`和`l_info[DT_FINI_ARRAYSZ]`条目(在内存中更或多少是连续的),使它们指向一个伪造的`Elf64_Dyn`结构,再次使**`array`指向攻击者控制的内存区域**。 
|
||||
* [**这篇文章**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell)用受控内存中`.bss`中的地址覆盖了`l_info[DT_FINI_ARRAY]`,其中包含一个伪造的`fini_array`。这个伪造的数组首先包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **地址**,然后是这个**伪造数组**地址与`map->l_addr`值之间的**差异**,以便`*array`指向伪造数组。
|
||||
* 根据这种技术的主要帖子和[**这篇文章**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet),ld.so在栈上留下一个指向ld.so中的二进制`link_map`的指针。通过任意写入,可以覆盖它并使其指向由攻击者控制的伪造`fini_array`,其中包含一个[**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md)的地址,例如。
|
||||
|
||||
在前面的代码之后,您可以找到另一个有趣的部分,其中包含以下代码:
|
||||
```c
|
||||
/* Next try the old-style destructor. */
|
||||
ElfW(Dyn) *fini = map->l_info[DT_FINI];
|
||||
if (fini != NULL)
|
||||
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
|
||||
}
|
||||
```
|
||||
在这种情况下,有可能覆盖`map->l_info[DT_FINI]`的值,指向一个伪造的`ElfW(Dyn)`结构。查找[**更多信息请点击这里**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure)。
|
||||
|
||||
## 在**`__run_exit_handlers`**中的TLS存储dtor\_list覆写
|
||||
|
||||
正如[**这里解释的**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite),如果程序通过`return`或`exit()`退出,它将执行**`__run_exit_handlers()`**,这将调用任何已注册的析构函数。
|
||||
|
||||
来自`_run_exit_handlers()`的代码:
|
||||
```c
|
||||
/* Call all functions registered with `atexit' and `on_exit',
|
||||
in the reverse of the order in which they were registered
|
||||
perform stdio cleanup, and terminate program execution with STATUS. */
|
||||
void
|
||||
attribute_hidden
|
||||
__run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
bool run_list_atexit, bool run_dtors)
|
||||
{
|
||||
/* First, call the TLS destructors. */
|
||||
#ifndef SHARED
|
||||
if (&__call_tls_dtors != NULL)
|
||||
#endif
|
||||
if (run_dtors)
|
||||
__call_tls_dtors ();
|
||||
```
|
||||
来自**`__call_tls_dtors()`**的代码:
|
||||
```c
|
||||
typedef void (*dtor_func) (void *);
|
||||
struct dtor_list //struct added
|
||||
{
|
||||
dtor_func func;
|
||||
void *obj;
|
||||
struct link_map *map;
|
||||
struct dtor_list *next;
|
||||
};
|
||||
|
||||
[...]
|
||||
/* Call the destructors. This is called either when a thread returns from the
|
||||
initial function or when the process exits via the exit function. */
|
||||
void
|
||||
__call_tls_dtors (void)
|
||||
{
|
||||
while (tls_dtor_list) // parse the dtor_list chained structures
|
||||
{
|
||||
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
|
||||
dtor_func func = cur->func;
|
||||
PTR_DEMANGLE (func); // demangle the function ptr
|
||||
|
||||
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
|
||||
func (cur->obj);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
对于**`tls_dtor_list`**中的每个注册函数,它将从**`cur->func`**中解码指针并使用参数**`cur->obj`**调用它。
|
||||
|
||||
使用来自[**GEF的分支**](https://github.com/bata24/gef)中的**`tls`**函数,可以看到**`dtor_list`**实际上非常接近**栈canary**和**PTR\_MANGLE cookie**。因此,通过对其进行溢出,可以**覆盖**cookie和**栈canary**。\
|
||||
覆盖PTR\_MANGLE cookie,将可能通过将其设置为0x00来**绕过`PTR_DEMANLE`函数**,这意味着用于获取真实地址的**`xor`**仅是配置的地址。然后,通过在**`dtor_list`**上写入,可以使用函数**地址**及其**参数**来**链接多个函数**。
|
||||
|
||||
最后请注意,存储的指针不仅会与cookie进行异或运算,还会旋转17位:
|
||||
```armasm
|
||||
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
|
||||
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
|
||||
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
|
||||
```
|
||||
所以在添加新地址之前,您需要考虑这一点。
|
||||
|
||||
在[**原始帖子**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite)中找一个例子。
|
||||
|
||||
## **`__run_exit_handlers`** 中的其他混淆指针
|
||||
|
||||
这个技术在[**这里解释**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite),再次取决于程序**通过调用 `return` 或 `exit()` 退出**,从而调用 **`__run_exit_handlers()`**。
|
||||
|
||||
让我们检查一下这个函数的更多代码:
|
||||
```c
|
||||
while (true)
|
||||
{
|
||||
struct exit_function_list *cur;
|
||||
|
||||
restart:
|
||||
cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
/* Exit processing complete. We will not allow any more
|
||||
atexit/on_exit registrations. */
|
||||
__exit_funcs_done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cur->idx > 0)
|
||||
{
|
||||
struct exit_function *const f = &cur->fns[--cur->idx];
|
||||
const uint64_t new_exitfn_called = __new_exitfn_called;
|
||||
|
||||
switch (f->flavor)
|
||||
{
|
||||
void (*atfct) (void);
|
||||
void (*onfct) (int status, void *arg);
|
||||
void (*cxafct) (void *arg, int status);
|
||||
void *arg;
|
||||
|
||||
case ef_free:
|
||||
case ef_us:
|
||||
break;
|
||||
case ef_on:
|
||||
onfct = f->func.on.fn;
|
||||
arg = f->func.on.arg;
|
||||
PTR_DEMANGLE (onfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
onfct (status, arg);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_at:
|
||||
atfct = f->func.at;
|
||||
PTR_DEMANGLE (atfct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
atfct ();
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
case ef_cxa:
|
||||
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
|
||||
we must mark this function as ef_free. */
|
||||
f->flavor = ef_free;
|
||||
cxafct = f->func.cxa.fn;
|
||||
arg = f->func.cxa.arg;
|
||||
PTR_DEMANGLE (cxafct);
|
||||
|
||||
/* Unlock the list while we call a foreign function. */
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
cxafct (arg, status);
|
||||
__libc_lock_lock (__exit_funcs_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
if (*listp != NULL)
|
||||
/* Don't free the last element in the chain, this is the statically
|
||||
allocate element. */
|
||||
free (cur);
|
||||
}
|
||||
|
||||
__libc_lock_unlock (__exit_funcs_lock);
|
||||
```
|
||||
变量`f`指向**`initial`**结构,根据`f->flavor`的值不同,将调用不同的函数。\
|
||||
根据数值不同,要调用的函数地址将位于不同位置,但始终会**解码**。
|
||||
|
||||
此外,在选项**`ef_on`**和**`ef_cxa`**中,还可以控制一个**参数**。
|
||||
|
||||
可以在使用GEF运行**`gef> p initial`**的调试会话中检查**`initial`结构**。
|
||||
|
||||
要利用这一点,您需要泄漏或擦除`PTR_MANGLE`cookie,然后用`system('/bin/sh')`覆盖initial中的`cxa`条目。\
|
||||
您可以在[**有关该技术的原始博客文章**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure)中找到一个示例。
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks AWS红队专家)</strong></a><strong>!</strong></summary>
|
||||
<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)!
|
||||
* 如果您想看到您的**公司在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)**。**
|
||||
* 探索[**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>
|
||||
|
|
Loading…
Reference in a new issue