Basic Stack Binary Exploitation Methodology
Last updated
Last updated
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Antes de começar a explorar qualquer coisa, é interessante entender parte da estrutura de um binário ELF:
Com tantas técnicas, é bom ter um esquema de quando cada técnica será útil. Note que as mesmas proteções afetarão diferentes técnicas. Você pode encontrar maneiras de contornar as proteções em cada seção de proteção, mas não nesta metodologia.
Existem diferentes maneiras de controlar o fluxo de um programa:
Estouros de Pilha sobrescrevendo o ponteiro de retorno da pilha ou o EBP -> ESP -> EIP.
Pode ser necessário abusar de um Estouro de Inteiro para causar o estouro
Ou via Gravação Arbitrária + Escrever Onde para Executar
Strings de Formato: Abusar do printf
para escrever conteúdo arbitrário em endereços arbitrários.
Indexação de Arrays: Abusar de uma indexação mal projetada para poder controlar alguns arrays e obter uma gravação arbitrária.
Pode ser necessário abusar de um Estouro de Inteiro para causar o estouro
bof para WWW via ROP: Abusar de um estouro de buffer para construir um ROP e ser capaz de obter um WWW.
Você pode encontrar as técnicas de Escrever Onde para Executar em:
Algo a se ter em conta é que geralmente apenas uma exploração de uma vulnerabilidade pode não ser suficiente para executar um exploit com sucesso, especialmente algumas proteções precisam ser contornadas. Portanto, é interessante discutir algumas opções para tornar uma única vulnerabilidade explorável várias vezes na mesma execução do binário:
Escrever em uma cadeia ROP o endereço da função main
ou para o endereço onde a vulnerabilidade está ocorrendo.
Controlando uma cadeia ROP adequada, você pode ser capaz de realizar todas as ações nessa cadeia
Escrever no endereço exit
em GOT (ou em qualquer outra função usada pelo binário antes de terminar) o endereço para voltar à vulnerabilidade
Como explicado em .fini_array, armazene 2 funções aqui, uma para chamar a vulnerabilidade novamente e outra para chamar**__libc_csu_fini
** que chamará novamente a função de .fini_array
.
ret2win: Existe uma função no código que você precisa chamar (talvez com alguns parâmetros específicos) para obter a flag.
Em um bof com PIE, você precisará contorná-lo
Em um bof com canary, você precisará contorná-lo
Se você precisar definir vários parâmetros para chamar corretamente a função ret2win, você pode usar:
Uma cadeia ROP se houver gadgets suficientes para preparar todos os parâmetros
SROP (caso possa chamar essa chamada de sistema) para controlar muitos registradores
Através de um Escrever Onde para Executar você poderia abusar de outras vulnerabilidades (não bof) para chamar a função win
.
Redirecionamento de Ponteiros: Caso a pilha contenha ponteiros para uma função que será chamada ou para uma string que será usada por uma função interessante (system ou printf), é possível sobrescrever esse endereço.
Variáveis não inicializadas: Você nunca sabe.
(Stack) Shellcode: Isso é útil para armazenar um shellcode na pilha antes ou depois de sobrescrever o ponteiro de retorno e então pular para ele para executá-lo:
De qualquer forma, se houver um canary, em um bof regular você precisará contorná-lo (vazar)
Com ASLR, você precisará de técnicas como ret2esp/ret2reg para pular para ele
Isso misturará shellcode com uma cadeia ROP.
Ret2syscall: Útil para chamar execve
para executar comandos arbitrários. Você precisa ser capaz de encontrar os gadgets para chamar a syscall específica com os parâmetros.
SROP pode ser útil para preparar o ret2execve
Ret2lib: Útil para chamar uma função de uma biblioteca (geralmente de libc
) como system
com alguns argumentos preparados (por exemplo, '/bin/sh'
). Você precisa que o binário carregue a biblioteca com a função que deseja chamar (geralmente libc).
Se compilado estaticamente e sem PIE, o endereço de system
e /bin/sh
não vão mudar, então é possível usá-los estaticamente.
Sem ASLR e conhecendo a versão da libc carregada, o endereço de system
e /bin/sh
não vão mudar, então é possível usá-los estaticamente.
Use ret2dlresolve
para resolver o endereço de system
e chamá-lo
Burlar ASLR e calcular o endereço de system
e '/bin/sh'
na memória.
Burlar PIE
Encontrar a versão da libc usada (vazar alguns endereços de função)
Verificar os cenários anteriores com ASLR para continuar.
Stack Pivoting / EBP2Ret / EBP Chaining: Controlar o ESP para controlar o RET através do EBP armazenado na pilha.
Útil para estouros de pilha off-by-one
Útil como uma maneira alternativa de controlar o EIP enquanto abusa do EIP para construir a carga na memória e então pular para ela via EBP
Redirecionamento de Ponteiros: Caso a pilha contenha ponteiros para uma função que será chamada ou para uma string que será usada por uma função interessante (system ou printf), é possível sobrescrever esse endereço.
Variáveis não inicializadas: Você nunca sabe