Como ocultar arquivos ou dados em uma imagem JPEG
Os cavalos de Tróia têm sido uma das maneiras mais eficazes de obter cargas úteis no dispositivo de um alvo. Se você não sabe o que é um cavalo de Tróia, a ideia por trás disso é ocultar a carga útil atrás do que o alvo considera legítimo.
Recentemente descobri coisas legais sobre imagens JPEG e imaginei que poderíamos anexar informações adicionais ou armazenar dados dentro do JPEG, sem distorcer a imagem.
Neste tutorial, aprenderemos como usar Python como linguagem de programação, como podemos ocultar dados em imagens JPEG e também como você pode ler os dados armazenados na imagem.
Isenção de responsabilidade: este tutorial não tem nada a ver com a criação de cavalos de Tróia.
O que é FFD9;
FFD9 ou x0FFx0D9
É um dos muitos marcadores em imagens JPEG que marca o final da imagem (EOI). Outros marcadores incluem FFD8
o início da imagem, FFFE
um comentário e muito mais. você pode procurar todos os marcadores disponíveis na página da Wikipedia .
Estaremos aproveitando o marcador final, ou seja, FFD9, e adicionaremos o que quisermos por trás dele, qualquer coisa, desde outras imagens, vídeos, áudios, executáveis ou qualquer dado que você possa imaginar.
Primeiro, vamos tentar adicionar um hello world a uma imagem. Usarei esta imagem de exemplo (prometo que não está bugada 😀, você pode confiar em mim 🙂) para esta demonstração. É seguro fazer download.
Crie um novo arquivo Python.
def inject(image, data):
image_file = open(image, 'ab')
image_file.write(data)
image_file.close()
Aqui, temos uma função simples que leva a imagem e os dados que queremos anexar ao JPEG. Coisas muito diretas; abrimos o ab
modo Imagem em, anexando o modo bytes.
Adicionando olá mundo;
Podemos chamar nossa função e adicionar:
inject('demo.jpg', b'Hello world')
É isso! Olá mundo agora em nossa imagem, e se você reabrir sua imagem, nenhum dano foi causado a ela. Além disso, estamos adicionando um byte sequence
em vez de uma string.
É bom saber : em Python, quando você vê uma string precedida por a b , como b'Hello world' , significa que a string é representada como uma sequência de bytes em vez de uma sequência de caracteres.
Você pode estar pensando: “É simples assim”! Bem, sim! Escrever os dados é muito fácil, mas faremos um pouco mais para tirar nossos dados da imagem.
Lendo nossos dados armazenados;
Em outro lugar, para escrever uma função que retornará nossos dados armazenados, é aqui que FFD9
entraremos em ação.
Leremos a imagem para localizar a posição de
FFD9
Em seguida, busque esse índice (coloque o cursor no local, para que a leitura da imagem comece a partir daí).
Aqui está como será a função:
def get_end_flag(image):
image_file = open(image, 'rb')
content = image_file.read()
end_flag_index = content.indexof(bytes.fromhex('FFD9'))
end_flag_offset = end_flag_index+2
image_file.close()
return end_flag_offset
A razão pela qual estamos adicionando 2 (dois) é para pular o marcador para ler a próxima seção dos dados. Nesse caso, adicionar 2 end_flag_index
posicionaria nosso ponteiro logo após o FFD9
marcador, pronto para processar a próxima parte dos dados.
Nossa função para ler os dados ficará assim:
def read_injected_data(image):
image_file = open(image, 'rb')
image_file.seek(get_end_flag(image))
data = image_file.read()
image_file.close()
return data
Yahoo! Terminamos o programa. Vamos começar lendo nosso Hello World que adicionamos inicialmente.
data = read_injected_data(image)
print(data)
Aí está: nosso Hello World e Image, ambos limpos e intactos.
Um Problema 🤨;
Temos um problema, veja bem: para adicionar mais dados a esta imagem, primeiro precisaremos nos livrar de tudo o que adicionamos inicialmente.
Podemos escrever uma função para fazer isso:
def clear_injected(image):
image_file = open(image, 'rb')
old_content = image_file.read()
new_content = old_content[:get_end_flag(image)]
with open(image, 'wb') as new_image:
new_image.write(new_content)
image.close()
Esta função basicamente reescreve o conteúdo original da imagem, ou seja, o conteúdo do início ao fim, e depois o reescreve no mesmo arquivo. Portanto, tudo após o sinalizador End Of Image (EOI) ser perdido.
Podemos testar nossa função novamente e tudo o que acrescentamos à imagem desaparece 🪄
clear_injected('image.jpg')
Opcionalmente, você pode chamar clear_injected
dentro da inject
função, para limpar qualquer coisa adicionada à imagem, antes de anexar qualquer outra coisa.
def inject(image, data):
clear_injected(image)
## rest of function
Injetando arquivos de mídia;
Como dito anteriormente, vamos ver como podemos injetar arquivos de mídia em nossa imagem. Como tudo o que escrevemos é uma sequência de bytes, podemos simplesmente ler qualquer arquivo no modo bytes e injetá-lo em nossa imagem.
Será algo parecido com isto:
with open('somevid.mp4', 'rb') as media:
inject('image.jpg', media.read())
Você pode ver que depois de anexar o vídeo à imagem, o tamanho aumentou:
Podemos facilmente buscar nosso vídeo usando:
data = read_injected_data('image.jpg')
with open('injected-video.mp4', 'wb') as file:
file.write(data)
Aí está, como você pode ocultar ou armazenar dados em imagens JPEG, sem sacrificar nada nos detalhes da imagem, a imagem funciona em qualquer lugar sem problemas. Este é um modo divino de esconder coisas no seu computador, sem nunca ser notado, o único problema é que, quanto maiores os dados que você está escondendo na imagem, maior será o tamanho.
Volte novamente, Paz ✌️!
Comentários
Postar um comentário