Você está na página 1de 5

01/07/2022 14:53 Fundação Estudar

 
Voltar


Anterior
Próximo

Exercício 3 - Recover

Implemente um programa que recupere JPEGs de uma imagem forense, conforme a seguir.

$ ./recover card.raw

Background

Prevendo esse problema, passamos os últimos dias tirando fotos de pessoas que conhecemos,
todas as quais foram salvas em uma câmera digital como JPEG em um cartão de memória. (Ok, é
possível que, em vez disso, tenhamos passado os últimos dias no Facebook.) Infelizmente, de
alguma forma excluímos todos eles! Felizmente, no mundo da informática, "excluído" tende a não
significar "excluído", mas sim "esquecido". Mesmo que a câmera insista que o cartão agora está
em branco, temos certeza de que isso não é bem verdade. Na verdade, estamos torcendo (er,
esperando!) Que você possa escrever um programa que recupere as fotos para nós!

Mesmo que JPEGs sejam mais complicados do que BMPs, JPEGs têm “assinaturas”, padrões de
bytes que podem distingui-los de outros formatos de arquivo. Especificamente, os primeiros três
bytes de JPEGs são

0xff 0xd8 0xff

do primeiro para o terceiro byte, da esquerda para a direita. O quarto byte, entretanto, é 0xe0 ,
0xe1 , 0xe2 , 0xe3 , 0xe4 , 0xe5 , 0xe6 , 0xe7 , 0xe8 , 0xe9 , 0xea , 0xeb ,
0xec , 0xed , 0xee ou 0xef . Dito de outra forma, os primeiros quatro bits do quarto byte
são 1110 .

As probabilidades são de que, se você encontrar esse padrão de quatro bytes na mídia
conhecida por armazenar fotos (por exemplo, meu cartão de memória), eles demarcam o início de

https://ead.napratica.org.br/enrollments/7235444/courses/84414/course_contents/2169400 1/5
01/07/2022 14:53 Fundação Estudar

um JPEG. Para ser justo, você pode encontrar esses padrões em algum disco puramente por
acaso, então a recuperação de dados não é uma ciência exata.

Felizmente, as câmeras digitais tendem a armazenar fotos de forma contígua em cartões de


memória, sendo que cada foto é armazenada imediatamente após a foto anterior. Da mesma
forma, o início de um JPEG geralmente marca o final de outro. No entanto, as câmeras digitais
geralmente inicializam os cartões com um sistema de arquivos FAT cujo “tamanho de bloco” é de
512 bytes (B). A implicação é que essas câmeras só gravam nesses cartões em unidades de 512
B. Uma foto com 1 MB (ou seja, 1.048.576 B) ocupa 1048576 ÷ 512 = 2048 “blocos” em um cartão
de memória. Mas o mesmo acontece com uma foto que é, digamos, um byte menor (ou seja,
1.048.575 B)! O espaço desperdiçado em disco é chamado de "espaço livre". Os investigadores
forenses costumam olhar para a folga em busca de resquícios de dados suspeitos.

A implicação de todos esses detalhes é que você, o investigador, provavelmente pode escrever
um programa que itera sobre uma cópia do meu cartão de memória, procurando assinaturas de
JPEGs. Cada vez que encontrar uma assinatura, você pode abrir um novo arquivo para escrever e
começar a preencher esse arquivo com bytes do meu cartão de memória, fechando esse arquivo
apenas quando encontrar outra assinatura. Além disso, em vez de ler os bytes do meu cartão de
memória um de cada vez, você pode ler 512 deles por vez em um buffer para fins de eficiência.
Graças ao FAT, você pode confiar que as assinaturas de JPEGs serão "alinhadas em bloco". Ou
seja, você só precisa procurar essas assinaturas nos primeiros quatro bytes de um bloco.

Perceba, é claro, que JPEGs podem abranger blocos contíguos. Caso contrário, nenhum JPEG
pode ser maior que 512 B. Mas o último byte de um JPEG pode não cair no final de um bloco.
Lembre-se da possibilidade de espaço livre. Mas não se preocupe. Como este cartão de memória
era novo quando comecei a tirar fotos, é provável que tenha sido “zerado” (ou seja, preenchido
com 0s) pelo fabricante, caso em que qualquer espaço livre será preenchido com 0s. Tudo bem
se esses 0s finais acabarem nos JPEGs que você recuperar; eles ainda devem estar visíveis.

Agora, só tenho um cartão de memória, mas são muitos de vocês! E então fui em frente e criei
uma “imagem forense” do cartão, armazenando seu conteúdo, byte após byte, em um arquivo
chamado card.raw . Para que você não perca tempo repetindo milhões de zeros
desnecessariamente, imaginei apenas os primeiros megabytes do cartão de memória. Mas você
deve descobrir que a imagem contém 50 JPEGs.

