BitsNBytes
3 minutos de lectura
Se nos proporcionan dos imágenes PNG intercepted.png y original.png:
$ file intercepted.png
intercepted.png: PNG image data, 775 x 550, 8-bit/color RGB, non-interlaced
$ file original.png
original.png: PNG image data, 775 x 550, 8-bit/color RGB, non-interlaced
Ambas imágenes parecen iguales visualmente:

Pero realmente son diferentes porque sus hashes MD5 no coinciden:
$ md5sum intercepted.png
88e9b5b97e4a615f1aa26d11dbcdec0d intercepted.png
$ md5sum original.png
04e2562c19e680b6493b2a31d65c51e3 original.png
Entonces, podemos deducir que hay algún tipo de esteganografía aplicada en intercepted.png. Como se trata de una imagen PNG, podríamos pensar en zsteg, pero no funciona de momento.
Como las imágenes PNG no pierden ningún dato al comprimirse, podemos operar las imágenes a nivel de píxel (por ejemplo, XOR o resta). Para obtener las diferencias entre ambos archivos, podemos usar este código simple en Python (solve.py):
#!/usr/bin/env python3
import numpy as np
from PIL import Image
def main():
intercepted = np.array(Image.open('intercepted.png'))
original = np.array(Image.open('original.png'))
result = np.subtract(intercepted, original)
Image.fromarray(result).save('result.png')
if __name__ == '__main__':
main()
Si quisiéramos usar XOR, el método habría sido bitwise_xor en lugar de subtract. La imagen resultante (result.png) parece completamente negra. Pero si ajustamos los colores, podremos ver unos píxeles raros a la izquierda:

Si hacemos zoom, lo veremos mejor:

En este punto, al usar zsteg en result.png veremos un texto:
$ python3 solve.py
$ zsteg -a result.png
b1,b,lsb,yx .. text: "SFRCezFmX2FfdzAwZF9jaHVja19jMHVsZF9jaHVja193MDBkfQ=="
b2,rgb,msb,yx .. file: Applesoft BASIC program data, first line number 128
b2,bgr,msb,yx .. file: Targa image data - RLE 128 x 8 x 32 +32768 +32 "�"
b4,b,lsb,yx .. file: PDP-11 UNIX/RT ldp
b4,bgr,lsb,yx .. file: dBase IV DBT, block length 4096, next free block index 256, next free block 0, next used block 0
b5,rgb,lsb,yx .. file: X11 SNF font data, MSB first
b6,rgb,lsb,yx .. file: GLS_BINARY_LSB_FIRST
b6,bgr,lsb,yx .. file: Targa image data - Map 65536 x 64 x 16
b7,b,lsb,yx .. file: TTComp archive data, binary, 1K dictionary
b7,rgb,msb,yx .. file: Matlab v4 mat-file (little endian) �, numeric, rows 512, columns 524288
b8,rgb,msb,yx .. file: Matlab v4 mat-file (little endian) , numeric, rows 32768, columns 2147483648
b1,rgb,msb,yx,prime .. file: Applesoft BASIC program data, first line number 146
b2,rgb,msb,yx,prime .. file: Applesoft BASIC program data, first line number 128
b4,b,lsb,yx,prime .. file: Targa image data - Map (17-4369) 273 x 4353 x 16 +4097 +256 - 1-bit alpha ""
b4,rgb,lsb,yx,prime .. file: Targa image data - Map 65536 x 65536 x 16 +1 +272 - 1-bit alpha
b5,rgb,lsb,yx,prime .. file: X11 SNF font data, MSB first
b6,rgb,lsb,yx,prime .. file: GLS_BINARY_LSB_FIRST
b6,bgr,lsb,yx,prime .. file: Targa image data - Map 65536 x 64 x 16 +256
b7,b,lsb,yx,prime .. file: TTComp archive data, binary, 1K dictionary
b7,rgb,msb,yx,prime .. file: Matlab v4 mat-file (little endian) �, numeric, rows 512, columns 524288, imaginary
b8,rgb,msb,yx,prime .. file: Matlab v4 mat-file (little endian) �, numeric, rows 32768, columns 2147483648
b1,b,lsb,Yx .. file: Matlab v4 mat-file (little endian) ���2r2Y�JZq�k9�J�Zr2Y�JZq�k� x���0jىz� )�(, numeric, rows 0, columns 0
b1,b,msb,Yx .. file: Matlab v4 mat-file (little endian) ٚQ�LNL��R�Z��֜R�ZNL��R�Z���]����
V��^ِ��, numeric, rows 0, columns 0
Y obtenemos una cadena de texto que parece codificada en Base64. Y aquí está la flag:
$ echo SFRCezFmX2FfdzAwZF9jaHVja19jMHVsZF9jaHVja193MDBkfQ== | base64 -d
HTB{1f_a_w00d_chuck_c0uld_chuck_w00d}