为什么这个 435 × 652 像素的 JPEG 超过 6 MB?

信息安全 取证 混淆 隐写术
2021-09-07 02:42:11

这是,在有人看到这个问题后帮助修复它之前,一张相对不起眼​​且很小的 ̶f̶i̶s̶h̶ nudibranch 照片,像素为 283,620。它有一些元数据:文本 Exif 标签以及 8.6kB 的颜色配置文件信息,以及 5,557 字节的缩略图以及 648,534 字节的预览图像(我无法阅读)和其他一些随机的东西(如人脸检测区域)占用空间小。

使用

exiftool -a -b -W %d%f_%t%-c.%s -u -g1 -ee -api RequestAll=3 temp.jpg

提取总共 <650kiB 的东西。

是否有任何策略或工具可用于发现正在发生的事情以及文件中是否隐藏了某些内容?

如果它使事情变得更容易,相同或非常相似的包含似乎会影响同一个 Flickr 用户的多个文件:2345

4个回答

简短回答:这是Nikon Picture Project的神器

我很难找到“Nikon Picture Project”,但最终找到了一个 1.5 版本来尝试。生成的最后一个版本是 1.7.6 。

事实证明,“尼康图片计划”确实实现了具有撤消和版本控制功能的无损编辑。与我见过的所有其他照片编辑软件不同,它通过直接更改 JPG 文件结构并直接在 JPG 中嵌入编辑控件和版本来实现这一点。软件中有一个导出 JPEG功能,可以展平和删除历史记录,但看起来像是发布了原生 munged JPG,而不是使用导出。

我加载了您的第一个参考图像(在此处调整大小)

参考.

果然,“尼康图片计划”将其显示为一张更大图片的编辑和裁剪(在此处调整大小)

原来的.

检查之前和之后的文件结构可以验证奇怪的工件。

感谢您的拼图!😎

这并不像起初看起来那么有趣。用户可能只是相机损坏、存储卡损坏或照片编辑软件出现故障,无法保存全分辨率图像,但能够保存各种尺寸的工作缩略图,包括 435 × 652 “原始”图片。

您的示例图片的文件大小由 4032 × 3024 像素和 5,47 MB​​ JPEG 流解释,该流已损坏并按比例缩小,如下所示:

破碎的图像按比例缩小

它从FF D8SOI(图像开始)开始:

从 HxD 开始的图像

并以FF D9EOI(图像结束)结束:

来自 HxD 的图像结尾

同一张图片还有另外一张不同的破损 1920 × 1440 缩略图和这张破损图片的缩略图,但如果灰色中隐藏了一些有趣的东西,它在006A4F和之间5812A2但是,我不会打赌。

正如其他评论者所提到的,该文件包含来自 Nikon Picture Project 的数据。如果您无法运行该软件,但您仍想知道其中隐藏的内容怎么办?

Nikon 的 Picture Project 格式似乎完全没有文档记录,这并不奇怪,因为它是特定应用程序的自定义格式,并且从未设计用于交换。也就是说,格式似乎非常简单,可以通过检查FF EA二进制文件中嵌入的 APP10 块(标签)来辨别。我使用以下代码使用 Hachoir(一种通用文件解析工具)查看了这些块:

from hachoir.parser.image.jpeg import JpegFile
from hachoir.stream import FileInputStream
import struct

p = JpegFile(FileInputStream('20200519221417!Goniobranchus_aureomarginatus_2.jpg'))
for i in p.array('chunk'):
    print(i['data'].value[:100].hex())

只需像这样排列所有块,就会立即看到模式:

