Athena Wiki
SteganographyImage Steganography

Pixel Manipulation Steganography

steganographyintermediate

Find flags hidden through pixel value manipulation, palette tricks, and color channel encoding.

steganographypixelspalettergbalphachannelpythonpil

Pixel Manipulation Steganography

Beyond LSB, flags can be hidden through direct pixel value manipulation — specific pixels storing ASCII values, color channel differences encoding data, or palette tricks hiding information in indexed color tables. These techniques require manual analysis with Python since automated tools like zsteg don't cover them.


Analysis Workflow

Mermaid diagram

Reading Pixel Data

from PIL import Image
import numpy as np

img = Image.open('suspicious.png')
print(f"Mode: {img.mode}")       # RGB, RGBA, P (palette), L (grayscale)
print(f"Size: {img.size}")       # (width, height)

pixels = np.array(img)
print(f"Shape: {pixels.shape}")  # (height, width, channels)

px = pixels[0, 0]  # top-left pixel
print(f"First pixel: {px}")      # [R, G, B] or [R, G, B, A]

Color Channel Techniques

Some challenges store the flag directly in pixel R values as printable ASCII:

from PIL import Image

img = Image.open('suspicious.png').convert('RGB')
width, height = img.size
flag = ''
for y in range(height):
    for x in range(width):
        r, g, b = img.getpixel((x, y))
        if 32 <= r <= 126:
            flag += chr(r)
print(flag)

Also try the Green and Blue channels independently.


Image Difference

Two nearly-identical images where the difference encodes the flag:

from PIL import Image
import numpy as np

img1 = np.array(Image.open('image1.png').convert('RGB'))
img2 = np.array(Image.open('image2.png').convert('RGB'))

diff = np.abs(img1.astype(int) - img2.astype(int))

# Amplify differences for visibility
amplified = np.clip(diff * 50, 0, 255).astype('uint8')
Image.fromarray(amplified).save('diff.png')

# Extract text from diff
for row in diff:
    for px in row:
        for v in px:
            if 32 <= v <= 126:
                print(chr(v), end='')

Generate All Bit Planes

from PIL import Image
import numpy as np

img = Image.open('suspicious.png').convert('RGB')
pixels = np.array(img)

for channel, name in enumerate(['R', 'G', 'B']):
    for bit in range(8):
        plane = ((pixels[:,:,channel] >> bit) & 1) * 255
        Image.fromarray(plane.astype('uint8')).save(f'{name}_bit{bit}.png')

print("Saved all 24 bit planes")

Open each *_bit0.png plane — if bit 0 (LSB) planes look like random static, data is likely hidden there.


Checklist

  • Check image mode: RGB, RGBA, P (palette)?
  • Extract alpha channel (RGBA): non-255 values → hidden data
  • Plot each bit plane: R/G/B × bits 0-7 → visual inspection
  • Check palette entries for ASCII-printable values
  • XOR R, G, B channels together
  • If two images provided: compute difference, amplify
  • Scan every pixel's RGB values for printable ASCII
  • Aperisolve automates many of these checks


Last updated on

On this page