LSB Steganography
LSB (Least Significant Bit) เป็นเทคนิค steganography ที่ใช้บ่อยที่สุด — ซ่อนข้อมูลใน bit ต่ำสุดของแต่ละ pixel/sample ซึ่งเปลี่ยนค่าสีนิดเดียวจนตาคนมองไม่ออก บทนี้ลงลึกถึงกลไก bit-plane, ลำดับการอ่าน (channel/bit order), เครื่องมือทุกตัว, และการเขียน solver เองเมื่อ tool สำเร็จรูปแก้ไม่ได้
1. LSB ทำงานอย่างไร
ภาพแบบ lossless (PNG/BMP) เก็บแต่ละ pixel เป็นค่าสี เช่น RGB ช่องละ 8 bit (0–255) bit ขวาสุด (LSB) ของแต่ละช่องมีน้ำหนักแค่ 1 — เปลี่ยนจาก 0→1 ทำให้สีเพี้ยนไปแค่ 1/255 ตาคนแยกไม่ออก ผู้ซ่อนจึงแทนที่ LSB ของแต่ละ pixel ด้วย bit ของข้อความลับ ทีละ bit เรียงต่อกัน
2. ตัวแปรที่ต้องเดา/ลอง
ปัญหาของ LSB คือผู้ซ่อนเลือก 'วิธีเรียง' ได้หลายแบบ การ extract ต้องลองทุก combination จนเจอข้อมูลที่อ่านรู้เรื่อง ตัวแปรหลักมีดังนี้:
| ตัวแปร | ค่าที่เป็นไปได้ | หมายเหตุ |
|---|---|---|
| channel | R, G, B, A, หรือผสม | ซ่อนในช่องไหน หรือหลายช่อง |
| bit order | LSB-first / MSB-first | อ่าน bit จากต่ำหรือสูงก่อน |
| pixel order | row-major / column-major | อ่านแนวนอนหรือแนวตั้ง |
| bit plane | bit 0 (LSB) หรือ bit 1,2... | บางทีซ่อนใน bit ที่สูงกว่า LSB |
| จำนวน bit/channel | 1, 2, หรือมากกว่า | ซ่อนหลาย bit ต่อช่อง |
| start offset | เริ่ม pixel ที่เท่าไหร่ | อาจข้าม header |
3. zsteg — ลองทุก combination อัตโนมัติ (PNG/BMP)
zsteg คือเครื่องมือแรกที่ต้องลองกับ PNG/BMP — มันลองทุก combination ของ channel/bit-order/plane ให้อัตโนมัติ แล้วโชว์อันที่ดูเป็นข้อมูล (text, file signature)
# ลองทุก combination
zsteg image.png
# ละเอียด (ทุก channel/bit)
zsteg -a image.png
# ดึงข้อมูลจาก channel/bit ที่เจอ (เช่น b1,rgb,lsb,xy)
zsteg -E "b1,rgb,lsb,xy" image.png > extracted.bin
file extracted.bin # เช็คว่าได้ไฟล์อะไร
# ติดตั้ง
gem install zsteg4. StegSolve — ดู bit-plane ด้วยตา
StegSolve (Java GUI) ให้ดูภาพแยกทีละ bit-plane ของแต่ละ channel — ถ้าข้อมูลซ่อนใน plane ไหน plane นั้นจะเห็นเป็น pattern/ข้อความชัดเจน (ไม่ใช่ noise สุ่ม)
- 1เปิดภาพใน StegSolve
- 2กดปุ่ม < > ไล่ดู bit-plane ทีละอัน (Red 0–7, Green 0–7, Blue 0–7, Alpha)
- 3plane ที่มีข้อมูลจะเห็น text/QR/pattern แทน noise
- 4ใช้ 'Data Extract' เลือก channel+bit ที่เจอ แล้ว save ออกมา
- 5ลอง 'Image Combiner' ถ้าโจทย์มีหลายภาพ (XOR/diff สองภาพ)
5. เขียน solver เอง (เมื่อ tool แก้ไม่ได้)
เมื่อ zsteg/StegSolve แก้ไม่ได้ (เช่น bit order แปลก, ซ่อนแบบ custom) ต้องเขียน Python อ่าน LSB เองด้วย PIL — ควบคุมทุกตัวแปรได้
from PIL import Image
img = Image.open("image.png")
pixels = list(img.getdata()) # [(r,g,b), ...] หรือ (r,g,b,a)
bits = ""
for px in pixels:
for ch in px[:3]: # R,G,B (ลอง [:3] หรือเลือกช่องเดียว)
bits += str(ch & 1) # ดึง LSB
# แปลง bit -> bytes ทีละ 8
chars = ""
for i in range(0, len(bits) - 7, 8):
byte = bits[i:i+8]
chars += chr(int(byte, 2))
print(chars[:500]) # หา flag{...}
# variant: MSB-first ให้กลับ byte = byte[::-1]
# variant: ช่องเดียว -> วน ch in [px[0]] เท่านั้น
# variant: 2 bit/channel -> str(ch & 3) ... ปรับ step เป็น 4import numpy as np
from PIL import Image
arr = np.array(Image.open("image.png"))
# ดึง bit-plane 0 ของ channel R ออกมาเป็นภาพขาวดำ
plane = (arr[:,:,0] & 1) * 255
Image.fromarray(plane.astype('uint8')).save("plane_r0.png")
# เปิด plane_r0.png ดู — ถ้ามี text/QR = เจอ6. เครื่องมือ all-in-one
- stegoveritas — รันชุดใหญ่: แยกทุก bit-plane, metadata, LSB, สี → output โฟลเดอร์เดียว (
stegoveritas image.png) - zsteg — PNG/BMP LSB อัตโนมัติ (ตัวแรกที่ลอง)
- StegSolve — ดู plane ด้วยตา + extract + combine
- stegseek — ถ้าสงสัยว่าเป็น steghide (มี passphrase) ดูหัวข้อ Steghide
- เริ่มจาก zsteg → StegSolve → stegoveritas → เขียน solver เอง
7. Quick Reference
- LSB = ซ่อนใน bit ต่ำสุดของ pixel (เฉพาะ lossless: PNG/BMP/WAV)
- PNG/BMP: zsteg image.png → zsteg -E 'b1,rgb,lsb,xy' ดึง
- ดูด้วยตา: StegSolve ไล่ bit-plane
- all-in-one: stegoveritas
- ตัวแปร: channel, bit-order, pixel-order, plane, bit/channel
- tool ไม่ได้ → เขียน PIL: ch & 1 ต่อ bit แล้วแปลงทีละ 8
- JPEG ใช้ LSB ไม่ได้ → ดูหัวข้อ stego-jpg
🧭 จับมือทำทีละขั้น (มีแค่ Kali) + ถ้าติดไปไหนต่อ
สมมติเจอโจทย์ให้ไฟล์ PNG/BMP มา มีแค่ Kali เปล่าๆ สงสัยว่าเป็น LSB — ทำตามนี้ทีละขั้น เริ่มจากเครื่องมืออัตโนมัติก่อนเสมอ ก่อนจะไล่ดูด้วยตาหรือเขียน script เอง
- 1พิมพ์
file image.pngและexiftool image.png— ยืนยันชนิดไฟล์ + เช็ค metadata ก่อนเสมอ - 2พิมพ์
zsteg image.png— ลอง combination มาตรฐาน ดูว่ามีบรรทัดไหนโชว์ text/file ที่ไม่ใช่ noise - 3ถ้าไม่เจอ พิมพ์
zsteg -a image.png— ลองละเอียดขึ้น (ทุก channel/bit/order) - 4เจอ payload ที่น่าสนใจ (เช่น
b1,r,lsb,xy .. text: "flag{...}") → ดึงด้วยzsteg -E "b1,r,lsb,xy" image.png - 5ถ้า zsteg ไม่เจออะไรเลย เปิดภาพใน StegSolve (หรือ stegsolve.jar) แล้วกด < > ไล่ดูทุก bit-plane ของ R/G/B/Alpha ทีละอัน
- 6plane ไหนที่เห็นเป็น noise สม่ำเสมอ (ไม่ตามรูปทรงภาพ) = น่าสงสัยว่ามีข้อมูล — ลองใช้ 'Data Extract' ใน StegSolve เลือก channel/bit นั้น
- 7ถ้ายังไม่เจอ รัน
stegoveritas image.pngให้มันลองทุกอย่างรวดเดียว (แยก bit-plane, metadata, สี) แล้วดูโฟลเดอร์ output - 8ถ้ายังไม่เจอ เขียน Python เอง (PIL) อ่าน LSB แล้วสลับ channel/bit-order/pixel-order ตามตารางในหัวข้อนี้จนได้ข้อความอ่านรู้เรื่อง
- 9ถ้าลองครบทุก combination แล้วยังไม่เจอ ให้กลับไปเช็คว่าไฟล์เป็น PNG/BMP จริงไหม หรือจริงๆ เป็น JPG/WAV ที่ใช้ LSB ไม่ได้
| ขั้นตอน/งาน | เครื่องมือใน Kali | ติดตั้งเพิ่ม (ถ้าไม่มี) | เครื่องมือออนไลน์ |
|---|---|---|---|
| สแกน LSB อัตโนมัติ (PNG/BMP) | zsteg | gem install zsteg | aperisolve.com |
| ดู bit-plane ด้วยตา | StegSolve (java -jar) | wget stegsolve.jar | stylesuxx.github.io/steganography |
| รันชุดใหญ่อัตโนมัติ | stegoveritas | pipx install stegoveritas | aperisolve.com |
| เขียน solver เอง | python3 + PIL/numpy | pip install pillow numpy | CyberChef (Extract LSB operation) |
| เช็ค metadata ก่อนเสมอ | exiftool | sudo apt install libimage-exiftool-perl | exifdata.com |
| เช็คไฟล์ฝัง/ต่อท้าย | binwalk | sudo apt install binwalk | aperisolve.com |
| ถ้าเป็น JPG แทน PNG | steghide | sudo apt install steghide | futureboy.us/stegano |
โน้ตของฉัน
ยังไม่มีโน้ตสำหรับหัวข้อนี้