4e696b6f6e20496d61676520496e666f000200000001f00000618396ffd8ffdb0084000101010101010101010101010101010201010101010202020102020202020202020202030303020303030202030403030304040404020304040404040304040401
4e696b6f6e20496d61676520496e666f000200000002f000bdcc1b6d3b9c535cb2bf520b2bff00340964d84ab6dc03cb7bf3c8ce6bd5bc1fae18562188d5e194bb9597040e36820f5e99e4f7fad7979b41bfebe67a5867785cf6e1e30c5b6e92621d8ef6
4e696b6f6e20496d61676520496e666f000200000003f000e0753fe7debf986355e1d34cfea696b17639dfb088ae1434600070a0fe7c57456f6931450a62507e47431072c3af04e3079af2b1152cf9bab65538dd5999b77a32f9991103d4739ce49e7eb5
4e696b6f6e20496d61676520496e666f000200000004f0000948036296da18e4e78e2bd98d292a577bbfebf1382b452bdcd28ef448cd8904a91a95f2cae368ee73d4fad4134b0ac68e082cd2336d033839ea7fbd9cf35c9384bda5dbd422a37b1fffd3fc
4e696b6f6e20496d61676520496e666f000200000005f000aa47dbc746ce9c2569c612aab7b9ffd3fcc2d67c0bf1b3e2d7c42bff00106972b695e0fd1ef46a1e25d7a4dc16360f84b7deea57730380b9dd5f6b7876730e8b6d664bce2c20581e590e7715
4e696b6f6e20496d61676520496e666f000200000006f000a0aa5a99ffd1fc2e5bb3ba2937c46471fc07210e73f89ae82c6e0163299631b8e58e793827afeb5fcc74aa3a57b1fd758cf7a3a1e8fa19230102b051921864306e7b9f7af54b1558e18dc310
4e696b6f6e20496d61676520496e666f000200000007f0009ddd707f957e974e7f5887b56f563a10743961d57e274be1ed7fed266b4b53219236659f703b78273863c139eb8ef5da695aba5a6b3610ddc2f3594ab219f6b0c162328727d0f6ef5e0d6c23
4e696b6f6e20496d61676520496e666f000200000008f000375ab993f790cd188651874393939cee0dd7a6411f4ae7478836811db4eac9972c4e41f94fcc416e5b9e01afa4861a528b99e34a6a261ea1e2268edc012399d0923692d9dc4920fe679ae12f
4e696b6f6e20496d61676520496e666f000200000009f000cd6fc7e6ee6de32bf75492727be7f0e6bf8be10536dbef73fb25c6317643f50958d9b9190318720124d73ba5c71c97af15e42df67b88c46252721893cf07ebfcfd2b2745467ccf7b9e950925
4e696b6f6e20496d61676520496e666f00020000000af000b0f9659df1b0f5c903a9c73f98aee03c5344b0c368bf31cf981f25f3fdecd44b1156524e5b1e156a692777a9c77882e65b547b60db6220b9dbd171ea7b579aa91a8de189519b24072b260e72
4e696b6f6e20496d61676520496e666f00020000000bf000d4fceeb5d124f262789d622cfb08924cf24e7a1e6bad8b462234ce245fe251b8063cf39afe48c5d48ceab6fccfe9ba5074e96a6c59db3c0ca8f1b850a18b2938662581e7f0fd6ba9b5b958fe
...
4e696b6f6e20496d61676520496e666f000200000068f0001acec0e2a791b919b9d91fffd6c432c611ce79c71594cf1cb202d8241af9849ec7b37b97ed648e59d60de067a8cd67f8816350d120048ef4a707a32a9cd5ec729a4de8d1b53576190c7a1af4
4e696b6f6e20496d61676520496e666f00020000006903960f515ce93b9d6e57d0cfbb94953c74eb58372df31e7f0ae983b239ea22a32a95e4d4ba7a057c139ad5dec713dcffd7f8f6f13692cc7807818a8609c4732b7615e7ad51dcb73a55bd82e60f9c
4e696b6f6e20496d61676520496e666f00030000000100000bbb0bbb40a9867a1be9d211a90a00aa00b1c1b70200a90b00000032a476a217d411a90a00aa00b1c1b70100050000000161512be4df5dd211a90a00aa00b1c1b7020005000000000132a476

