Skip to content

Instantly share code, notes, and snippets.

@karmanyaahm
Last active April 4, 2023 02:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karmanyaahm/03025089054fa4568bc47eb14d1aff51 to your computer and use it in GitHub Desktop.
Save karmanyaahm/03025089054fa4568bc47eb14d1aff51 to your computer and use it in GitHub Desktop.
PNG Text Polyglot generator, insert tEXt chunk into PNG using Python (made for micropython/circuitpython, so it conserves memory and has minimal dependencies)
# Minimum index is 1, the IHDR block MUST be first for a valid PNG
# this assumes the skipped blocks aren't very large, so it reads the whole block into memory at once, beware of setting index to more than 1
# The script is also read into memory so don't make it too large
def insert_text_chunk(filein, fileout, text, index = 1):
from binascii import crc32
from struct import pack, unpack
with open(filein, 'rb') as fin, open(fileout, 'wb') as fout:
fout.write(fin.read(8)) # PNG Header
# skip blocks
for _ in range(index):
fout.write(block_len := fin.read(4))
block_len = unpack(">I", block_len)[0] # Len of IHDR BLOCK
fout.write(fin.read(block_len + 4 + 4)) # + for CRC and Type
#insert text block
# type, label null, newline to start script, script, newline to cleanly finish just cuz
script_block = b'tEXt\0\n' + open('script.ps1','rb').read() + b'\n'
block_len = len(script_block) - 4 # Len doesn't include type but CRC does because of course bloody hell
crc = crc32(script_block)
fout.write(pack(">I", block_len))
fout.write(script_block)
fout.write(pack(">I", crc))
# copy rest of the file in chunks of 100 to reduce memory consumption
while fout.write(fin.read(100)):
pass
if __name__ == '__main__':
import sys
insert_text_chunk(sys.argv[1],sys.argv[2], '\0\n' + open(sys.argv[3]).read(), 1)
@karmanyaahm
Copy link
Author

For example, you can use this to hide a PowerShell or Bash script in a PNG, and then run the script using cat output.png | powershell or similar, while it will look like an image to laypeople.

@karmanyaahm
Copy link
Author

BTW you can run it like this

python polyglot.py oreo-from.png oreo.png script.ps1

@karmanyaahm
Copy link
Author

Also 010 editor's script really helped me debug and understand the PNG file format while making this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment