Steganography Techniques - LSB Steganography in PNG Files

Onedaysec
5 min read
0 views
docx image 1770018791268 0 4621063e19

0x00 Preface

The previous article analyzed the PNG file format and introduced how to insert payloads into PNG files in the auxiliary data chunk tEXt format without affecting normal browsing. This time, we will introduce a technique for hiding payloads under the image data chunk IDAT—LSB steganography

0x00 Preface — technical illustration 1

Image sourced from http://datagenetics.com/blog/march12012/index.html

0x01 Introduction

---

IDAT Data Chunk

  • Stores image pixel data
  • Can contain multiple consecutive image data chunks in the data stream
  • Compressed using a derivative algorithm of LZ77
  • Can be decompressed with zlib

Python implementation code for zlib decompression:

#! /usr/bin/env python
import zlib
import binascii
IDAT = "789C5D91011280400802BF04FFFF5C75294B5537738A21A27D1E49CFD17DB3937A92E7E603880A6D485100901FB0410153350DE83112EA2D51C54CE2E585B15A2FC78E8872F51C6FC1881882F93D372DEF78E665B0C36C529622A0A45588138833A170A2071DDCD18219DB8C0D465D8B6989719645ED9C11C36AE3ABDAEFCFC0ACF023E77C17C7897667".decode('hex')
result = binascii.hexlify(zlib.decompress(IDAT))
print result

Cited from http://drops.wooyun.org/tips/4862

LSB Steganography

  • LSB stands for least significant bit
  • In PNG files, image pixels are typically composed of three primary colors: red, green, and blue (RGB). Each color occupies 8 bits, with a value range from 0x00 to 0xFF, meaning there are 256 possible values per color. This results in a total of 256^3 colors, which is 16,777,216 colors.
  • The human eye can distinguish approximately 10 million different colors.
  • This means the human eye cannot distinguish the remaining approximately 6,777,216 colors.
  • LSB steganography involves modifying the least significant bit (LSB) of the RGB color components, and the human eye does not notice the change before and after.
  • Each pixel can carry 3 bits of information.

0x02 Python Implementation

---

Notable projects on GitHub for learning about LSB steganography:

https://github.com/RobinDavid/LSB-Steganography

https://github.com/cyberinc/cloacked-pixel

Testing cloacked-pixel below

Test image:

0x02 Python Implementation — technical illustration 2

Source file download URL:

http://www.easyicon.net/language.en/1119182-Enderman_Png_icon.html

1. Encryption

Run:

python lsb.py hide big.png 1.txt 123456

Parameter description:

hide: indicates encryption mode

big.png: PNG image to be encrypted

1.txt: stores the payload

123456: encryption password

After running, generate the image big.png-stego.png

As shown in the figure

1. Encryption — technical illustration 3

Analyze the format of the encrypted image big.png-stego.png using the check.cpp introduced in the previous article

Download link:

An open-source project

Comparison before and after encryption as shown in the figure

1. Encryption — technical illustration 4

cloacked-pixel deletes other data chunks during encryption, retaining only the key IDAT data chunks

Using HexEditorNeo to view the encrypted image also confirms our judgment, as shown in the figure

1. Encryption — technical illustration 5

Note:

Of course, analysis can also be performed by reading the source code

2. Decryption

Run:

python lsb.py extract big.png-stego.png 3.txt 123456

Parameter description:

extract: indicates decryption mode

big.png-stego.png: PNG image to be decrypted

3.txt: stores the exported payload

123456: decryption password

As shown, successfully decrypted to obtain payload

2. Decryption — technical illustration 6

3. Analysis

Run:

python lsb.py analyse big.png-stego.png

Parameter description:

analyse: indicates analysis mode

big.png-stego.png: PNG image to be analyzed

After running, the image will be analyzed, divided into blocks, and the least significant bits of each block will be marked

As shown in the figure

3. Analysis — technical illustration 7

This is a comparative analysis diagram before and after encryption

3. Analysis — technical illustration 8

The difference in the images is almost indistinguishable to the naked eye, because the shorter the payload, the smaller the difference in the analysis diagram. Here we can use software to assist in the analysis

Tool name:Stegsolve

Download address:

http://www.caesum.com/handbook/Stegsolve.jar

Environment setup:

Install JDK and configure the Java environment

Open a.png with Stegsolve, select Analyse-Image Combiner, and choose b.png

Perform XOR comparison, as shown in the figure, subtle differences are detected

3. Analysis — technical illustration 9

0x03 C++ Implementation

---

Grant Curell shared a method implemented through C++, which is worth learning, so here we introduce and test it.

Article address:

http://www.codeproject.com/Articles/581298/PNG-Image-Steganography-with-libpng

Author:

Grant Curell

Code download link:

http://www.codeproject.com/KB/security/581298/PNG_stego.zip

Test environment:

Win7 X64

vs2012

1. Direct compilation will report an error

The zlib project can be compiled successfully directly

Compiling the libpng project, the error is as follows:

fatal error C1083: Cannot open include file: 'zlib.h': No such file or directory

Solution:

Need to add include directory to the project

Right-click - Property - VC++ Directories

Select Include Directories

As shown in the figure

1. Direct compilation will report an error — technical illustration 10

Add zlib-1.2.3, input:

..\..\..\zlib-1.2.3;

As shown in the figure

1. Direct compilation will report an error — technical illustration 11

Compile again, error reported as follows:

fatal error LNK1181: cannot open input file 'zlib.lib'

Solution:

Need to add lib directory to the project

Select Library Directories

Add zlib.lib, input:

..\..\..\LIB Debug;

As shown, compilation succeeded

1. Direct compilation will report an error — technical illustration 12