我们可以看到有一个固定的标头(4e696b6f6e20496d61676520496e666f:Nikon Image Info在 ASCII 中),然后是0002or 0003,然后是一个递增的数字(从 开始00000001和结束00000069),最后是某种长度字段(f000对于大多数块,除了最后两个, 其中有03960000)。之后它看起来像数据。

所以,我猜标题是这样的:

uint16_t chunktype;
uint16_t unknown; /* always zero */
uint16_t serial;
uint16_t datasize;
uint8_t payload[];

然后将所有有效负载位转储到文件中:

out = open('dump.bin', 'wb')
for i in p.array('chunk'):
    data = i['data'].value
    magic, ctype, unknown, serial, size = struct.unpack('>16sHHHH', data[:24])
    print(magic, ctype, serial, size, len(data[24:]))
    chunk = data[24:24+size]
    out.write(chunk)

生成的文件以四个字节00 61 83 96(0x618396) 开头,与数据的总长度 (0x618396 = 6390678 字节) 匹配。接下来是FF D8 FF DBJPEG 的开头,因此去掉长度字段会显示 4032x3024 JPEG。这大概是相机的原始照片。这是照片,调整大小以适应上传限制:

第一张图片 - 4032x3024

Hachoir 之旅表明 JPEG 在结构上非常正常,但它已被剥离所有元数据。奇怪的是,Hachoir 还显示它在 5742120 字节之后结束。在结束后转储数据会显示第二个JPEG,大小为 1920x1440:

第二张图片 - 1920x1440

可悲的是,这不是一些令人兴奋的间谍东西,它只是原始图片的另一个版本,但有些缩小了。不过,它仍然比实际裁剪的照片数据大得多!这次最后什么都没有了,所以我们从文件中提取了所有的图像。

剩下的就是最后一块数据,它有 3008 字节长。这个块似乎包含实际的图片项目信息,大概包括编辑历史,详细的编辑信息等。格式更不规则,虽然我认识不少双精度浮点数和一些看起来像的东西幻数 ( 65 D4 11 D1 91 94 44 45 53 54)。再做一些工作,也应该可以对这些块进行逆向工程——但这里似乎没有隐藏任何有趣的东西:)

它没有损坏,只是充满了 APP10 段,包含某种特定于应用程序的数据。可能是尼康特有的,因为开头的 APP1/EXIF 段中有尼康参考。在大约 6 MB 的 APP10 段之后,有 103,001 字节的实际 JPEG 图像数据。但是所有分段标记都在正确的位置,这意味着它们显示在有效载荷长度之后,因此它似乎是具有 6 MB 尼康特定数据的有效图像:

Byte 0x00000000 (0): marker 0xD8 found: SOI (Start Of Image)

Byte 0x00000002 (2): marker 0xE1 found: APP1 (EXIF data)
        Payload length: 18523 bytes

Byte 0x00004861 (18529): marker 0xE2 found: APP2 (ICC profile)
        Payload length: 8650 bytes

Byte 0x00006A2F (27183): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 61468 bytes

Byte 0x00015A4F (88655): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 61464 bytes

Byte 0x00024A6B (150123): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 61464 bytes

(... this goes on and on, 6 MB of APP10 segments...)

Byte 0x00610577 (6358391): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 61464 bytes

Byte 0x0061F593 (6419859): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 942 bytes

Byte 0x0061F945 (6420805): marker 0xEA found: APP10 (Application marker 10)
        Payload length: 3032 bytes

Byte 0x00620521 (6423841): marker 0xDB found: DQT (Define Quantization Table)
        Payload length: 130 bytes

Byte 0x006205A7 (6423975): marker 0xC4 found: DHT (Define Huffman Table)
        Payload length: 168 bytes

Byte 0x00620653 (6424147): marker 0xC0 found: SOF0 (Start Of Frame (Baseline DCT))
        Payload length: 15 bytes

Byte 0x00620666 (6424166): marker 0xDA found: SOS (Start Of Scan)
        Reading image data... 103001 bytes read.

Byte 0x006398C1 (6527169): marker 0xD9 found: EOI (End Of Image)