Vamos começar

Veja como baixar o “código de distribuição” desse problema (ou seja, código inicial) em seu
próprio CS50 IDE. Faça login no CS50 IDE e, em uma janela de terminal, execute cada um dos
itens abaixo.

https://ead.napratica.org.br/enrollments/7235444/courses/84414/course_contents/2169400 2/5
01/07/2022 14:53 Fundação Estudar

Navegue até o diretório pset4 que já deve existir.


Execute wget http://cdn.cs50.net/2020/fall/psets/4/recover/recover.zip para baixar
um arquivo ZIP (compactado) com a distribuição desse problema.
Execute unzip recover.zip para descompactar esse arquivo.
Execute rm recover.zip seguido por yes ou y para excluir o arquivo ZIP.
Execute ls . Você deve ver um diretório chamado recover , que estava dentro desse arquivo
ZIP.
Execute cd recover para mudar para esse diretório.
Execute ls . Você deve ver a distribuição deste problema, incluindo card.raw e recover.c .

Especificação

Este vídeo irá te ajudar a entender o problema ;)

Atenção: para adicionar legendas ao vídeo clique no botão CC localizado no Player e selecione


a opção "Português (Brasil)".

CC50: PSet 4 - Recuperação

Implemente um programa denominado recover que recupera JPEGs de uma imagem forense.

Implemente seu programa em um arquivo chamado recover.c em um diretório chamado


recover .
Seu programa deve aceitar exatamente um argumento de linha de comando, o nome de
uma imagem forense da qual recuperar JPEGs.
Se seu programa não for executado com exatamente um argumento de linha de comando,
ele deve lembrar o usuário do uso correto e main deve retornar 1.

https://ead.napratica.org.br/enrollments/7235444/courses/84414/course_contents/2169400 3/5
01/07/2022 14:53 Fundação Estudar

Se a imagem forense não puder ser aberta para leitura, seu programa deve informar isso ao
usuário, e main deve retornar 1.
Cada um dos arquivos gerados deve ser nomeado como ###.jpg , onde ### é um número
decimal de três dígitos, começando com 000 para a primeira imagem e aumentando.
Seu programa, se usar malloc , não deve perder memória.

Uso

Seu programa deve se comportar de acordo com os exemplos abaixo.

$ ./recover

Uso: ./recuperar imagem

$ ./recover card.raw

Dicas
Lembre-se de que você pode abrir card.raw programaticamente com fopen , como abaixo, desde
que argv[1] exista.

FILE *file = fopen(argv[1], "r");


Quando executado, seu programa deve recuperar cada um dos JPEGs de card.raw ,
armazenando cada um como um arquivo separado em seu diretório de trabalho atual. Seu
programa deve numerar os arquivos de saída nomeando cada ###.jpg , onde ### é um número
decimal de três dígitos de 000 em diante. ( Vire amigo do sprintf .) Você não precisa tentar
recuperar os nomes originais dos JPEGs. Para verificar se os JPEGs que seu programa emitiu
estão corretos, basta clicar duas vezes e dar uma olhada! Se cada foto aparecer intacta, sua
operação provavelmente foi um sucesso!

As probabilidades são, no entanto, os JPEGs que o primeiro rascunho de seu código divulga não
estarão corretos. (Se você abri-los e não ver nada, provavelmente eles não estão corretos!)
Execute o comando abaixo para excluir todos os JPEGs em seu diretório de trabalho atual.

$ rm * .jpg

Se você preferir não ser solicitado a confirmar cada exclusão, execute o comando abaixo.

$ rm -f * .jpg
Apenas tome cuidado com a opção -f , pois ela “força” a exclusão sem avisar você.

https://ead.napratica.org.br/enrollments/7235444/courses/84414/course_contents/2169400 4/5
01/07/2022 14:53 Fundação Estudar

Se você gostaria de criar um novo tipo para armazenar um byte de dados, você pode fazer isso
por meio do comando abaixo, que define um novo tipo chamado BYTE como uint8_t (um tipo
definido em stdint.h , representando um inteiro sem sinal).

typedef uint8_t BYTE;

Lembre-se também de que você pode ler dados de um arquivo usando o fread , que lerá os
dados de um arquivo em um local da memória e retornará o número de itens lidos com êxito do
arquivo.

Testando
Execute o seguinte comando para avaliar a exatidão do seu código usando check50 . Mas
certifique-se de compilar e testar você mesmo!

check50 cs50/problems/2021/x/recover

Execute o seguinte para avaliar o estilo do seu código usando style50 .

style50 recover.c


Anterior
Próximo

Em caso de dúvida, envie email para relacionamento@estudar.org.br

Plataforma de ensino por  

https://ead.napratica.org.br/enrollments/7235444/courses/84414/course_contents/2169400 5/5

Você também pode gostar