This code is a tool for embedding data into a...

August 23, 2025 at 08:39 AM

import zlib from struct import unpack_from import sys PNG_MAGIC = b"\x89PNG\r\n\x1a\n" if len(sys.argv) != 4: print(f"USAGE: {sys.argv[0]} cover.png content.bin output.png") exit() # this function is gross def fixup_zip(data, start_offset): # find the "end of central directory" marker end_central_dir_offset = data.rindex(b"PK\x05\x06") # adjust comment length so that any trailing data (i.e. PNG IEND) # is part of the comment comment_length = (len(data)-end_central_dir_offset) - 22 + 0x10 cl_range = slice(end_central_dir_offset+20, end_central_dir_offset+20+2) data[cl_range] = comment_length.to_bytes(2, "little") # find the number of central directory entries cdent_count = unpack_from("<H", data, end_central_dir_offset+10)[0] # find the offset of the central directory entries, and fix it cd_range = slice(end_central_dir_offset+16, end_central_dir_offset+16+4) central_dir_start_offset = int.from_bytes(data[cd_range], "little") data[cd_range] = (central_dir_start_offset + start_offset).to_bytes(4, "little") # iterate over the central directory entries for _ in range(cdent_count): central_dir_start_offset = data.index(b"PK\x01\x02", central_dir_start_offset) # fix the offset that points to the local file header off_range = slice(central_dir_start_offset+42, central_dir_start_offset+42+4) off = int.from_bytes(data[off_range], "little") data[off_range] = (off + start_offset).to_bytes(4, "little") central_dir_start_offset += 1 png_in = open(sys.argv[1], "rb") content_in = open(sys.argv[2], "rb") png_out = open(sys.argv[3], "wb") # check the PNG magic is present in the input file, and write it to the output file png_header = png_in.read(len(PNG_MAGIC)) assert(png_header == PNG_MAGIC) png_out.write(png_header) idat_body = b"" # iterate through the chunks of the PNG file while True: # parse a chunk chunk_len = int.from_bytes(png_in.read(4), "big") chunk_type = png_in.read(4) chunk_body = png_in.read(chunk_len) chunk_csum = int.from_bytes(png_in.read(4), "big") # if it's a non-essential chunk, skip over it if chunk_type not in [b"IHDR", b"PLTE", b"IDAT", b"IEND"]: print("Warning: dropping non-essential or unknown chunk:", chunk_type.decode()) continue # take note of the image width and height, for future calculations if chunk_type == b"IHDR": width, height = unpack_from(">II", chunk_body) print(f"Image size: {width}x{height}px") # There might be multiple IDAT chunks, we will concatenate their contents # and write them into a single chunk later if chunk_type == b"IDAT": idat_body += chunk_body continue # the IEND chunk should be at the end, now is the time to write our IDAT # chunk, before we actually write the IEND chunk if chunk_type == b"IEND": start_offset = png_out.tell()+8+len(idat_body) print("Embedded file starts at offset", hex(start_offset)) # concatenate our content that we want to embed idat_body += content_in.read() if len(idat_body) > width * height: exit("ERROR: Input files too big for cover image resolution.") # if its a zip file, fix the offsets if sys.argv[2].split(".")[-1].lower() in ["zip", "jar"]: print("Fixing up zip offsets...") idat_body = bytearray(idat_body) fixup_zip(idat_body, start_offset) # write the IDAT chunk png_out.write(len(idat_body).to_bytes(4, "big")) png_out.write(b"IDAT") png_out.write(idat_body) png_out.write(zlib.crc32(b"IDAT" + idat_body).to_bytes(4, "big")) # if we reached here, we're writing the IHDR, PLTE or IEND chunk png_out.write(chunk_len.to_bytes(4, "big")) png_out.write(chunk_type) png_out.write(chunk_body) png_out.write(chunk_csum.to_bytes(4, "big")) if chunk_type == b"IEND": # we're done! break # close our file handles png_in.close() content_in.close() png_out.close()

This code is a tool for embedding data into a PNG file by appending that data inside its IDAT (image data) chunk. Here's a breakdown of what the code does:

  1. Inputs:

    • It takes three command-line arguments:
      • cover.png: The source PNG file used as a "host" or "cover" for hiding the extra data.
      • content.bin: The content file you wish to embed, e.g., a binary file or a zip file.
      • output.png: The output PNG file with the embedded content.
  2. Validates PNG Format:

    • It checks the first few bytes of cover.png to verify that it has the correct PNG magic bytes to ensure it's a valid PNG file.
  3. Processes PNG Chunks:

    • PNG files are composed of chunks, each with a specific type (e.g., IHDR, IDAT, IEND, etc.). The code iterates through these chunks:
      • IHDR: Extracts and prints the image dimensions (width and height).
      • IDAT: Collects all image data chunks into a buffer (idat_body), as it plans to replace or extend them.
      • Non-essential chunks (those not in [IHDR, PLTE, IDAT, IEND]): These are skipped, but a warning is printed.
      • IEND: This marks the end of the PNG file. Before writing the IEND chunk, the tool embeds the content file data (content.bin) into the IDAT section.
  4. Embedding Data:

    • Combines the existing image data (IDAT) with the content file data.
    • Ensures the content does not exceed the image's pixel-based storage capacity (width * height bytes limit). If the content size is too large, the program exits with an error.
    • If the content is a zip file or similar archive, it "fixes up" the internal offsets in the zip to account for the new location within the PNG file.
  5. Fixing Embedded Zip Offsets:

    • If the file being embedded is a zip (or has a zip-like extension such as .jar), the function fixup_zip() is used to adjust the zip archive's internal offsets.
    • This ensures the zip remains functional even as part of the PNG file.
    • Adjustments include fixing the "End of Central Directory" marker and recalculating offsets for file headers inside the zip to reflect their new position.
  6. Writes to Output:

    • The processed chunks are written to the output file (output.png), with the combined IDAT chunk containing both the original image data and the embedded content.
    • Chunks are written following the PNG file format specification, including their types, lengths, and CRC checksums.
  7. Output:

    • The result is a PNG file (output.png) that looks and functions as a normal PNG image but secretly contains extra embedded data. If the content file is a valid zip, the embedded zip can still be extracted using tools such as unzip.

Applications:

  • This technique is a type of steganography or data-hiding method.
  • It can be used for hiding arbitrary data inside a PNG file in a way that's not immediately apparent.
  • Specific use cases include combining an image with hidden archives (zip), storing metadata, or creating hybrid files.
Generate your own explanations
Download our vscode extension
Read other generated explanations

Built by @thebuilderjr
Sponsored by beam analytics
Read our terms and privacy policy
Forked from openai-quickstart-node