打开从 Android 应用程序中提取的非标准 PNG 文件 - 缺少签名和 IHDR 块

逆向工程 安卓 文件格式 apk
2021-06-20 08:34:23

我无法打开从某个 Android 应用程序中提取的 PNG 文件。我无法使用现有的 Android Gallery 应用程序打开它们。在我的计算机上下载它们后,我无法在图像浏览器中打开它们。使用 pngcheck 分析文件会导致this is neither a PNG or JNG image nor a MNG stream错误。

有问题的文件是用 apktool 提取的。直接从设备缓存中提取它们会导致同样的问题。

使用十六进制编辑器进行的进一步调查显示,这些文件缺少 PNG 签名和 IHDR 块,这些通常存在于有效的 PNG 文件中。

这是两个文件的标题和前几行:

41 6E 74 6D 02 C5 01 DB FB C3 AB 00 00 00 00 00 63 BA A4 AD E7 E0 F0 E0 EA EA EA E7 A3 A2 AE B8 EA EA EA AA EA EA EA AA E2 E9 EA EA EA 77 5D 6B 06 EA EA EA EE 8D AB A7 AB EA EA 5B 65 E1 16 8B EF EA EA EA EB 99 B8 AD A8 EA 44 24 F6 03 EA EA E8 8B BA A6 BE AF EB F3 EA EA E5 EA EA FE EA EB F1 EA 09 13 3F E8 F4 EB EA E0 EA 0A 12 38 EA F8 EA E8 CB EB 34 1D 25 EB FD EA 31 1C 26 05 11 0C 1F 17 07 EA CE EA 32 1F 22 3E 1E 2F EA EF EA EA 07 00 00 0C 00 E9 FB DD 00 6E 00 10 68 07 E4 F9 D7 05 24 02 01 6B 00 0B 43 05 00 09 00 00 30 00 00 28 00 07 34 03 18 9B 0B 0F 62 07 01 73 00 07 39 03 ED FC E3 0D 57 06 E7 FA DB 0C 52 05 13 70 08 F2 FD EA EB FB E0 E6 F9 D9 00 2C 00 08 7C 03 C1 EB B1 06 2C 03 07 30 03 A3 DF 95 01 50 00 0A 3E 04 0F 5C 07 11 78 07 10 8B 07 04 78 01 2D B8 ...

41 6E 74 6D 02 09 01 77 D9 ED AB 00 00 00 00 00 63 BA A4 AD E7 E0 F0 E0 EA EA EA E7 A3 A2 AE B8 EA EA EA 98 EA EA EA 98 E2 E9 EA EA EA 52 E9 9F A5 EA EA EA EE 8D AB A7 AB EA EA 5B 65 E1 16 8B EF EA EA EA EB 99 B8 AD A8 EA 44 24 F6 03 EA EA E9 EA BA A6 BE AF A6 83 9B 6F BF C6 6F BF C1 57 E2 ED 81 6A 22 02 C9 C9 9A D9 F5 68 29 1B 6E BC C1 6F 80 62 6C B9 C1 14 4A 4E 81 68 2D 53 9B D4 14 14 14 34 2D 3D 81 6B 23 B2 81 77 03 32 0B 68 C2 F0 AE DB F3 B7 99 AE CB A7 C3 3E BC BF ED 93 51 02 A3 00 B9 73 39 B0 6D 38 E0 CB DA FF FE FF CD A5 C5 C6 A1 BD 81 BF EE 2B 53 81 2D 56 86 84 0E 0A FE 5D 65 BB 96 B2 98 3C 50 25 4A 7A 79 41 2B E6 D6 E3 D2 15 15 FE 9C A2 83 4D 27 AF 8C A7 5A 41 26 B7 71 3D 32 65 A7 DE C9 D8 D0 11 10 D8 BF D1 CA 0A 09 CE 16 15 62 3B 29 83 68 85 CC A7 ...

相比之下,以下是有效 PNG 示例的开头:

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 50 00 00 00 50 08 06 00 00 00 ...

有趣的是,这两个文件都有 IDAT 和 IEND 块。

我只对查看文件感兴趣。我如何“修复”它们以便在普通图像查看器中打开它们?


编辑:我在周末玩了这些文件,得出了类似的结论。我决定完全专注于 IDAT 块。这是我到目前为止发现的。

我寻找00均匀间隔的字节。这使我能够找到相同大小的扫描线。

因为我知道 IDAT 块的完整大小和扫描线的数量(高度),所以我可以猜测像素的宽度和它们的布局。使用真彩色像素最终会得到过度拉伸的图像。使用灰度像素更有希望,但好吧,它是灰度 - 我对颜色文件感兴趣。

难道颜色是用调色板索引的?

2个回答

前 16 个字节未知(可能是某种私人数据)。之后是一个常规的 PNG 文件,但前 128 个字节已与值 234 进行异或运算。文件的其余部分不变。

我怀疑一个简单的 XOR 的原因是0xEA开头附近的一系列字节;通常那里会有零。在十六进制查看器中应用 XOR 立即显示熟悉的‰PNG签名,然后是缺失的IHDRPLTE,以及之前0xEA出现的一系列空值由于这一系列空值在中途更改为0xEA,这表明只有部分文件因此被遮挡。剩下的就是计算字节了。

因此,取消编码就像丢弃前 16 个字节一样简单,将接下来的 128 个字节与 234 进行异或,并原封不动地复制整个其余字节。

编码在理论上是可能的,但要使其起作用,您需要知道前 16 个字节的含义。(可能这些字节总是相同的,或者在某些方面有所不同。)

这是一个未编码形式的示例,“levelselect/map_1.png”:

随机选择的图像

由以下快速而肮脏的 Python 程序未编码:

import sys

if len(sys.argv) == 2:
  with open(sys.argv[1], 'rb') as orig:
    # skip first 16 bytes
    orig.seek(16)
    # read in the rest
    data = bytearray(orig.read())
    # xor first 128 bytes with 0xea
    for x in range(0,128):
      data[x] ^= 0xea
    # write to new file
    with open(sys.argv[1]+'.fixed.png', 'wb') as fixed:
      fixed.write(data)

(我没有在所有文件上测试这个例程。)

是的,这个有点时髦。我不确定 IDAT 块之前的内容是部分垃圾数据、某种压缩/加密的标头还是什么。他们都有自己的魔法(41 6E 74 6D 02),我四处寻找字节和文本(Antm,但我选择了Ant)。我遇到了这个,但我认为这只是巧合。

我尝试了一些事情,比如用来自少数其他 PNG 的字节(包括与分辨率相关的其他必要块等)替换 IDAT 之前的所有字节。我可以通过这样做看到结果,但图像尺寸、颜色等都关闭了。

您可能必须自己重建标题,并进行类似的操作。您知道文件中是否有相同大小的 PNG?您可以尝试像我在此处尝试使用随机 PNG 一样交换这些字节。

您可能也有一些运气将 GIMP 中的那些加载为原始图像数据。向下滚动到这篇文章中RAW 图像数据部分,看看你如何公平地使用宽度和高度滑块。您可能需要为这些文件使用来自另一个 PNG 的良好标题,这可能会给您错误的宽度/高度,但您可以使用滑块调整它们。

根据您在那里找到的内容,您可以尝试使用其他已记录的 PNG 格式的重建标头- 可能从关键块(这些文件中已有 2 个)开始。