BitsNBytes
3 minutes to read
We are given two PNG images called intercepted.png
and 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
Both images look the same visually:
But they are different because their MD5 hashes do not coincide:
$ md5sum intercepted.png
88e9b5b97e4a615f1aa26d11dbcdec0d intercepted.png
$ md5sum original.png
04e2562c19e680b6493b2a31d65c51e3 original.png
Hence, we might think that there is some kind of steganography being used on intercepted.png
. Since it is a PNG image, we can think of zsteg
, but it does not seem useful for the moment.
Since PNG images do not lose any data when compressed, we can operate both images at pixel level (for example, XOR or substraction). In order to get the differences between both files, we can use this short Python code (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()
If we wanted to use XOR, the method for that is bitwise_xor
instead of substract
. The resulting image (result.png
) seems to be completely black. But we can tweak the colors to see some strange pixels at the left:
If we zoom in, we can appreciate them better:
At this point, if we use zsteg
on the result.png
image, we will get a text message:
$ 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
And we get a string that seems to be encoded in Base64. And there’s the flag:
$ echo SFRCezFmX2FfdzAwZF9jaHVja19jMHVsZF9jaHVja193MDBkfQ== | base64 -d
HTB{1f_a_w00d_chuck_c0uld_chuck_w00d}