kudos to my colleague Maros Plsik who gave me hint that i should analyze the bit planes
==============================================================
- check first row of pixels in the image, analyze bit planes
from PIL import Image
img_path = “WeirdTurkey.png”
im = Image.open(img_path).convert(“RGB”)
w, h = im.size
pixels = im.load()
r_bits, g_bits, b_bits = , ,
for x in range(w):
r, g, b = pixels[x, 0]
r_bits.append(format(r, “08b”))
g_bits.append(format(g, “08b”))
b_bits.append(format(b, “08b”))
print(f"Image size: {w}x{h}")
print(“First row binary values (per channel):\n”)
print(“Red channel bits:”)
for idx in range(8):
line = ‘’.join(bits[idx] for bits in r_bits)
print(f"Bit {7-idx}: {line}") # label in MSB order
print(“\nGreen channel bits:”)
for idx in range(8):
line = ‘’.join(bits[idx] for bits in g_bits)
print(f"Bit {7-idx}: {line}")
print(“\nBlue channel bits:”)
for idx in range(8):
line = ‘’.join(bits[idx] for bits in b_bits)
print(f"Bit {7-idx}: {line}")
===========
import csv
from PIL import Image
img_path = “WeirdTurkey.png”
csv_out = “first_row_bits.csv”
im = Image.open(img_path).convert(“RGB”)
w, h = im.size
pixels = im.load()
r_bits, g_bits, b_bits = , ,
for x in range(w):
r, g, b = pixels[x, 0]
r_bits.append(format(r, “08b”))
g_bits.append(format(g, “08b”))
b_bits.append(format(b, “08b”))
with open(csv_out, “w”, newline=“”) as f:
writer = csv.writer(f)
writer.writerow([“Channel”, “BitPlane”, “BitsAcrossPixels”])
for idx in range(8):
# Red
line = ‘’.join(bits[idx] for bits in r_bits)
writer.writerow([“R”, f"{7-idx}“, line])
# Green
line = ‘’.join(bits[idx] for bits in g_bits)
writer.writerow([“G”, f”{7-idx}“, line])
# Blue
line = ‘’.join(bits[idx] for bits in b_bits)
writer.writerow([“B”, f”{7-idx}“, line])
print(f”[+] Saved first row bit-planes to {csv_out}")
Hidden messages usually appear as non-random, high-entropy but structured binary data in a specific plane. I will not boring you with details
for task 3 : R=7 G=6 and 2 B=0
for task 4: R=2 G=4
============================
step 2 extract data
#!/usr/bin/env python3
import argparse
from PIL import Image
import string
def msb_to_lsb(bit_indices):
return bit_indices
def extract_hidden_data(image_path, r_planes=None, g_planes=None, b_planes=None,
stop_at_null=True, limit_pixels=None):
img = Image.open(image_path).convert(“RGB”)
width, height = img.size
pix = img.load()
r_idx = msb_to_lsb(r_planes or )
g_idx = msb_to_lsb(g_planes or )
b_idx = msb_to_lsb(b_planes or )
bitstream = []
total_pixels = 0
for y in range(height):
for x in range(width):
r, g, b = pix[x, y]
for plane in r_idx:
bitstream.append((r >> plane) & 1)
for plane in g_idx:
bitstream.append((g >> plane) & 1)
for plane in b_idx:
bitstream.append((b >> plane) & 1)
total_pixels += 1
if limit_pixels and total_pixels >= limit_pixels:
break
if limit_pixels and total_pixels >= limit_pixels:
break
data_bytes = bytearray()
byte = 0
count = 0
for bit in bitstream:
byte = (byte << 1) | bit
count += 1
if count == 8:
data_bytes.append(byte)
if stop_at_null and byte == 0:
return bytes(data_bytes)
byte = 0
count = 0
return bytes(data_bytes)
def printable_preview(data, max_len=200):
return ‘’.join(
chr(b) if chr(b) in string.printable and b != 0 else (‘.’ if b != 0 else ‘\0’)
for b in data[:max_len]
)
def main():
parser = argparse.ArgumentParser(description=“Extract hidden data “)
parser.add_argument(“image”, help=“Path to the image file (PNG, BMP, etc.)”)
parser.add_argument(”-o”, “–output”, default=“extracted.txt”, help=“save”)
parser.add_argument(“–no-stop”, action=“store_true”, help=“NULL byte”)
parser.add_argument(“–preview-len”, type=int, default=256)
parser.add_argument(“–limit-pixels”, type=int, default=None)
args = parser.parse_args()
# INSERT suspected planes for task3 and task4
r_planes = [7]
g_planes = [6, 2]
b_planes = []
data = extract_hidden_data(
args.image,
r_planes=r_planes,
g_planes=g_planes,
b_planes=b_planes,
stop_at_null=not args.no_stop,
limit_pixels=args.limit_pixels
)
with open(args.output, "wb") as f:
f.write(data)
print(f"[+] Extracted {len(data)} bytes, saved to: {args.output}")
print("[+] Preview:")
print(printable_preview(data, args.preview_len))
if name == “main”:
main()
============
for task 3 : R=7 G=6 and 2 B=0
for task 4: R=2 G=4 B=0
task3 : you should see the passwd
task4 : └─$ echo " somethinf from step 2 " | base64 -d