Tips:

In Include Directories and Library Directories, absolute paths can also be directly specified (e.g., C:\test\cloacked-pixel-master\PNG_stego\zlib-1.2.3). This example uses ..\ to represent relative paths

When compiling the project PNG_encode_decode, the same compilation error occurs

Solution:

Add zlib-1.2.3 and libpng-1.2.37-src under Include Directories, input:

../zlib-1.2.3;../libpng-1.2.37-src;

Add libpng.lib under Library Directories, input:

..\LIB Debug;

As shown, final compilation succeeded

1. Direct compilation will report an error — technical illustration 13

Note:

Three project components have sequential dependencies, so the compilation order is zlib-libpng-PNG_encode_decode

2. Encryption Testing

File to be encrypted: big.png

Payload file: 1.txt

Output encrypted file: bigen.png

Modify main.cpp in project PNG_encode_decode as follows:

#include "PNG_file.h"
void main() {

PNG_file link = PNG_file("big.png");
link.encode("1.txt");
link.outputPNG("bigen.png");
}

After execution, bigen.png is generated as shown

2. Encryption Testing — technical illustration 14

Comparing files before and after encryption shows size differences as illustrated

2. Encryption Testing — technical illustration 15

In principle, LSB steganography does not change file size; investigate the cause

Using check.cpp to parse the data chunk directory, several additional tTXt segments were found after encryption

As shown in the figure

2. Encryption Testing — technical illustration 16

Using HexEditorNeo to view the details of the encrypted image, as shown in the figure

2. Encryption Testing — technical illustration 17

The encrypted image contains some information from the original image, resulting in different image sizes

3. Remove redundant information

Method a:

Use HexEditorNeo to directly delete redundant information

Method b:

Use compress.cpp

Download link:

An open-source project

Generate encrypted image bigensimple.png with redundant tTXt chunks removed, as shown

3. Remove redundant information — technical illustration 18

bigensimple.png has the same size as the original image, as shown

3. Remove redundant information — technical illustration 19

4. Decryption Test

Modify main.cpp in project PNG_encode_decode as follows:

#include "PNG_file.h"
void main() {

PNG_file link = PNG_file("bigensimple.png");
link.decode("2.txt");
}

After running, 2.txt is generated, obtaining the stored encrypted payload

(5) Analysis

For LSB steganography, Stegsolve can be used for auxiliary analysis

After opening the encrypted image, select Analyse-DataExtract

Select the 0th bit of Reg, Green, and Blue in Bit Planes

Select LSB First in Bit Order

Select RGB in Bit Plane Order

The encrypted form of the payload can be seen, as shown in the figure

(5) Analysis — technical illustration 20

Note:

Of course, the encrypted data of the image can be found by reading the program source code. This example only provides some reference ideas for image analysis.

0x04 Summary

---

This article introduces how to implement LSB steganography for PNG files using Python and C++ respectively. By following the analysis ideas in the article, common LSB steganography data can also be extracted and analyzed.

Note:

The modified PNG_stego project has been uploaded to GitHub:

An open-source project

More learning materials:

https://github.com/fgrimme/Matroschka

https://waronpants.net/article/png-steganography/

https://waronpants.net/pngsteg/trunk/steg.c

http://www1.chapman.edu/~nabav100/ImgStegano/

http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3.1

https://www.w3.org/TR/PNG/

Related Questions & Answers

Why might a PNG file size change after LSB steganography, and how can you avoid that?

Some implementations, like Grant Curell's C++ code, may add extra tEXt chunks or retain original metadata, increasing file size. To avoid this, you can use a tool like `compress.cpp` from the [modified PNG_stego project](/news/steganography-techniques-lsb-steganography-in-png-files) to remove redundant chunks, restoring the original size. Pure LSB steganography on the IDAT chunk itself does not inherently change the file size when properly implemented.

What tool can visually analyze LSB steganography in PNG images, and how does it reveal hidden data?

Stegsolve is a Java-based tool for steganalysis. After opening an encrypted image, you can go to Analyse → Data Extract, select the 0th bit of each RGB plane in Bit Planes, and choose LSB First with RGB order. This reveals the encrypted payload's bits visually. Stegsolve also allows XOR comparison between two images to highlight subtle differences caused by LSB embedding.

How can you decrypt or extract hidden data from a PNG file that uses LSB steganography with a password?

To decrypt, use a tool like [cloacked-pixel](https://github.com/cyberinc/cloacked-pixel) with the command `python lsb.py extract big.png-stego.png output.txt password`. This reverses the embedding process by reading the least significant bits of the pixel data, applying the password-based decryption, and writing the hidden payload to a file. The same password used during encryption is required.

What is the role of the IDAT data chunk in PNG LSB steganography, and how is it compressed?

The IDAT data chunk stores the actual pixel data of the PNG image. It uses a compression algorithm based on LZ77 (deflate), and the compressed data can be decompressed using zlib. In LSB steganography, the payload is hidden by altering the least significant bits of the decompressed pixel data before re-compressing it into the IDAT chunk. Tools like [cloacked-pixel](https://github.com/cyberinc/cloacked-pixel) replace all other chunks with only the essential IDAT chunk.

How does LSB steganography hide data in PNG images without being noticeable to the human eye?

LSB steganography modifies the least significant bit of each RGB color component in a PNG pixel. Since each color component ranges from 0 to 255 and the human eye can only distinguish about 10 million colors, changing the least significant bit (which alters the color by at most 1) is imperceptible. Each pixel can carry 3 bits of data (one per color channel). This technique is commonly used in tools like [cloacked-pixel](https://github.com/cyberinc/cloacked-pixel).

Continue Reading