Ret2esp / Ret2reg
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)
Porque o ESP (Ponteiro de Pilha) sempre aponta para o topo da pilha, essa técnica envolve substituir o EIP (Ponteiro de Instrução) pelo endereço de uma instrução jmp esp
ou call esp
. Ao fazer isso, o shellcode é colocado imediatamente após o EIP sobrescrito. Quando a instrução ret
é executada, o ESP aponta para o próximo endereço, precisamente onde o shellcode está armazenado.
Se o Address Space Layout Randomization (ASLR) não estiver ativado no Windows ou Linux, é possível usar as instruções jmp esp
ou call esp
encontradas em bibliotecas compartilhadas. No entanto, com o ASLR ativo, pode ser necessário procurar essas instruções dentro do programa vulnerável em si (e pode ser necessário derrotar o PIE).
Além disso, ser capaz de colocar o shellcode após a corrupção do EIP, em vez de no meio da pilha, garante que quaisquer instruções push
ou pop
executadas durante a operação da função não interfiram no shellcode. Essa interferência poderia ocorrer se o shellcode fosse colocado no meio da pilha da função.
Se você estiver com espaço insuficiente para escrever após sobrescrever o RIP (talvez apenas alguns bytes), escreva um shellcode jmp
inicial como:
E escreva o shellcode no início da pilha.
Você pode encontrar um exemplo dessa técnica em https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp com um exploit final como:
Você pode ver outro exemplo dessa técnica em https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html. Há um estouro de buffer sem NX habilitado, é usado um gadget para reduzir o endereço de $esp
e então um jmp esp;
para pular para o shellcode:
Da mesma forma, se soubermos que uma função retorna o endereço onde o shellcode está armazenado, podemos aproveitar as instruções call eax
ou jmp eax
(conhecidas como técnica ret2eax), oferecendo outro método para executar nosso shellcode. Assim como eax, qualquer outro registro contendo um endereço interessante poderia ser usado (ret2reg).
Você pode encontrar alguns exemplos aqui:
strcpy
irá armazenar em eax
o endereço do buffer onde o shellcode foi armazenado e eax
não está sendo sobrescrito, então é possível usar um ret2eax
.
No ARM64, não existem instruções que permitem saltar para o registro SP. Pode ser possível encontrar um gadget que move sp para um registro e então salta para esse registro, mas na libc do meu kali não consegui encontrar nenhum gadget assim:
Os únicos que descobri mudariam o valor do registro onde sp foi copiado antes de pular para ele (então se tornaria inútil):
Se um registro tiver um endereço interessante, é possível pular para ele apenas encontrando a instrução adequada. Você poderia usar algo como:
No ARM64, é o x0
que armazena o valor de retorno de uma função, então poderia ser que x0 armazene o endereço de um buffer controlado pelo usuário com um shellcode para executar.
Código de exemplo:
Verificando a desmontagem da função, é possível ver que o endereço do buffer (vulnerável a bof e controlado pelo usuário) é armazenado em x0
antes de retornar do estouro de buffer:
Também é possível encontrar o gadget br x0
na função do_stuff
:
Vamos usar esse gadget para pular para ele porque o binário é compilado SEM PIE. Usando um padrão, é possível ver que o deslocamento do estouro de buffer é 80, então o exploit seria:
Se em vez de fgets
fosse usado algo como read
, teria sido possível contornar o PIE também apenas sobrescrevendo os últimos 2 bytes do endereço de retorno para retornar à instrução br x0;
sem precisar saber o endereço completo.
Com fgets
não funciona porque adiciona um byte nulo (0x00) no final.
NX: Se a pilha não for executável, isso não ajudará, pois precisamos colocar o shellcode na pilha e pular para executá-lo.
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)