intermediatecat/stego~2 min read
Deep LSB Steganography & Bitplane Extraction
Extract hidden messages and binary payloads from image color channels using custom Python PIL/OpenCV bit-shifting scripts.
// prerequisite reading
Least Significant Bit (LSB) Deep Dive
In 24-bit RGB images, each pixel consists of three 8-bit color channels: Red, Green, and Blue ($0$ to $255$).
An 8-bit binary value represents a channel:
$$\text{Pixel Red Channel} = 1101011\mathbf{0}2 \quad (214{10})$$
Changing only the least significant bit (bit 0) alters the integer value to $215_{10}$. This $1/256$-th variation in color intensity is completely imperceptible to human vision.
Bitplane Extraction Principles
An 8-bit image channel contains 8 distinct bitplanes (Bit 0 to Bit 7).
- Bitplane 7 (MSB): Contains high-level image structure and visual features.
- Bitplane 0 (LSB): Contains fine noise, where steganographic data is embedded.
Bitplane 7 (MSB) -> [ 1 ] 1 0 1 0 1 1 0 (Visual structural data)
...
Bitplane 0 (LSB) -> 1 1 0 1 0 1 1 [ 0 ] (Steganographic payload location)
Python LSB Extraction Script (PIL / NumPy)
When standard GUI tools like StegSolve do not extract custom bit orderings, write a Python script to iterate over pixel coordinates:
from PIL import Image
def extract_lsb(image_path, bit_index=0, channel=0):
img = Image.open(image_path).convert('RGB')
width, height = img.size
extracted_bits = []
# Iterate row by row (x, y) or column by column
for y in range(height):
for x in range(width):
pixel = img.getpixel((x, y))
channel_val = pixel[channel] # 0=Red, 1=Green, 2=Blue
# Extract specific bit using bitwise AND
bit = (channel_val >> bit_index) & 1
extracted_bits.append(str(bit))
# Convert bits array to characters
bit_string = "".join(extracted_bits)
bytes_list = [int(bit_string[i:i+8], 2) for i in range(0, len(bit_string), 8)]
return bytes(bytes_list)
# Usage example: Extract LSB of Red Channel
output_data = extract_lsb("stego_challenge.png", bit_index=0, channel=0)
with open("extracted_flag.bin", "wb") as f:
f.write(output_data)
print("Extraction complete! Check extracted_flag.bin")
Common Bitplane Combinations in CTFs
- RGB LSB Interleaved: Read Bit 0 of R, then G, then B sequentially for each pixel.
- Column-Major Order: Loop
for xinsidefor yvsfor yinsidefor x. - Inverted Bit Plane: Bits embedded in MSB (Bit 7) instead of LSB.
Automated CLI Suite
# zsteg checks all 256 permutations of channels and bitplanes automatically
zsteg -a stego_challenge.png
# Extract specific channel bitplane (e.g., b1,bgr,lsb,xy)
zsteg -E "b1,bgr,lsb,xy" stego_challenge.png > payload.bin