mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-24 05:33:33 +00:00
Translated ['binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc
This commit is contained in:
parent
345e349fcd
commit
b70783dfd4
4 changed files with 294 additions and 278 deletions
|
@ -2,12 +2,12 @@
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>Aprenda hacking na AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira [**produtos oficiais PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
|
@ -38,50 +38,58 @@ Isso foi abusado em um dos exemplos da página abusando de um ataque de fast bin
|
|||
[unsorted-bin-attack.md](../libc-heap/unsorted-bin-attack.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
Um truque interessante (de [**aqui**](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html)) para encontrar a localização do free hook se o binário tiver símbolos é **fazer algo como**:
|
||||
É possível encontrar o endereço de `__free_hook` se o binário tiver símbolos com o seguinte comando:
|
||||
```bash
|
||||
gef➤ p &__free_hook
|
||||
```
|
||||
gef➤ set __free_hook = 0xfacade
|
||||
gef➤ search-pattern 0xfacade
|
||||
```
|
||||
No mesmo post, você pode encontrar um guia passo a passo sobre como localizar o endereço do **free hook** sem símbolos. Em resumo, na função **free**:
|
||||
[No post](https://guyinatuxedo.github.io/41-house\_of\_force/bkp16\_cookbook/index.html) você pode encontrar um guia passo a passo sobre como localizar o endereço do **free hook** sem símbolos. Em resumo, na função **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]--- BREAK HERE
|
||||
</strong>0xf75deddb <free+27>: test eax,eax ;<
|
||||
0xf75deddd <free+29>: jne 0xf75dee50 <free+144>
|
||||
</code></pre>
|
||||
|
||||
Na quebra mencionada no código anterior em `$eax` estará localizado o endereço do **free hook**.
|
||||
|
||||
Agora é realizado um **ataque de fast bin**:
|
||||
|
||||
- Primeiramente, é descoberto que é possível trabalhar com **pedaços rápidos de tamanho 200** na localização do **`__free_hook`**:
|
||||
-
|
||||
|
||||
```c
|
||||
gef➤ p &__free_hook
|
||||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||||
- Primeiramente é descoberto que é possível trabalhar com **pedaços rápidos de tamanho 200** na localização do **`__free_hook`**:
|
||||
- <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
|
||||
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||||
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||||
```
|
||||
|
||||
- Se conseguirmos obter um pedaço rápido de tamanho 0x200 nessa localização, será possível sobrescrever um ponteiro de função que será executado.
|
||||
- Para isso, é criado um novo pedaço de tamanho `0xfc` e a função mesclada é chamada com esse ponteiro duas vezes, dessa forma obtemos um ponteiro para um pedaço liberado de tamanho `0xfc*2 = 0x1f8` no fast bin.
|
||||
<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>
|
||||
- Se conseguirmos obter um pedaço rápido de tamanho 0x200 nessa localização, será possível sobrescrever um ponteiro de função que será executado
|
||||
- Para isso, um novo pedaço de tamanho `0xfc` é criado e a função mesclada é chamada com esse ponteiro duas vezes, dessa forma obtemos um ponteiro para um pedaço liberado de tamanho `0xfc*2 = 0x1f8` no fast bin.
|
||||
- Em seguida, a função de edição é chamada neste pedaço para modificar o endereço **`fd`** deste fast bin para apontar para a função anterior **`__free_hook`**.
|
||||
- Depois, é criado um pedaço com tamanho `0x1f8` para recuperar do fast bin o pedaço inútil anterior, então outro pedaço com tamanho `0x1f8` é criado para obter um pedaço do fast bin no **`__free_hook`** que é sobrescrito com o endereço da função **`system`**.
|
||||
- E finalmente, um pedaço contendo a string `/bin/sh\x00` é liberado chamando a função de exclusão, acionando a função **`__free_hook`** que aponta para o sistema com `/bin/sh\x00` como parâmetro.
|
||||
- Depois, um pedaço com tamanho `0x1f8` é criado para recuperar do fast bin o pedaço inútil anterior, então outro pedaço com tamanho `0x1f8` é criado para obter um pedaço do fast bin no **`__free_hook`** que é sobrescrito com o endereço da função **`system`**.
|
||||
- E finalmente um pedaço contendo a string `/bin/sh\x00` é liberado chamando a função de exclusão, acionando a função **`__free_hook`** que aponta para o sistema com `/bin/sh\x00` como parâmetro.
|
||||
|
||||
## Referências
|
||||
|
||||
- [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>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -20,13 +20,13 @@ Outras maneiras de apoiar o HackTricks:
|
|||
|
||||
A **Tabela de Deslocamento Global (GOT)** é um mecanismo usado em binários com ligação dinâmica para gerenciar os **endereços de funções externas**. Como esses **endereços não são conhecidos até o tempo de execução** (devido à ligação dinâmica), a GOT fornece uma maneira de **atualizar dinamicamente os endereços desses símbolos externos** uma vez que são resolvidos.
|
||||
|
||||
Cada entrada na GOT corresponde a um símbolo nas bibliotecas externas que o binário pode chamar. Quando uma **função é chamada pela primeira vez, seu endereço real é resolvido pelo vinculador dinâmico e armazenado na GOT**. Chamadas subsequentes para a mesma função usam o endereço armazenado na GOT, evitando assim o custo de resolver o endereço novamente.
|
||||
Cada entrada na GOT corresponde a um símbolo nas bibliotecas externas que o binário pode chamar. Quando uma **função é chamada pela primeira vez, seu endereço real é resolvido pelo linkador dinâmico e armazenado na GOT**. Chamadas subsequentes para a mesma função usam o endereço armazenado na GOT, evitando assim o custo de resolver o endereço novamente.
|
||||
|
||||
### **PLT: Tabela de Vínculo de Procedimento**
|
||||
### **PLT: Tabela de Ligação de Procedimentos**
|
||||
|
||||
A **Tabela de Vínculo de Procedimento (PLT)** trabalha em conjunto com a GOT e serve como um trampolim para lidar com chamadas a funções externas. Quando um binário **chama uma função externa pela primeira vez, o controle é passado para uma entrada na PLT associada a essa função**. Essa entrada da PLT é responsável por invocar o vinculador dinâmico para resolver o endereço da função se ainda não tiver sido resolvido. Após a resolução do endereço, ele é armazenado na **GOT**.
|
||||
A **Tabela de Ligação de Procedimentos (PLT)** trabalha em conjunto com a GOT e serve como um trampolim para lidar com chamadas a funções externas. Quando um binário **chama uma função externa pela primeira vez, o controle é passado para uma entrada na PLT associada a essa função**. Esta entrada da PLT é responsável por invocar o linkador dinâmico para resolver o endereço da função se ainda não tiver sido resolvido. Após o endereço ser resolvido, ele é armazenado na **GOT**.
|
||||
|
||||
**Portanto,** as entradas da GOT são usadas diretamente uma vez que o endereço de uma função ou variável externa é resolvido. **As entradas da PLT são usadas para facilitar a resolução inicial** desses endereços via o vinculador dinâmico.
|
||||
**Portanto,** as entradas da GOT são usadas diretamente uma vez que o endereço de uma função ou variável externa é resolvido. **As entradas da PLT são usadas para facilitar a resolução inicial** desses endereços via linkador dinâmico.
|
||||
|
||||
## Obter Execução
|
||||
|
||||
|
@ -36,21 +36,21 @@ Obtenha o endereço da tabela GOT com: **`objdump -s -j .got ./exec`**
|
|||
|
||||
![](<../../.gitbook/assets/image (121).png>)
|
||||
|
||||
Observe como após **carregar** o **executável** no GEF você pode **ver** as **funções** que estão na **GOT**: `gef➤ x/20x 0xDIR_GOT`
|
||||
Observe como após **carregar** o **executável** no GEF você pode **ver** as **funções** que estão na **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) (1) (2) (2) (2).png>)
|
||||
![](<../../.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>)
|
||||
|
||||
Usando o GEF você pode **iniciar** uma **sessão de depuração** e executar **`got`** para ver a tabela got:
|
||||
Usando o GEF você pode **iniciar** uma sessão de **depuração** e executar **`got`** para ver a tabela got:
|
||||
|
||||
![](<../../.gitbook/assets/image (496).png>)
|
||||
|
||||
### GOT2Exec
|
||||
|
||||
Em um binário a GOT tem os **endereços das funções ou** da seção **PLT** que carregará o endereço da função. O objetivo desta escrita arbitrária é **substituir uma entrada da GOT** de uma função que será executada posteriormente **com** o **endereço** do PLT da **função `system`** por exemplo.
|
||||
Em um binário a GOT tem os **endereços das funções ou** da seção **PLT** que carregará o endereço da função. O objetivo desta escrita arbitrária é **substituir uma entrada da GOT** de uma função que será executada posteriormente **com** o **endereço** do PLT da função **`system`** por exemplo.
|
||||
|
||||
Idealmente, você irá **substituir** a **GOT** de uma **função** que está **sendo chamada com parâmetros controlados por você** (assim você poderá controlar os parâmetros enviados para a função system).
|
||||
|
||||
Se **`system`** **não for usado** pelo script, a função system **não** terá uma entrada na PLT. Nesse cenário, você precisará **vazar primeiro o endereço** da função `system` e então sobrescrever a GOT para apontar para este endereço.
|
||||
Se **`system`** **não for usada** pelo binário, a função system **não** terá uma entrada na PLT. Neste cenário, você precisará **vazar primeiro o endereço** da função `system` e então sobrescrever a GOT para apontar para este endereço.
|
||||
|
||||
Você pode ver os endereços da PLT com **`objdump -j .plt -d ./vuln_binary`**
|
||||
|
||||
|
@ -64,7 +64,13 @@ Encontre [**mais informações sobre essa técnica aqui**](https://github.com/no
|
|||
|
||||
## **Free2system**
|
||||
|
||||
Em CTFs de exploração de heap, é comum poder controlar o conteúdo dos blocos e, em algum momento, até mesmo sobrescrever a tabela GOT. Um truque simples para obter RCE se um gadget não estiver disponível é sobrescrever o endereço GOT do `free` para apontar para `system` e escrever dentro de um bloco `"/bin/sh"`. Dessa forma, quando esse bloco for liberado, ele executará `system("/bin/sh")`.
|
||||
Em CTFs de exploração de heap, é comum poder controlar o conteúdo de chunks e em algum momento até mesmo sobrescrever a tabela GOT. Um truque simples para obter RCE se um gadget não estiver disponível é sobrescrever o endereço GOT de `free` para apontar para `system` e escrever dentro de um chunk `"/bin/sh"`. Dessa forma, quando este chunk for liberado, ele executará `system("/bin/sh")`.
|
||||
|
||||
## **Strlen2system**
|
||||
|
||||
Outra técnica comum é sobrescrever o endereço **`strlen`** GOT para apontar para **`system`**, então se esta função for chamada com entrada do usuário é possível passar a string `"/bin/sh"` e obter um shell.
|
||||
|
||||
Além disso, se `puts` for usado com entrada do usuário, é possível sobrescrever o endereço GOT de `puts` para apontar para `system` e passar a string `"/bin/sh"` para obter um shell porque **`puts` chamará `strlen` com a entrada do usuário**.
|
||||
|
||||
## **One Gadget**
|
||||
|
||||
|
@ -74,18 +80,18 @@ Em CTFs de exploração de heap, é comum poder controlar o conteúdo dos blocos
|
|||
|
||||
## **Abusando da GOT do Heap**
|
||||
|
||||
Uma maneira comum de obter RCE a partir de uma vulnerabilidade de heap é abusar de um fastbin para ser possível adicionar parte da tabela GOT ao fast bin, para que sempre que esse bloco for alocado seja possível **sobrescrever o ponteiro de uma função, geralmente `free`**.\
|
||||
Então, apontando `free` para `system` e liberando um bloco onde foi escrito `/bin/sh\x00` executará um shell.
|
||||
Uma maneira comum de obter RCE a partir de uma vulnerabilidade de heap é abusar de um fastbin para ser possível adicionar parte da tabela GOT no fast bin, então sempre que aquele chunk for alocado será possível **sobrescrever o ponteiro de uma função, geralmente `free`**.\
|
||||
Em seguida, apontar `free` para `system` e liberar um chunk onde foi escrito `/bin/sh\x00` executará um shell.
|
||||
|
||||
É possível encontrar um [**exemplo aqui**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk\_extend\_overlapping/#hitcon-trainging-lab13)**.**
|
||||
|
||||
## **Proteções**
|
||||
|
||||
A proteção **Full RELRO** visa proteger contra esse tipo de técnica resolvendo todos os endereços das funções quando o binário é iniciado e tornando a **tabela GOT somente leitura** depois disso:
|
||||
A proteção **Full RELRO** é destinada a proteger contra esse tipo de técnica, resolvendo todos os endereços das funções quando o binário é iniciado e tornando a **tabela GOT somente leitura** depois disso:
|
||||
|
||||
{% content-ref url="../common-binary-protections-and-bypasses/relro.md" %}
|
||||
[relro.md](../common-binary-protections-and-bypasses/relro.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Referências
|
||||
|
||||
* [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,12 +99,12 @@ A proteção **Full RELRO** visa proteger contra esse tipo de técnica resolvend
|
|||
|
||||
<details>
|
||||
|
||||
<summary><strong>Aprenda hacking na AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
* **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -28,7 +28,7 @@ Obtenha o endereço desta seção com:
|
|||
objdump -s -j .dtors /exec
|
||||
rabin -s /exec | grep “__DTOR”
|
||||
```
|
||||
Normalmente você encontrará os marcadores **DTOR** **entre** os valores `ffffffff` e `00000000`. Portanto, se você apenas ver esses valores, significa que **não há nenhuma função registrada**. Portanto, **sobrescreva** o **`00000000`** com o **endereço** do **shellcode** para executá-lo.
|
||||
Normalmente você encontrará os marcadores **DTOR** **entre** os valores `ffffffff` e `00000000`. Portanto, se você apenas ver esses valores, significa que **não há nenhuma função registrada**. Então, **sobrescreva** o **`00000000`** com o **endereço** do **shellcode** para executá-lo.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Claro, primeiro você precisa encontrar um **local para armazenar o shellcode** para depois chamá-lo.
|
||||
|
@ -61,217 +61,9 @@ Para abusar do **`.fini_array`** e obter um loop eterno, você pode [**ver o que
|
|||
|
||||
{% hint style="danger" %}
|
||||
Note que com [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** a seção **`.fini_array`** é tornada **somente leitura**.
|
||||
Em versões mais recentes, mesmo com [**Partial RELRO**], a seção **`.fini_array`** também é tornada **somente leitura**.
|
||||
{% endhint %}
|
||||
|
||||
## link\_map
|
||||
|
||||
Como explicado [**neste post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure), se o programa sair usando `return` ou `exit()`, ele executará `__run_exit_handlers()` que chamará os destruidores registrados.
|
||||
|
||||
{% hint style="danger" %}
|
||||
Se o programa sair via função **`_exit()`**, ele chamará a **chamada de sistema `exit`** e os manipuladores de saída não serão executados. Portanto, para confirmar que `__run_exit_handlers()` está sendo executado, você pode definir um breakpoint nele.
|
||||
{% endhint %}
|
||||
|
||||
O código importante é ([fonte](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
|
||||
}
|
||||
```
|
||||
Observe como `map -> l_addr + fini_array -> d_un.d_ptr` é usado para **calcular** a posição do **array de funções a serem chamadas**.
|
||||
|
||||
Existem **algumas opções**:
|
||||
|
||||
* Sobrescrever o valor de `map->l_addr` para fazê-lo apontar para um **`fini_array` falso** com instruções para executar código arbitrário
|
||||
* Sobrescrever as entradas `l_info[DT_FINI_ARRAY]` e `l_info[DT_FINI_ARRAYSZ]` (que são mais ou menos consecutivas na memória), para fazer com que elas apontem para uma estrutura `Elf64_Dyn` forjada que fará novamente **`array` apontar para uma zona de memória** controlada pelo atacante. 
|
||||
* [**Este relatório**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) sobrescreve `l_info[DT_FINI_ARRAY]` com o endereço de uma memória controlada em `.bss` contendo um `fini_array` falso. Este array falso contém **primeiro um** [**endereço de one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) que será executado e depois a **diferença** entre o endereço deste **array falso** e o **valor de `map->l_addr`** para que `*array` aponte para o array falso.
|
||||
* De acordo com a postagem principal desta técnica e [**este relatório**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so deixa um ponteiro na pilha que aponta para o `link_map` binário em ld.so. Com uma escrita arbitrária é possível sobrescrevê-lo e fazê-lo apontar para um `fini_array` falso controlado pelo atacante com o endereço de um [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md), por exemplo.
|
||||
|
||||
Seguindo o código anterior, você pode encontrar outra seção interessante com o código:
|
||||
```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));
|
||||
}
|
||||
```
|
||||
Neste caso, seria possível sobrescrever o valor de `map->l_info[DT_FINI]` apontando para uma estrutura `ElfW(Dyn)` forjada. Encontre [**mais informações aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure).
|
||||
|
||||
## Sobrescrevendo a lista de dtor\_list de TLS-Storage em **`__run_exit_handlers`**
|
||||
|
||||
Conforme [**explicado aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite), se um programa encerra via `return` ou `exit()`, ele executará **`__run_exit_handlers()`** que chamará qualquer função de destruição registrada.
|
||||
|
||||
Código de `_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 ();
|
||||
```
|
||||
Código de **`__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);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
Para cada função registrada em **`tls_dtor_list`**, ele irá desembaralhar o ponteiro de **`cur->func`** e chamá-lo com o argumento **`cur->obj`**.
|
||||
|
||||
Usando a função **`tls`** deste [**fork do GEF**](https://github.com/bata24/gef), é possível ver que na verdade a **`dtor_list`** está muito **próxima** do **canário de pilha** e do **cookie PTR\_MANGLE**. Portanto, com um estouro nela, seria possível **sobrescrever** o **cookie** e o **canário de pilha**.\
|
||||
Sobrescrevendo o cookie PTR\_MANGLE, seria possível **burlar a função `PTR_DEMANLE`** ao defini-lo como 0x00, o que significa que o **`xor`** usado para obter o endereço real é apenas o endereço configurado. Em seguida, escrevendo na **`dtor_list`**, é possível **encadear várias funções** com o endereço da função e seu **argumento**.
|
||||
|
||||
Por fim, observe que o ponteiro armazenado não apenas será xorado com o cookie, mas também rotacionado 17 bits:
|
||||
```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
|
||||
```
|
||||
Portanto, você precisa levar isso em consideração antes de adicionar um novo endereço.
|
||||
|
||||
Encontre um exemplo no [**post original**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite).
|
||||
|
||||
## Outros ponteiros corrompidos em **`__run_exit_handlers`**
|
||||
|
||||
Essa técnica é [**explicada aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite) e depende novamente do programa **sair chamando `return` ou `exit()`** para que **`__run_exit_handlers()`** seja chamado.
|
||||
|
||||
Vamos verificar mais código desta função:
|
||||
```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);
|
||||
```
|
||||
A variável `f` aponta para a estrutura **`initial`** e dependendo do valor de `f->flavor`, diferentes funções serão chamadas.\
|
||||
Dependendo do valor, o endereço da função a ser chamada estará em um local diferente, mas sempre será **desembaralhado**.
|
||||
|
||||
Além disso, nas opções **`ef_on`** e **`ef_cxa`**, também é possível controlar um **argumento**.
|
||||
|
||||
É possível verificar a estrutura **`initial`** em uma sessão de depuração com o GEF executando **`gef> p initial`**.
|
||||
|
||||
Para abusar disso, você precisa vazar ou apagar o **cookie `PTR_MANGLE`** e então sobrescrever uma entrada `cxa` em initial com `system('/bin/sh')`.\
|
||||
Você pode encontrar um exemplo disso no [**post original do blog sobre a técnica**](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>
|
||||
|
||||
|
@ -281,8 +73,8 @@ Outras maneiras de apoiar o HackTricks:
|
|||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou nos siga no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os repositórios do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
* Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -1,42 +1,252 @@
|
|||
# WWW2Exec - atexit()
|
||||
# WWW2Exec - atexit(), Armazenamento TLS e Outros Ponteiros Manipulados
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
<summary><strong>Aprenda hacking na AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
* **Compartilhe seus truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
|
||||
</details>
|
||||
|
||||
## **\_\_atexit Estruturas**
|
||||
## **Estruturas \_\_atexit**
|
||||
|
||||
{% hint style="danger" %}
|
||||
Atualmente é muito **estranho explorar isso!**
|
||||
{% endhint %}
|
||||
|
||||
**`atexit()`** é uma função para a qual **outras funções são passadas como parâmetros.** Essas **funções** serão **executadas** ao executar um **`exit()`** ou o **retorno** do **main**.\
|
||||
Se você puder **modificar** o **endereço** de qualquer dessas **funções** para apontar para um shellcode, por exemplo, você **ganhará controle** do **processo**, mas isso atualmente é mais complicado.\
|
||||
Se você puder **modificar** o **endereço** de qualquer uma dessas **funções** para apontar para um shellcode, por exemplo, você **ganhará controle** do **processo**, mas isso atualmente é mais complicado.\
|
||||
Atualmente os **endereços das funções** a serem executadas estão **ocultos** por várias estruturas e finalmente o endereço para o qual apontam não são os endereços das funções, mas são **criptografados com XOR** e deslocamentos com uma **chave aleatória**. Portanto, atualmente esse vetor de ataque não é muito útil pelo menos em x86 e x64\_86.\
|
||||
A **função de criptografia** é **`PTR_MANGLE`**. **Outras arquiteturas** como m68k, mips32, mips64, aarch64, arm, hppa... **não implementam a função de criptografia** porque ela **retorna o mesmo** que recebeu como entrada. Portanto, essas arquiteturas seriam atacáveis por esse vetor.
|
||||
|
||||
Você pode encontrar uma explicação detalhada de como isso funciona em [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
|
||||
|
||||
Como explicado [**neste post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure), Se o programa sair usando `return` ou `exit()` ele executará `__run_exit_handlers()` que chamará os destruidores registrados.
|
||||
|
||||
{% hint style="danger" %}
|
||||
Se o programa sair via **função `_exit()`**, ele chamará a **chamada de sistema `exit`** e os manipuladores de saída não serão executados. Portanto, para confirmar se `__run_exit_handlers()` é executado, você pode definir um breakpoint nele.
|
||||
{% endhint %}
|
||||
|
||||
O código importante é ([fonte](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
|
||||
}
|
||||
```
|
||||
Observe como `map -> l_addr + fini_array -> d_un.d_ptr` é usado para **calcular** a posição do **array de funções a serem chamadas**.
|
||||
|
||||
Existem **algumas opções**:
|
||||
|
||||
* Sobrescrever o valor de `map->l_addr` para fazê-lo apontar para um **`fini_array` falso** com instruções para executar código arbitrário
|
||||
* Sobrescrever as entradas `l_info[DT_FINI_ARRAY]` e `l_info[DT_FINI_ARRAYSZ]` (que são mais ou menos consecutivas na memória), para fazer com que elas **apontem para uma estrutura `Elf64_Dyn` forjada** que fará novamente **`array` apontar para uma zona de memória** controlada pelo atacante. 
|
||||
* [**Este relatório**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) sobrescreve `l_info[DT_FINI_ARRAY]` com o endereço de uma memória controlada em `.bss` contendo um `fini_array` falso. Este array falso contém **primeiramente um** [**endereço de one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) que será executado e em seguida a **diferença** entre o endereço deste **array falso** e o v**alor de `map->l_addr`** para que `*array` aponte para o array falso.
|
||||
* De acordo com a postagem principal desta técnica e [**este relatório**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so deixa um ponteiro na pilha que aponta para o `link_map` binário em ld.so. Com uma escrita arbitrária é possível sobrescrevê-lo e fazê-lo apontar para um `fini_array` falso controlado pelo atacante com o endereço de um [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md), por exemplo.
|
||||
|
||||
Após o código anterior, você pode encontrar outra seção interessante com o código:
|
||||
```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));
|
||||
}
|
||||
```
|
||||
Neste caso, seria possível sobrescrever o valor de `map->l_info[DT_FINI]` apontando para uma estrutura `ElfW(Dyn)` forjada. Encontre [**mais informações aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link\_map-structure).
|
||||
|
||||
## Sobrescrita de TLS-Storage dtor\_list em **`__run_exit_handlers`**
|
||||
|
||||
Conforme [**explicado aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite), se um programa sai via `return` ou `exit()`, ele executará **`__run_exit_handlers()`** que chamará qualquer função de destruição registrada.
|
||||
|
||||
Código de `_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 ();
|
||||
```
|
||||
Código de **`__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);
|
||||
[...]
|
||||
}
|
||||
}
|
||||
```
|
||||
Para cada função registrada em **`tls_dtor_list`**, ele irá desfazer a mangled do ponteiro de **`cur->func`** e chamá-lo com o argumento **`cur->obj`**.
|
||||
|
||||
Usando a função **`tls`** deste [**fork do GEF**](https://github.com/bata24/gef), é possível ver que na verdade a **`dtor_list`** está muito **próxima** do **canário de pilha** e do **cookie PTR\_MANGLE**. Portanto, com um estouro nela, seria possível **sobrescrever** o **cookie** e o **canário de pilha**.\
|
||||
Sobrescrevendo o cookie PTR\_MANGLE, seria possível **burlar a função `PTR_DEMANLE`** definindo-o como 0x00, o que significa que o **`xor`** usado para obter o endereço real é apenas o endereço configurado. Em seguida, escrevendo na **`dtor_list`**, é possível **encadear várias funções** com o endereço da função e seu **argumento**.
|
||||
|
||||
Por fim, observe que o ponteiro armazenado não apenas será xorado com o cookie, mas também rotacionado 17 bits:
|
||||
```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
|
||||
```
|
||||
Portanto, você precisa levar isso em consideração antes de adicionar um novo endereço.
|
||||
|
||||
Encontre um exemplo no [**post original**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite).
|
||||
|
||||
## Outros ponteiros corrompidos em **`__run_exit_handlers`**
|
||||
|
||||
Essa técnica é [**explicada aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor\_list-overwrite) e depende novamente do programa **sair chamando `return` ou `exit()`** para que **`__run_exit_handlers()`** seja chamado.
|
||||
|
||||
Vamos verificar mais código desta função:
|
||||
```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);
|
||||
```
|
||||
A variável `f` aponta para a estrutura **`initial`** e dependendo do valor de `f->flavor`, diferentes funções serão chamadas.\
|
||||
Dependendo do valor, o endereço da função a ser chamada estará em um local diferente, mas sempre será **desemanglado**.
|
||||
|
||||
Além disso, nas opções **`ef_on`** e **`ef_cxa`**, também é possível controlar um **argumento**.
|
||||
|
||||
É possível verificar a estrutura **`initial`** em uma sessão de depuração com o GEF executando **`gef> p initial`**.
|
||||
|
||||
Para abusar disso, você precisa vazar ou apagar o **cookie `PTR_MANGLE`** e então sobrescrever uma entrada `cxa` em initial com `system('/bin/sh')`.\
|
||||
Você pode encontrar um exemplo disso no [**post original do blog sobre a técnica**](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>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
||||
Outras maneiras de apoiar o HackTricks:
|
||||
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
|
||||
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
|
||||
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
||||
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
Loading…
Reference in a new issue