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 substract
. 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}