Embed Arbitrary Payloads into JPEGs without Special Tools

3 min read Original article ↗

Using ordinary shell commands to embed and extract hidden binary data in JPEG images

Arbitrary binary data can be hidden at the end of JPEG files which otherwise behave normally. This article explores strategies for packing and unpacking payloads into JPEG images using standard console commands and no external tools or special steganography software. I find it amusing how easy it is to hide arbitrary data in JPEG images that otherwise appear normal!

Images with unexpected trailing binary data will be quickly flagged by antivirus systems, or the trailing data will be stripped when the image is re-encoded, but the easy detection of binary payloads in images is somewhat offset by the simplicity and availability of this method, allowing JPEG images to be appended with arbitrary binary payloads on virtually any system.

Theory of Operation

  • JPEG files terminate with an EOI (End Of Image) marker FF D9
  • Data after the EOI marker is typically ignored when displaying the image
  • Embed an arbitrary payload to a JPEG by appending it to the end of the file
  • Extract the binary payloads by capturing data after the first FF D9
  • Embedding and extracting payloads can be done with standard console commands
  • Payloads may be any file type (exe, mp3, etc.) and are not restricted to other images

Commands

These commands can be run on any system and do not require any special tools. See the JPEG binary payload GitHub repository for downloadable script files, original images, and images pre-loaded with hidden data.

Bash

# Embed a payload
cat image.jpg payload.bin > image_with_payload.jpg
# Extract the payload
offset=$(grep -abo $'\xff\xd9' image_with_payload.jpg | head -n1 | cut -d: -f1)
tail -c +$((offset + 3)) image_with_payload.jpg > payload.bin

Powershell

# Embed a payload
[IO.File]::WriteAllBytes(
    "image_with_payload.jpg",
    [IO.File]::ReadAllBytes("image.jpg") +
    [IO.File]::ReadAllBytes("payload.bin")
)
# Extract the payload
$data = [IO.File]::ReadAllBytes("image_with_payload.jpg")
for ($i = 0; $i -lt $data.Length - 1; $i++) {
    if ($data[$i] -eq 0xFF -and $data[$i + 1] -eq 0xD9) {
        $start = $i + 2
        break
    }
}
[IO.File]::WriteAllBytes("payload.bin", $data[$start..($data.Length - 1)])

Command Prompt

:: Embed a payload
copy /b image.jpg + payload.bin image_with_payload.jpg

Extracting payloads with the command prompt is difficult because it does not have native byte array handling, so extraction requires writing a script that calls external system tools like certutil. Although it is possible to extract payloads using only command prompt and system tools, it is recommended to use the PowerShell extraction script on Windows platforms instead.

Example Images with Payload Data

Image + Payload Payload

Image:

Plain Text: zen_of_python.txt

Audio: payload.mp3

Limitations

  • The payload will get dropped if the image is re-encoded
  • The payload increases the file size, so large payloads become obvious
  • JPEGs with embedded thumbnails may have multiple FF D9 instances
  • Some software legitimately stores metadata after the JPEG EOI marker

Resources

  Feedback   Source   Contact

Built with Hugo 0.111.3 on May 2, 2026 at 7:10 pm EST