mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
99 lines
5.3 KiB
Markdown
99 lines
5.3 KiB
Markdown
# Stack Overflow
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## O que é um Stack Overflow
|
|
|
|
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.
|
|
|
|
O principal problema dessa sobrescrita é que o **ponteiro de instrução salvo (EIP/RIP)** e o **ponteiro 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**.
|
|
|
|
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.
|
|
|
|
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 podem 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);
|
|
}
|
|
```
|
|
### Encontrando os offsets de Stack Overflows
|
|
|
|
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**.
|
|
|
|
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 subsequência possível de comprimento _n_ aparece exatamente uma vez** como uma subsequência contígua.
|
|
|
|
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, em seguida, encontrar o offset dos bytes que acabaram sobrescrevendo-o.
|
|
|
|
É possível usar **pwntools** para isso:
|
|
```python
|
|
from pwn import *
|
|
|
|
# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
|
|
pattern = cyclic(1000)
|
|
|
|
# This is an example value that you'd have found in the EIP/IP register upon crash
|
|
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}")
|
|
```
|
|
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 Estouro de Pilha
|
|
|
|
Durante um estouro (supondo que o tamanho do estouro 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.
|
|
|
|
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
|
|
|
|
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/index.html) estaria desativado) para que, quando a função vulnerável retornar, a função oculta seja chamada:
|
|
|
|
{{#ref}}
|
|
ret2win/
|
|
{{#endref}}
|
|
|
|
### Shellcode na Pilha
|
|
|
|
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}}
|
|
|
|
### Técnicas ROP & Ret2...
|
|
|
|
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/
|
|
{{#endref}}
|
|
|
|
## Estouros de Heap
|
|
|
|
Um estouro não ocorrerá sempre na pilha, também pode ocorrer no **heap**, por exemplo:
|
|
|
|
{{#ref}}
|
|
../libc-heap/heap-overflow.md
|
|
{{#endref}}
|
|
|
|
## Tipos de proteções
|
|
|
|
Existem várias proteções tentando prevenir a exploração de vulnerabilidades, confira-as em:
|
|
|
|
{{#ref}}
|
|
../common-binary-protections-and-bypasses/
|
|
{{#endref}}
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|