Entre os dias 18/02/2020 e 22/02/2020 eu participei pela primeira vez de um Capture The Flag no CTF promovido pela Tenable que conteve diversos desafios interessantes e foi uma experiência incrível. Meu time, 418 We’re a teapot, ficou em 60º lugar entre os 1589 times que participaram, nada mal para uma primeira vez! O desafio que irei resolver nesse post é o Numerological, segue a descrição do desafio:
Numerological
While working on his latest historical fact book, Don Beige came across a weird group of monks whose only communication with one another was to message the same picture back and forth.
Don thinks there must be something more going on and grabbed a sample.
Can you help him solve this case?
Enquanto trabalhava em seu último livro de fatos históricos, Don Beige se deparou com um grupo estranho de monges que só se comunicava entre eles enviando a mesma imagem.
Don acredita que tem algo a mais acontecendo e pegou uma amostra.
Pode ajudar ele a resolver esse caso?
Esse desafio valia 100 pontos (as pontuações dos desafios variavam entre 25 e 250).
Inicialmente eu verifiquei se o arquivo realmente era um PNG válido utilizando file shield.png
e estava tudo certo, depois eu verifiquei com binwalk
se continha algum outro arquivo embutido e lá estava ele:
$ binwalk shield.png
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PNG image, 1200 x 1464, 8-bit/color RGBA, non-interlaced
138 0x8A Zlib compressed data, best compression
492445 0x7839D PNG image, 885 x 400, 8-bit/color RGBA, non-interlaced
495277 0x78EAD TIFF image data, big-endian, offset of first image directory: 8
O binwalk
é um programa que identifica números mágicos (sequencia de bytes no começo do arquivo que identificam o formato do arquivo) ao longo do arquivo, ou seja, identifica possíveis arquivos dentro de outro arquivo.
Como podemos ver, o binwalk
acusou conter uma imagem PNG de 1200 x 1464 na posição 0x0, nenhuma surpresa até aqui, afinal, é a própria imagem que abre no visualizador de imagens. Após esse PNG, o binwalk
acusou conter uns dados comprimido em Zlib
, porém esse é um dado irrelevante, esses dados comprimidos são do próprio PNG (isso se não é um falso positivo), mas ainda assim vale a pena perder uns segundos extraindo e descomprimindo para ter certeza de que é irrelevante, para isso eu usei binwalk -e shield.png
que extrai e descomprime numa pasta _shield.png.extracted.
Após conferir esses 2 primeiros resultados, me restou o PNG de 885 x 400 e o TIFF, para o PNG eu abri o arquivo num editor de hexadecimal, observei os números mágicos do PNG (89 50 4E 47) e removi o conteúdo anterior aos números mágicos. Após extrair esse PNG, já observei que era um PNG válido e abria no visualizador de imagens. Não entendi absolutamente nada do que tinha nessa imagem.
Antes de seguir com esse PNG, também extrai o TIFF e não consegui abrir, não sei se realmente era algo ou se era um falso positivo.
Talvez você nesse ponto já tenha sacado o que é essa imagem e como chegar na flag, mas eu não, eu demorei horas para ter essa sacada. Eu me senti o Dr. House ao resolver o mistério em um momento completamente aleatório.
Antes de seguir para a solução desse desafio, vamos entender como que uma PNG pode conter outra imagem PNG e o visualizador de imagem funcionar normalmente exibindo apenas a primeira imagem.
Para entender isso, é preciso entender primeiro o básico das especificações de um arquivo PNG, não entrarei em grandes detalhes, mas caso queira saber detalhadamente, recomendo que leia as especificações do PNG.
Os primeiros oito bytes de um arquivo PNG são 89 50 4E 47 0D 0A 1A 0A
(números mágicos do PNG), são esses oito bytes que identifica um arquivo como PNG, inclusive, o comando file
não é um comando que simplesmente identifica pela extensão do arquivo, esse comando identifica pelos números mágicos, faça o teste, mude a extensão de um arquivo qualquer e veja que o resultado não se altera.
Após esses oito bytes que vai ter de fato as informações da imagem, organizadas em chunks (pedaços), que são 4 bytes para identificar o tamanho do chunk, 4 bytes para identificar o tipo do chunk, a quantidade de bytes definida anteriormente de conteúdo e 4 bytes para CRC (verificador de integridade do conteúdo). Tem um chunk especifico que é essencial para ter um arquivo PNG como o desse desafio, é o chunk “IEND”, esse é um chunk que sempre possui tamanho 0 e identifica o fim do PNG.
Ou seja, os visualizadores de imagem interpretam o arquivo PNG até o chunk “IEND”, ou seja, você pode incluir o que quiser depois do “IEND” que o PNG continua sendo visualizado normalmente.
Então, voltando ao desafio, eu encontrei essa imagem e não entendi o que isso significava, tentei manipular ambas as imagens no GIMP procurando por algo, mas não encontrei nada, tentei no Stegsolve também e nada. Tentei encontrar alguma pista em “cistercium mater nostra” e… pasmem, nada.
Depois de não ter nenhuma ideia nova, eu fui ver outros desafios, umas horas depois eu pensei “não é possível, devo ter deixado passar uma besteirinha só”, fui reler a descrição do desafio e pensei “será que monges é a pista que eu precisava?”. Parti para o nosso velho amigo, o Google, pesquisei “monks crypto” (criptografia de monges), comecei a achar alguns resultados e percebi que provavelmente estava no caminho certo.
Depois de alguns resultados eu encontrei um link na nossa outra velha amiga, a Wikipedia, a página era “The Ciphers of the Monks” (A cifra dos monges) e logo que eu abro eu dou de cara com símbolos semelhantes à imagem do desafio.
Tá ai a flag, basta fazer a conversão e ver como transformar esses números em texto contendo o formato “flag{…}” e foi isso que fui fazer, comecei a converter manualmente, pois achei (errado) que seria razoavelmente rápido e fácil, após o segundo símbolo eu percebi que demoraria muito mais do que gostaria e voltei ao velho amigo Google procurando um site que decifre a cifra dos monges.
Logo no primeiro resultado eu encontrei um conversor que não apenas agilizou o meu trabalho como me fez perceber que o código não podia ter a combinação de mais de 4 símbolos e o que eu fiz manualmente estava errado, acontece…
Os números que encontrei foram: 3637, 3639, 3734, 3265, 3639, 3666, 3266, 3461, 3734, 3461, 3631, 3538. Primeiro eu tentei converter de decimal para ASCII, o resultado foi uns caracteres aleatórios e inválidos, então, próxima tentativa foi tentar converter de hexadecimal para ASCII, o resultado foi “6769742e696f2f4a744a6158”, ai percebi que isso podia ser algo, tentei base64 e vi que não era, ai percebi que os caracteres variam entre 0 e f, então podia ser outro hexadecimal (além da imagem dentro de outra imagem, tem hexadecimal dentro de outro hexadecimal), converti de hexadecimal para ASCII novamente e encontrei um link “git.io/JtJaX” e, finalmente, encontrei a flag: “flag{th0s3_m0nk5_w3r3_cl3v3r}”.