### Setup virtual environment with uv Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Sets up a virtual environment and installs the project plus development dependencies using uv. Run this before using the manual linting commands. ```bash # Create & activate a virtual environment uv venv # Install project + development dependencies from pyproject.toml uv sync --extra dev ``` -------------------------------- ### Install binwalk with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/binwalk.md Installs binwalk locally using apt. This is the installation command for Debian-based systems. ```console $ apt install binwalk ``` -------------------------------- ### Install jsteg with Go Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/jsteg.md Installs the jsteg command-line tool using Go's install command. Prebuilt binaries are also available on GitHub releases. ```console $ go install lukechampine.com/jsteg/cmd/jsteg@latest ``` -------------------------------- ### Install OutGuess with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/outguess.md Install OutGuess locally on Debian/Ubuntu systems. Requires root privileges or sudo. ```console $ apt install outguess ``` -------------------------------- ### Install exiftool locally with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/exiftool.md Install ExifTool on Debian/Ubuntu systems using the libimage-exiftool-perl package. ```console $ apt install libimage-exiftool-perl ``` -------------------------------- ### Install stegseek on Debian/Ubuntu Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/stegseek.md Installation commands for Debian/Ubuntu. Downloads the .deb package from the releases page and installs it with apt. ```console $ # Debian/Ubuntu: grab the .deb from the releases page $ wget https://github.com/RickdeJager/stegseek/releases/latest/download/stegseek.deb $ sudo apt install ./stegseek.deb ``` -------------------------------- ### Install foremost with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/foremost.md Installs foremost locally using apt on Debian-based systems. ```console $ apt install foremost ``` -------------------------------- ### Install a new tool with apt-get in Dockerfile Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Add this RUN instruction to the Dockerfile when installing a new tool that is available via apt-get. It updates package lists, installs the tool, and cleans up the apt cache to keep the image small. ```dockerfile RUN apt-get update && apt-get install -y \ your-new-tool \ && rm -rf /var/lib/apt/lists/* ``` -------------------------------- ### Install pngcheck with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pngcheck.md Install pngcheck locally using the apt package manager. ```console $ apt install pngcheck ``` -------------------------------- ### Install pre-commit hooks Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Installs the pre-commit hooks so staged files are checked on commit. ```bash pre-commit install ``` -------------------------------- ### Install OpenStego from .deb or .jar Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/openstego.md Download the `.deb` or `.jar` from the GitHub releases; Java is required. The command shows installing the .deb package, with the alternative `java -jar openstego.jar` commented. ```console $ sudo dpkg -i openstego_0.8.6-1_all.deb # or: java -jar openstego.jar ``` -------------------------------- ### Start AperiSolve with Docker Compose Source: https://github.com/zeecka/aperisolve/blob/main/README.md Clone the repository, copy the environment template, and start the Docker Compose stack. Requires Docker and Docker Compose. After running, browse to http://localhost:5000/. Ads and analytics are disabled by default; integrations like CUSTOM_EXTERNAL_SCRIPT, GOOGLE_ADS_TXT, SITE_BASE_URL, and Sentry are opt-in via environment variables in .env.example. ```bash git clone https://github.com/Zeecka/AperiSolve.git cd AperiSolve cp .env.example .env docker compose up -d ``` -------------------------------- ### Install zsteg with gem Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/zsteg.md Installs zsteg locally using Ruby's gem command. ```console $ gem install zsteg ``` -------------------------------- ### Install ImageMagick with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/identify.md Installs ImageMagick locally on Debian/Ubuntu systems to use the identify command. ```console $ apt install imagemagick ``` -------------------------------- ### Example file command output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/file.md Example output from the file command. PNG and JPEG lines indicate the file is what it claims, with dimensions and color type from the header. Zip archive data means the file is actually something else. 'data' means no known signature matched, indicating a missing, corrupted, or deliberately mangled header. ```text PNG image data, 800 x 600, 8-bit/color RGBA, non-interlaced JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72 Zip archive data, at least v2.0 to extract data ``` -------------------------------- ### Install stegsnow with apt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/stegsnow.md Install stegsnow on Kali/Debian via apt. The tool is part of the 'snow' package. ```console $ sudo apt install stegsnow # Kali/Debian; part of the "snow" package ``` -------------------------------- ### Example zsteg output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/zsteg.md Sample output lines from zsteg. Each line starts with the encoding it was found in, followed by the detected content. Short repeated strings like 'AAAA' are usually noise; real payloads tend to be readable sentences, flags, or file signatures. ```text b1,r,lsb,xy .. text: "hidden message" b1,rgb,lsb,xy .. file: Zip archive data b2,g,msb,yx .. text: "AAAAAAAA" ``` -------------------------------- ### Brainfuck program example Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/text.md A short Brainfuck program that prints 'Hello World!'. Brainfuck uses only the characters +-<>[]., and this snippet is a common CTF example. ```text brainfuck> ++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++.>+.+++++++..+++. ``` -------------------------------- ### Install poppler-utils Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pdfinfo.md Installs the poppler-utils package, which provides pdfinfo along with pdftotext, pdfimages, and pdftk-style helpers for extracting PDF content. ```console $ apt install poppler-utils ``` -------------------------------- ### Complete analyzer example (PngcheckAnalyzer) Source: https://github.com/zeecka/aperisolve/blob/main/docs/adding-analyzer.md Complete example of a custom analyzer class. It subclasses SubprocessAnalyzer, sets the name and display_order, defines the command to run, and implements is_error and process_error methods to handle errors. ```python from .base_analyzer import SubprocessAnalyzer class PngcheckAnalyzer(SubprocessAnalyzer): name = "pngcheck" display_order = 80 def __init__(self, input_img, output_dir): super().__init__(input_img, output_dir) self.cmd = ["pngcheck", "-v", self.img] def is_error(self, returncode, stdout, stderr, *, zip_exist): return "this is neither a PNG or JNG image" in stdout def process_error(self, stdout, stderr): if "neither a PNG or JNG" in stdout: return "File format not supported (PNG/JNG only)" return stdout ``` -------------------------------- ### Commit message examples Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Shows recommended and discouraged commit message formats. The first block lists good examples that are descriptive and specific, while the second block shows vague messages to avoid. ```bash git commit -m "Add zsteg analyzer for PNG steganography detection" git commit -m "Fix foremost error detection when no files extracted" ``` ```bash git commit -m "updates" git commit -m "fix" ``` -------------------------------- ### Run unit and end-to-end tests (uv, pytest, docker compose) Source: https://github.com/zeecka/aperisolve/blob/main/README.md Shown in the Testing section of the project's README. The first two commands set up the development environment and run unit tests without requiring any services. The next two commands start the development services via Docker Compose and run end-to-end analyzer tests against the running application. ```bash uv sync --extra dev uv run pytest -q # unit tests (no services needed) docker compose -f compose.dev.yml up -d uv run pytest tests/test_webapp_analyzers.py -v ``` -------------------------------- ### Worked example: extract a ZIP hidden in LSBs Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/images.md Worked example: zsteg -a finds a ZIP archive in the LSBs. Extract the raw bytes of that combination with -E, then unzip to recover flag.txt. If -E yields an unrecognized header, run file payload.bin first. ```console $ zsteg -a challenge.png ``` ```console $ zsteg -E 'b1,rgb,lsb,xy' challenge.png > payload.zip ``` ```console $ unzip payload.zip ``` -------------------------------- ### Install and run PCRT locally Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pcrt.md Commands to clone the original PCRT repository and run it on an image. The original is Python 2 era; the PCRT3 forks run on Python 3. ```console $ git clone https://github.com/sherlly/PCRT $ python PCRT.py -i image.png ``` -------------------------------- ### Run webapp analyzer tests with Docker Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Starts the development stack and runs the end-to-end webapp analyzer tests. These tests are skipped automatically when no server is reachable. ```bash docker compose -f compose.dev.yml up -d pytest tests/test_webapp_analyzers.py -v # or point APERISOLVE_BASE_URL elsewhere ``` -------------------------------- ### Install GraphicsMagick with ImageMagick compatibility Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/identify.md Installs the GraphicsMagick flavor that Aperi'Solve uses, including the ImageMagick compatibility layer that provides the identify command. ```console $ apt install graphicsmagick graphicsmagick-imagemagick-compat ``` -------------------------------- ### Example strings output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/strings.md Sample output from strings showing readable islands: chunk names, editor signatures, a base64 blob, and a flag. Long alphanumeric blobs ending in '=' are likely base64; text near the end often sits after image data. ```text IHDR Adobe Photoshop 2024 XML:com.adobe.xmp aHR0cHM6Ly9leGFtcGxlLmNvbQ== CTF{str1ngs_f1rst_alw4ys} ``` -------------------------------- ### Render spectrogram for challenge.wav Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/audio.md Worked example: render the spectrogram of challenge.wav to reveal text drawn between 2 and 8 kHz. If the result is smeared, re-render with high-resolution options (-X 200 -Y 2050 -z 120) and scan above 20 kHz before giving up. ```console sox challenge.wav -n spectrogram -o spec.png ``` ```console sox challenge.wav -n spectrogram -o spec.png -X 200 -Y 2050 -z 120 ``` -------------------------------- ### Example pdfid output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pdfid.md Sample output from pdfid showing counts for various PDF objects and keywords. Non-zero counts for /JavaScript, /OpenAction, /Launch, /EmbeddedFile, or /URI indicate potential malicious activity. ```text PDFiD 0.2.8 document.pdf PDF Header: %PDF-1.7 obj 8 endobj 8 stream 2 endstream 2 /JS 1 /JavaScript 1 /OpenAction 1 /Launch 0 /EmbeddedFile 1 /URI 0 ``` -------------------------------- ### Triage with capinfos and tshark Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/cheatsheet/network.md Use these commands to get basic capture info, protocol hierarchy, and TCP conversations. The `-q -z io,phs` option shows what protocols are present, and `-q -z conv,tcp` lists endpoints and byte counts. ```console $ capinfos capture.pcap # size, packet count, time range $ tshark -r capture.pcap -q -z io,phs # protocol hierarchy — what's in here? $ tshark -r capture.pcap -q -z conv,tcp # TCP conversations (endpoints, bytes) ``` -------------------------------- ### Carve payload with dd using offset Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/files-archives.md Manually carve a payload from a file once you know the offset, when `binwalk` misses it. Use `bs=1` and `skip=$OFFSET` to copy bytes starting at the offset. ```console $ dd if=target of=payload.bin bs=1 skip=$OFFSET ``` -------------------------------- ### Example pdfinfo output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pdfinfo.md Shows the typical output of pdfinfo, including title, author, producer, creation date, page count, encryption status, page size, and PDF version. Useful for understanding the metadata fields. ```text Title: Annual Report Author: alice Producer: LibreOffice 7.4 CreationDate: Sat Jul 5 12:00:00 2025 UTC Pages: 3 Encrypted: no Page size: 612 x 792 pts (letter) PDF version: 1.7 ``` -------------------------------- ### Inspect file type and appended data with file, tail, xxd, binwalk Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/files-archives.md Inspect a file's type and look for appended data or embedded signatures. `file` only reads the magic bytes at the start, so appended content is invisible to it; `tail` and `xxd` reveal the trailer, and `binwalk` lists or extracts embedded signatures. ```console $ file target $ tail -c 200 target | xxd # inspect the trailer $ binwalk target # list embedded signatures $ binwalk -e target # auto-extract them ``` -------------------------------- ### Sample identify -verbose output Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/identify.md Example output from identify -verbose showing the image name, format, geometry, depth, colorspace, and channel statistics. The -verbose flag also lists resolution, interlacing, compression, unique colors, and free-form text properties such as comments and key/value pairs (PNG tEXt/zTXt chunks, JPEG comments). ```text Image: image.png Format: PNG (Portable Network Graphics) Geometry: 800x600 Depth: 8 bits-per-pixel component Colorspace: sRGB Channel Statistics: ... ``` -------------------------------- ### pngcheck output for a healthy PNG Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pngcheck.md Example output from pngcheck showing a healthy PNG with IHDR, IDAT, and IEND chunks, including offsets and lengths. A healthy PNG starts with IHDR, contains one or more IDAT chunks, and ends with IEND. ```text File: image.png (54321 bytes) chunk IHDR at offset 0x0000c, length 13 800 x 600 image, 32-bit RGB+alpha, non-interlaced chunk IDAT at offset 0x00025, length 54000 chunk IEND at offset 0x0d33d, length 0 No errors detected in image.png (3 chunks, 77.4% compression). ``` -------------------------------- ### Run exiftool with -a -u -g1 to show all tags including unknown Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/exiftool.md Aperi'Solve runs this command to reveal metadata. -a shows duplicated tags, -u shows unknown tags where hand-crafted data usually hides, and -g1 groups output by metadata block. ```console $ exiftool -a -u -g1 image.jpg ``` -------------------------------- ### Extract with default algorithm via OpenStego CLI Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/openstego.md The CLI equivalent of what Aperi'Solve does; `randomlsb` is the default algorithm, so `-a` can usually be omitted. Running `openstego` with no arguments opens the GUI. ```console $ openstego extract -sf image.png -p password -xd outdir ``` -------------------------------- ### foremost audit.txt output example Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/foremost.md Example audit.txt output from foremost. The first entry is often the carrier image itself; additional files, like the Zip at offset 54187, are the carved hidden files. ```text Num Name (bs=512) Size File Offset Comment 0: 00000105.zip 1 KB 54187 1: 00000000.jpg 52 KB 0 ``` -------------------------------- ### PCRT log output example Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pcrt.md Example log output from PCRT showing an IHDR CRC error, the incorrect and correct CRC values, and the recovered dimensions found via exhaustive search. ```text Error IHDR CRC found at offset 0x1d Chunk crc: 00000000, Correct crc: 575943df Found correct dimensions via exhaustive search: 800x600 ``` -------------------------------- ### Basic steganography checks: file, strings, exiftool, binwalk Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/methodology.md Run these commands in order to solve many easy challenges and reveal anomalies. The extension is attacker-controlled; trust the `file` output over the extension. ```bash file ``` ```bash strings ``` ```bash exiftool ``` ```bash binwalk ``` -------------------------------- ### Run jpseek with passphrase prompt Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/jpseek.md Aperi'Solve runs jpseek with expect, answering the interactive passphrase prompt with the upload password or an empty line. On success, jpseek.out is zipped and offered as a download. ```console $ jpseek image.jpg jpseek.out Passphrase: ``` -------------------------------- ### Override process_output() for custom output formatting Source: https://github.com/zeecka/aperisolve/blob/main/docs/adding-analyzer.md Override process_output() to format the results. The example parses stdout lines into key-value pairs based on a colon separator. ```python def process_output(self, stdout: str, stderr: str) -> dict[str, str]: # Parse into key-value pairs metadata = {} for line in stdout.split("\n"): if ":" in line: key, value = line.split(":", 1) metadata[key.strip()] = value.strip() return metadata ``` -------------------------------- ### Prepare rockyou wordlist Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/cheatsheet/brute-force.md Check for the rockyou wordlist and decompress it if needed. The -k flag keeps the original .gz file. ```console $ ls -la /usr/share/wordlists/rockyou.txt # the default CTF list $ gunzip -k /usr/share/wordlists/rockyou.txt.gz # if it's still gzipped ``` -------------------------------- ### Override is_error() for custom error detection Source: https://github.com/zeecka/aperisolve/blob/main/docs/adding-analyzer.md Override is_error() to define what counts as an error. The example returns True only if stderr is non-empty and no zip file was extracted. ```python def is_error(self, returncode: int, stdout: str, stderr: str, *, zip_exist: bool) -> bool: # Only error if no files were extracted return len(stderr) > 0 and not zip_exist ``` -------------------------------- ### Override process_error() for user-friendly error messages Source: https://github.com/zeecka/aperisolve/blob/main/docs/adding-analyzer.md Override process_error() to provide helpful messages. The example returns a custom message when stdout contains 'not supported', otherwise returns stderr. ```python def process_error(self, stdout: str, stderr: str) -> str: if "not supported" in stdout: return "This file format is not supported (PNG only)" return stderr ``` -------------------------------- ### Build jphs tools from source Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/jpseek.md Builds the jphs tools locally. The bundled jpeg-8a must be built first; make all produces ./jphide and ./jpseek. Aperi'Solve's Docker image builds it this way with small patches to the Makefile and jpseek.c. ```console $ git clone https://github.com/h3xx/jphs $ cd jphs/jpeg-8a && ./configure && make && cd .. $ make all # produces ./jphide and ./jpseek ``` -------------------------------- ### Tag and push a release (git tag 3.3.0) Source: https://github.com/zeecka/aperisolve/blob/main/docs/deploy.md Publishing a git tag triggers the production deployment. Create and push a tag in the format shown; the release workflow then builds, pushes the image, and redeploys the stack on the production server. ```console $ git tag 3.3.0 $ git push origin 3.3.0 ``` -------------------------------- ### Pillow: extract LSB bits from red channel Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/images.md Script LSB extraction with Pillow: open an image, get pixel data, and extract the LSB of the red channel for each pixel. Useful once a plane looks structured. ```python # pip install Pillow from PIL import Image img = Image.open("file.png") pixels = list(img.getdata()) # [(r, g, b), (r, g, b), ...] bits = [px[0] & 1 for px in pixels] # LSB of the red channel ``` -------------------------------- ### Compile and copy jphide/jpseek binaries in Dockerfile Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Use this builder-stage pattern for tools that require compilation, such as jphide. The first block clones, builds, and copies the binaries into the builder stage; the second block copies the compiled binaries into the runtime stage. ```dockerfile RUN git clone https://github.com/h3xx/jphs.git /tmp/jphs && \ cd /tmp/jphs && \ make && \ cp jphide jpseek /usr/local/bin/ && \ rm -rf /tmp/jphs ``` ```dockerfile COPY --from=builder /usr/local/bin/jphide /usr/local/bin/jphide COPY --from=builder /usr/local/bin/jpseek /usr/local/bin/jpseek ``` -------------------------------- ### Probe container with ffprobe, mediainfo, exiftool Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/video.md Probe the container before touching pixels. Enumerate streams, codecs, durations, and metadata. An extra subtitle, data, or attachment stream is a common hiding place. ```console $ ffprobe -hide_banner file.mp4 # streams, codecs, durations $ mediainfo file.mkv # human-readable track table $ exiftool -a -u -g1 file.mp4 # container metadata + tags ``` -------------------------------- ### pngcheck output with CRC error Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pngcheck.md Example output showing a CRC error in a chunk, which indicates that the chunk data was edited without recomputing the CRC. The original CRC still matches the original data, which is how tools recover it. ```text chunk IHDR at offset 0x0000c, length 13 CRC error in chunk IHDR (computed 575943df, expected 12345678) ERRORS DETECTED in image.png ``` -------------------------------- ### Run pdfid.py with Python 3 Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/pdfid.md Command to run pdfid.py locally after downloading it from Didier Stevens' site. Requires Python 3. ```console $ python3 pdfid.py document.pdf ``` -------------------------------- ### Detect polyglot files with binwalk and xxd magic grep Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/cheatsheet/files.md Detect polyglot files that are valid under two parsers. file reads only the start and will not flag them; binwalk shows multiple signatures at nonzero offsets, and xxd greps for PDF/ZIP/JPEG/GIF magic bytes. ```console $ binwalk target # multiple signatures at nonzero offsets $ xxd target | grep -iE '25504446|504b0304|ffd8ff|47494638' # PDF/ZIP/JPEG/GIF magic ``` -------------------------------- ### Run binwalk with recursive extraction Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/binwalk.md Runs binwalk with recursive extraction on an image. The -e flag extracts every recognized signature, and --matryoshka recurses into extracted archives. When anything is extracted, the result page offers the files as a .7z download. ```console $ binwalk --matryoshka -e image.png ``` -------------------------------- ### List NTFS alternate data streams with dir /r Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/techniques/files-archives.md List files and their alternate data streams on Windows. ```console dir /r ``` -------------------------------- ### Run pre-commit on all files Source: https://github.com/zeecka/aperisolve/blob/main/CONTRIBUTING.md Manually runs all pre-commit hooks on all files before committing. ```bash pre-commit run --all-files ``` -------------------------------- ### Check PNG structure and inflate IDAT with pngcheck and zlib-flate Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/cheatsheet/image.md pngcheck verifies structure, CRCs, and text chunks. zlib-flate manually inflates a raw IDAT if needed. ```console $ pngcheck -vtp7f image.png # structure, CRCs, text chunks $ zlib-flate -uncompress < idat.bin # manually inflate a raw IDAT if needed ``` -------------------------------- ### Basic SubprocessAnalyzer template for a new tool Source: https://github.com/zeecka/aperisolve/blob/main/docs/adding-analyzer.md Create a file in analyzers/ and subclass SubprocessAnalyzer. Set the name attribute to the tool name used as the results.json key and download URL segment, and display_order for frontend position. The __init__ method must set self.cmd to the command to run. ```python from .base_analyzer import SubprocessAnalyzer class MyToolAnalyzer(SubprocessAnalyzer): """Analyzer for mytool.""" name = "mytool" # results.json key and download URL segment display_order = 165 # frontend position (lower renders first) def __init__(self, input_img, output_dir): super().__init__(input_img, output_dir) self.cmd = ["mytool", self.img] ``` -------------------------------- ### Manually carve embedded file with dd and unzip Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/binwalk.md Carves a specific region from an image without binwalk's automation. The dd command extracts bytes starting at offset 54187 into hidden.zip, then unzip extracts the archive. Useful for manually extracting a known embedded file. ```console $ dd if=image.png of=hidden.zip bs=1 skip=54187 $ unzip hidden.zip ``` -------------------------------- ### binwalk output showing embedded Zip archive Source: https://github.com/zeecka/aperisolve/blob/main/aperisolve/wiki_content/en/tools/binwalk.md Example output from binwalk showing the carrier image and an embedded Zip archive at byte offset 54187. The first line is the carrier itself; any additional signature is suspicious. False positives are common with short generic signatures, so check extraction results before drawing conclusions. ```text DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------- 0 0x0 PNG image, 800 x 600, 8-bit/color RGBA 54187 0xD3AB Zip archive data, name: flag.txt ```