Imposter
Imposter
Platform: hackerlab | Category: Steganography | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2025-12-22 | Status: Solved Techniques: inverted_bit_extraction, lsb_url_encoding, multi_stage_steganography, steghide_bruteforce
Summary
Task: PNG image with Among Us character containing hidden data. Solution: Extract URL from LSB in red channel using inverted bit positions, download second JPG image, bruteforce steghide password with stegseek to get the flag.
Imposter — hackerlab
Description
"There is 1 Imposter."
Provided a ZIP archive with an Among Us character image (red imposter on green background).
Analysis
Step 1: Initial Image Analysis
File Imposter.png — PNG image 842x1024, RGB. Red Among Us character on green background.
bash read-only • copy allowedfile Imposter.png # PNG image data, 842 x 1024, 8-bit/color RGB, non-interlaced
Step 2: LSB Analysis
When analyzing the first row of pixels, anomalies were found — 92 pixels differ from the background by 1 in the red channel:
- Background: RGB(71, 112, 76)
- "Imposter" pixels: RGB(70, 112, 76)
The difference is only in the LSB of the red channel (71 → 70, i.e., bit changed from 1 to 0).
Step 3: Decoding the Hidden URL
Positions of "imposter" pixels in the first row encode a binary message. After bit inversion, we get a URL:
python read-only • copy allowedfrom PIL import Image import numpy as np img = Image.open('Imposter.png') arr = np.array(img) # Analyze first row row0 = arr[0] background = (71, 112, 76) # Find pixels that differ from background imposter_cols = [] for col in range(arr.shape[1]): pixel = tuple(row0[col]) if pixel != background: imposter_cols.append(col) print(f"Found {len(imposter_cols)} imposter pixels") # Found 92 imposter pixels # Positions encode bits (presence = 0, absence = 1 after inversion) # Decoding gives URL: https://ibb.co/d2TxBjh
Hidden URL: https://ibb.co/d2TxBjh
Step 4: Second Image
The URL downloads image sticker.jpg — a robot/cyborg with Russian text "УЛЬТРАХОРОШ" (ULTRAKHOROSH).
bash read-only • copy allowedcurl -L "https://ibb.co/d2TxBjh" -o sticker.jpg
Step 5: Steghide Bruteforce
JPG image — classic candidate for steghide. Using stegseek for password bruteforce:
bash read-only • copy allowed# Via Docker docker run --rm -v $(pwd):/data -v /tmp:/wordlists \ rickdejager/stegseek /data/sticker.jpg /wordlists/rockyou.txt \ -xf /data/extracted.txt # Result: # [i] Found passphrase: "696969" # [i] Original filename: "flag.txt" # [i] Extracting to "extracted.txt"
Found password: 696969
Step 6: Flag Extraction
bash read-only • copy allowedsteghide extract -sf sticker.jpg -p "696969" -xf flag.txt cat flag.txt # CODEBY{REDACTED}
Solution (Full Script)
python read-only • copy allowed#!/usr/bin/env python3 """ Imposter - Multi-stage steganography solver Stage 1: LSB in PNG -> URL Stage 2: Steghide in JPG -> Flag """ from PIL import Image import numpy as np import subprocess import requests # Stage 1: Extract URL from PNG LSB def extract_url_from_png(filename): img = Image.open(filename) arr = np.array(img) # Background color bg = (71, 112, 76) # Find imposter pixels in row 0 row0 = arr[0] width = arr.shape[1] # Build binary string from pixel positions bits = [] for col in range(width): pixel = tuple(row0[col]) # Imposter pixel (differs by 1 in R channel) = 0, background = 1 if pixel[0] == bg[0] - 1 and pixel[1:] == bg[1:]: bits.append('0') else: bits.append('1') # Invert and decode inverted = ''.join('1' if b == '0' else '0' for b in bits) # Convert to bytes url_bytes = [] for i in range(0, len(inverted), 8): byte = inverted[i:i+8] if len(byte) == 8: char = chr(int(byte, 2)) if char.isprintable() or char in '\n\r\t': url_bytes.append(char) url = ''.join(url_bytes).strip() # Extract actual URL if 'https://' in url: start = url.find('https://') end = url.find(' ', start) if ' ' in url[start:] else len(url) return url[start:end].strip() return url # Stage 2: Steghide bruteforce with stegseek def extract_from_steghide(jpg_file, wordlist='/tmp/rockyou.txt'): cmd = [ 'docker', 'run', '--rm', '-v', f'{jpg_file}:/data/image.jpg', '-v', f'{wordlist}:/wordlists/rockyou.txt', 'rickdejager/stegseek', '/data/image.jpg', '/wordlists/rockyou.txt', '-xf', '/data/output.txt' ] result = subprocess.run(cmd, capture_output=True, text=True) return result.stdout if __name__ == "__main__": # Stage 1 url = extract_url_from_png('Imposter.png') print(f"[+] Hidden URL: {url}") # Download second image # ... download sticker.jpg from url ... # Stage 2 # stegseek sticker.jpg rockyou.txt # Password: 696969 # Flag in flag.txt
Additional Notes
Multi-stage Steganography
The task demonstrates classic multi-stage steganography:
- PNG → URL — LSB in red channel with inverted bits
- URL → JPG — external image hosting (ImgBB)
- JPG → Flag — steghide with dictionary password
Tools for Steghide Bruteforce
- stegseek — fast bruteforce for steghide (recommended)
- stegcracker — alternative, slower
- John the Ripper — with steghide module
Typical Steghide Passwords
- Numeric patterns: 123456, 696969, 111111
- Simple words: password, secret, hidden
- Context-related: imposter, amongus, red
Why Bit Inversion?
Authors often invert bits to:
- Complicate automatic detection
- Make "0" more rare (fewer modifications)
- Add an additional layer of obfuscation