如何提取追加到PNG文件中的二进制数据?

4

似乎如果我将二进制数据追加到png文件的末尾,该png文件仍然可以查看。因此,该png文件仍然是一个有效的文件。有没有办法从未记录原始文件大小的png文件中自动提取这样的尾随数据?


我不知道如何在命令行上执行此操作(您可能需要在superuser.com上提问,因为这是一个工具请求,而不是特定的编程问题),但规范足够详细。详见 - Jongware
有没有办法将问题迁移到超级用户? - user1424739
如果你在这里删除并在那边发布一个新的,会更快。 - Jongware
我不明白规范中如何确定有多少块以及如何确定原始文件大小。你能告诉我在哪里可以找到这些信息吗? - user1424739
无论有多少块,"IEND [...]应该是最后一个"(表5.3)。每个块的大小在其本身中定义。 - Jongware
2个回答

6

PNG文件以"IEND"块结束。最后的12个字节总是相同的。因此,您可以尝试使用以下内容:

dd if=appended.png of=extracted.png bs=1 count=$((($(od -t x1 appended.png | awk '{$1=""}1' | tr -d \\n | sed "s/00 00 00 00 49 45 4e 44 ae 42 60 82/XMATCHX/" | tr X \\n  | grep -b MATCH | cut -f1 -d:)-2)/3+12))

以上内容比在MacOS上工作所需的内容要长一些,因为MacOS处理grep -b的方式与GNU grep不同。其要点如下:
  • 使用dd从appended.png的开头提取count字节
  • 通过以下步骤确定count数:
    • 使用od/awk/tr将文件转换为一个带有空格分隔字节的十六进制字符串
    • 使用sed/tr搜索IEND模式并用MATCH替换
    • 使用grep -bcut获取MATCH的偏移量
    • 计算实际的文件长度(减去额外的空格/ CR,除以每个字节的3个十六进制字符/空格,加上12个IEND长度)
注意:很少情况下(如果不是不可能),12字节的IEND块会出现在PNG中,但上述内容没有对此进行检查。
这是一个有趣的冠状病毒锻炼 — 谢谢!

3
你可以运行 pngcheck -v YOURFILE.png 命令,它会告诉你文件末尾是否有额外的字节,并以错误状态 2 退出。
它也会告诉你实际的文件结尾在哪里:
# Generate legitimate PNG with ImageMagick
convert -size 300x400 gradient:yellow-red orig.png

# Check its size
ls -l orig.png
-rw-r--r--  1 mark  staff  2509  3 May 17:47 orig.png

# Check it with `pngcheck` - exit status = 0, i.e. all ok
    File: orig.png (2509 bytes)
  chunk IHDR at offset 0x0000c, length 13
    300 x 400 image, 48-bit RGB, non-interlaced
  chunk gAMA at offset 0x00025, length 4: 0.45455
  chunk cHRM at offset 0x00035, length 32
    White x = 0.3127 y = 0.329,  Red x = 0.64 y = 0.33
    Green x = 0.3 y = 0.6,  Blue x = 0.15 y = 0.06
  chunk bKGD at offset 0x00061, length 6
    red = 0xffff, green = 0xffff, blue = 0xffff
  chunk IDAT at offset 0x00073, length 2276
    zlib: deflated, 32K window, maximum compression
  chunk tEXt at offset 0x00963, length 37, keyword: date:create
  chunk tEXt at offset 0x00994, length 37, keyword: date:modify
  chunk IEND at offset 0x009c5, length 0
No errors detected in orig.png (8 chunks, 99.7% compression).

现在在末尾添加一些无用的内容:

ls -l >> orig.png

# Check the size again
ls -l orig.png
-rw-r--r--  1 mark  staff  8398  3 May 17:53 orig.png

# And check again - exit status =2
pngcheck -v orig.png
File: orig.png (8398 bytes)
  chunk IHDR at offset 0x0000c, length 13
    300 x 400 image, 48-bit RGB, non-interlaced
  chunk gAMA at offset 0x00025, length 4: 0.45455
  chunk cHRM at offset 0x00035, length 32
    White x = 0.3127 y = 0.329,  Red x = 0.64 y = 0.33
    Green x = 0.3 y = 0.6,  Blue x = 0.15 y = 0.06
  chunk bKGD at offset 0x00061, length 6
    red = 0xffff, green = 0xffff, blue = 0xffff
  chunk IDAT at offset 0x00073, length 2276
    zlib: deflated, 32K window, maximum compression
  chunk tEXt at offset 0x00963, length 37, keyword: date:create
  chunk tEXt at offset 0x00994, length 37, keyword: date:modify
  chunk IEND at offset 0x009c5, length 0
  additional data after IEND chunk
ERRORS DETECTED in orig.png

它还会告诉你文件的真正结尾在倒数第三行,即在0x009c5处。您需要将其加8以允许IEND本身的大小。 顺便说一下,如果您使用macOS,可以使用homebrew安装pngcheck:
brew install pngcheck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接