A Guide to Cracking Steganography: Least Significant Bits and Basic Tools

least significant bit

When it comes to cracking steganography – like other capture-the-flag challenges, there's a particular methodology you can follow. While there are a myriad of online decryption and encryption tools, the goal of this guide is to show you how to analyse files and learn how steganography works.

In this guide, we're going to examine file compressions and least significant bits – the tools and the methodology you can follow.

1. File and Strings 

First and foremost, when you get an image, the first step is to boot up your terminal and run 'file' in the command-line to examine the file. Given it's a png or a jpg image – take particular note of the size of the image and the colour depth of image – is it 8-bit or 16-bit?

$ file photo.png
For a passive overview of possible messages stored within the image, run the 'strings' command and see if there are any hidden text of interest. Sometimes, useful sentences can be configured within the file – I once had a challenge where the words 'IV: Prince' and 'Rijndael' were stored within a jpg file. For those familiar with cryptography, you'll recognise that IV stands for initialisation vector and Rijndael was one of the creators of AES – a cipher block algorithm commonly used.
$ strings photo.png
By running these two commands, you've engaged in passive reconnaissance and often you won't have found anything interesting. However, it's good practice just to collect as much information as you can about the file in case anything stands out further down the line.

2. Binwalk

Binwalk is a tool used for analysing, reverse engineering and examining file composition. Usage is extremely simple:
$ binwalk photo.png

0             0x0             PNG image data, 
10541         0x292D          Zip archive data
Immediately, the tool will break down the composition of the file. As you can see above, the file contains two compartments – the png image data and also a zip file. Often in these instances, an extraction of the zip file will give you the flag, however in other cases, it's a pandora's box with encapsulation within encapsulation (files within files) and you'll have to follow the method a few times to extract the final.

To extract the hidden files, run the command with the flag '-e' to extract the unknown files:
$ binwalk -e photo.png
This will automatically unzip the foreign file into your current directory. At this point, 'cat' the file to print the contents, examine the type of file that's been extracted using 'file' and 'strings' and repeat the process again.

Tip: Compare the file before and after extraction by looking at the hexdump by running the command below:
$ xxd <your_decompressed_file> | less

3. Pngcheck

Pngcheck is a great tool to check for any image corruption or sections that seem out of place. It's important for you to have a basic understanding of the make-up of a png file. Typically, png files are created in 'chunks' of data which are non-critical. These classes of 'chunks' have particular names and functions relating to that particular image.

To run a pngcheck in verbose mode, do the following:
$ pngcheck -v photo.png
Examine the chunks that are presented. In particular, take note of the following chunks:
  • tEXT: Stores text that's presented in ISO/IEC 8859-1
  • zTXt: Compressed text
  • iTXt: UTF-8 text that can be compressed
  • pHYs: Gives information relating to the intended pixel size of the image

4. Least Significant Bit (Binary & RGB)

Images are made up of pixels. Each pixel contains an identity, commonly known as RGB. As computers represent data in the form of binary (zeros and ones), the RGB code can also be expressed in the same way. Each value for RGB is a number from 0 to 255. Knowing that a byte (made up of 8-bits) can store up to the number 255 in binary – the RGB code of a pixel is stored in the binary format as follows for the colour pale yellow:

Pale Yellow

RGB: 200, 180, 120
Hexadecimal RGB: (C8, B4, 78)
Binary: 11001000, 10110100, 01111000

The principle of least significant bit is also known as the right-most-bit due to the fact that the last bit value of the byte, if flipped / changed, will not affect the image composition to the naked eye. This means, if you aggregate all these changed bits together and converted binary to ascii — you will find your hidden message.

A simple way to convert each pixel into RGB is to use a Python module called PIL – designed for image processing. The following piece of code converts each pixel in an image to its respective binary code (i.e. one byte – or one binary number per R, G and B) and then prints out only the last bit of each (the least significant bit).

from PIL import Image

im = Image.open("photo.png")
pix = im.load()
for i in range(width):
    for j in range(height):
        print(bin(pix[j,i][0])[-1] + bin(pix[j,i][1])[-1] + bin(pix[j,i][2])[-1], end='')

Following from the code above, instead of printing out the binary, you can save it in a variable and then convert it into ascii to retrieve the message.

If you have any questions, issues, shoot me an email or let me know below.


  1. in the last python bit width and height should be im.width and im.height


Post a Comment

Popular posts from this blog

Forensic Analysis of AnyDesk Logs

Successful 4624 Anonymous Logons to Windows Server from External IPs?

How to Reverse Engineer and Patch an iOS Application for Beginners: Part I