- Регистрация
- 19.09.18
- Сообщения
- 189
- Реакции
- 82
- Репутация
- 1
Всем привет.
В 1948 году американское следствие по делу Алджера Хисса опиралось на любопытное доказательство: документы, напечатанные на конкретной машинке. У каждой пишущей машинки есть собственные дефекты: чуть сдвинутая литера, особенность в оттиске, неровность в строке. Эксперты сопоставили шрифт документов с машинкой Хиссов и решили, что дело в одной и той же машине. Защита ответила гипотезой о подделке, и спор о том, можно ли такой почерк воспроизвести, не утих и десятилетия спустя.
Цифровые изображения оставляют такие следы на нескольких уровнях сразу, и большинство людей, зачищающих «метаданные», работает лишь с верхним. Ниже я разберу, что остаётся в файле после удаления EXIF, откуда это берётся и как это увидеть.
Слои отпечатка
Фотография это не только пиксели и EXIF. Из неё можно вытянуть информацию на шести уровнях.
Таблицы квантования
JPEG теряет часть информации по таблице: 64 числа для яркости и 64 для цвета, на которые делятся коэффициенты. Чем больше число, тем грубее сохраняется эта частота. Таблицы лежат в файле, чтобы декодер мог всё развернуть обратно, и именно поэтому они всегда видны.
У библиотеки libjpeg есть стандартная таблица, которая масштабируется по «качеству» от 1 до 100. Масштаб для качества выше 50 равен 200 минус удвоенное качество, для меньшего значения 5000 делить на качество. Каждое число таблицы умножается на масштаб, делится на 100 и округляется. Отсюда известные следствия: первая строка стандартной яркостной таблицы 16 11 10 16 24 40 51 61 при качестве 75 превращается в 8 6 5 8 12 20 26 31. Любой инструмент на libjpeg при таком качестве даст ровно эти числа.
Но многие производители не используют стандартные таблицы. Камеры, телефоны, Photoshop, веб-службы и мессенджеры нередко применяют свои собственные, подобранные под их задачи. Эксперты по криминалистике изображений описали это ещё в 2000-х: по таблицам можно определить, прошло ли изображение через конкретный редактор, камеру или сервис. Это не точный отпечаток одного устройства, а отпечаток семейства, но в сочетании с остальными признаками картина сужается быстро.
Есть и вторая особенность, о которой мало говорят. При повторном сжатии в файле остаётся статистический след предыдущего: в гистограммах коэффициентов DCT появляются характерные периодические провалы. Метод называют обнаружением двойного сжатия, и он показывает, что картинку пересохраняли, а часто и с какими параметрами она сжималась в первый раз. Так что одной зачистки таблиц мало: если пиксели уже побывали в сжатии, это видно.
Посмотреть таблицы просто. В Python: Image.open("a.jpg").quantization из Pillow выдаёт словарь с тремя-четырьмя таблицами. Ещё identify -format "%Q" a.jpg оценивает «качество», и если число получилось нестандартным или таблицы не совпадают с libjpeg, значит, тут работал другой кодировщик.
Структура файла
Помимо таблиц, у кодировщика есть привычки. Какие используются таблицы Хаффмана (стандартные или оптимизированные), как задана субдискретизация цвета (4:4:4, 4:2:2, 4:2:0), базовый ли это JPEG или прогрессивный, есть ли restart-маркеры, в каком порядке идут сегменты APPn и есть ли заголовок JFIF, Exif или оба. Сама последовательность блоков уже подпись. Камеры, редакторы и библиотеки укладывают их по-разному.
Среди сегментов есть те, о которых забывают. APP1 несёт EXIF и XMP, в APP2 лежат ICC-профиль и данные Multi-Picture Format, в APP13 данные Photoshop. Внутри XMP бывает история правок и идентификаторы документа (DocumentID, InstanceID, OriginalDocumentID), которые связывают разные версии одного изображения между собой, даже если пиксели менялись.
ICC-профиль
Профиль описывает цветовое пространство. Многие смартфоны Apple встраивают профиль Display P3, а многие другие устройства и сервисы sRGB. Профиль, его имя, версия и контрольная сумма уже признак: по ним нередко можно отличить платформу и конвейер обработки. Скриншоты на macOS обычно несут профиль монитора, а значит, иногда и название экрана.
Интересная деталь: если ты удаляешь профиль без конвертации в sRGB, цвета на изображении смещаются, и тот, кто смотрит на него, видит, что картинку «чистили», а нестандартный размер или цветовой сдвиг дополнительно выделяет файл среди остальных.
Миниатюры и всё, что лежит внутри
В EXIF обычно встроена уменьшенная копия изображения. Известная ошибка: редактор обрезает или закрашивает часть снимка, а миниатюру не обновляет, и в файле остаётся уменьшенный оригинал. Старые случаи с утечками закрашенных фрагментов именно из такого рода.
Ещё интереснее хвост файла. Некоторые телефоны дописывают после маркера конца изображения дополнительные данные: видеоклип для «живых фото», карту глубины, карту усиления для HDR, служебные блоки производителя. Отдельная известная уязвимость acropalypse (CVE-2023-21036 в Google Pixel Markup, подобная ей в Windows Snipping Tool): отредактированный файл записывался поверх старого без усечения, и после конца нового изображения оставался хвост исходного.
Проверка: exiftool -a -G1 -s файл.jpg покажет все блоки, а предупреждение о лишних данных после конца JPEG сразу укажет на хвост. Извлечь миниатюру: exiftool -b -ThumbnailImage файл.jpg > t.jpg. Для поиска вложенных файлов подойдёт binwalk файл.jpg.
Шум матрицы (PRNU)
Самый глубокий отпечаток находится в самих пикселях. Фотоматрица каждого экземпляра камеры имеет микроскопические неоднородности чувствительности пикселей, и они образуют стабильный паттерн шума. В 2006 году Лукаш, Фридрих и Голян показали, что по нему снимки связываются с конкретной камерой с высокой достоверностью: усредняя шумовые остатки множества снимков, получают «отпечаток» устройства, а затем сравнивают его с шумом спорного изображения.
Главное, что отличает PRNU от остального: он живёт в содержимом. Удаление метаданных на него не действует. Паттерн ослабляется при сильном сжатии, масштабировании и обрезке, но не исчезает полностью, а в исследованиях по контрмерам описаны как способы стирания отпечатка, так и способы его подделки. Надёжность разных приёмов зависит от условий, и полагаться на единичный способ нельзя.
Путь файла
Последний слой это следы, оставленные путём. Мессенджер перекодирует изображение, и результат несёт отпечаток его конвейера: новые таблицы, новый размер, иногда характерные артефакты. Если отправить файл как документ, а не как фото, он сохранится без изменений вместе со всеми блоками. Скриншот передаёт отпечаток экрана и программы. Всё, что прошло через несколько сервисов, накапливает следы каждого.
Что с этим делать
Зачистка метаданных утилитой удаляет только верхний слой. Для остальных нужен другой подход: декодировать до пикселей и закодировать заново чистым кодировщиком.
Грубая схема на ImageMagick:
magick in.jpg -auto-orient -profile sRGB.icc -strip \<br> -interlace None -sampling-factor 4:2:0 -quality 85 out.jpg<br>
Порядок существенен: сначала применить ориентацию (после очистки её информация пропадёт), потом перевести цвета в sRGB по встроенному профилю, и лишь затем убрать профиль, иначе цвета сместятся. Мозаику параметров подбирай так, чтобы они совпадали с самой распространённой конфигурацией, а не с экзотической: необычная комбинация сама становится уникальным признаком.
Для шума матрицы помогают изменение размера на нецелый коэффициент, обрезка, умеренное пересжатие, а наиболее радикальный путь вывести изображение через физический носитель: печать и сканирование заменяют отпечаток камеры на отпечаток сканера. Ни один из этих способов не гарантирует результата против серьёзного анализа.
После любой чистки проверь итог тем же инструментом, которым смотрел исходник. Сделай exiftool -a -G1 -s на выходном файле, сравни таблицы через Pillow, убедись, что нет хвоста и миниатюры. Нельзя считать файл чистым, пока не прочитал его так, как прочитал бы наблюдатель.
Об ограничениях
Все эти методы вероятностные. Совпадение таблиц говорит о типе конвейера, а не о конкретном человеке. PRNU требует образцов с той же камеры, а значит, опасен для того, у кого они есть. Но множество анонимности здесь работает так же, как везде: каждый особый признак вычитает биты из толпы. Если твои изображения всегда проходят один и тот же необычный конвейер, они связаны между собой, даже когда по отдельности безымянны.
Поэтому правило звучит так: не пытайся стереть себя, а постарайся выглядеть как самая обычная картинка из самого обычного конвейера, и не смешивай этот конвейер между разными личностями. Хисс был пойман машинкой, которая отличалась от остальных. Побеждает тот, кто ничем не отличается.
В 1948 году американское следствие по делу Алджера Хисса опиралось на любопытное доказательство: документы, напечатанные на конкретной машинке. У каждой пишущей машинки есть собственные дефекты: чуть сдвинутая литера, особенность в оттиске, неровность в строке. Эксперты сопоставили шрифт документов с машинкой Хиссов и решили, что дело в одной и той же машине. Защита ответила гипотезой о подделке, и спор о том, можно ли такой почерк воспроизвести, не утих и десятилетия спустя.
Цифровые изображения оставляют такие следы на нескольких уровнях сразу, и большинство людей, зачищающих «метаданные», работает лишь с верхним. Ниже я разберу, что остаётся в файле после удаления EXIF, откуда это берётся и как это увидеть.
Слои отпечатка
Фотография это не только пиксели и EXIF. Из неё можно вытянуть информацию на шести уровнях.
- Контейнер: порядок и состав служебных блоков.
- Кодировщик: таблицы квантования, таблицы Хаффмана, цветовая субдискретизация.
- Цвет: встроенный ICC-профиль.
- Вложения: миниатюры, превью, история правок, чужие данные в хвосте файла.
- Матрица камеры: шум датчика.
- Путь файла: что с ним делали после съёмки.
Таблицы квантования
JPEG теряет часть информации по таблице: 64 числа для яркости и 64 для цвета, на которые делятся коэффициенты. Чем больше число, тем грубее сохраняется эта частота. Таблицы лежат в файле, чтобы декодер мог всё развернуть обратно, и именно поэтому они всегда видны.
У библиотеки libjpeg есть стандартная таблица, которая масштабируется по «качеству» от 1 до 100. Масштаб для качества выше 50 равен 200 минус удвоенное качество, для меньшего значения 5000 делить на качество. Каждое число таблицы умножается на масштаб, делится на 100 и округляется. Отсюда известные следствия: первая строка стандартной яркостной таблицы 16 11 10 16 24 40 51 61 при качестве 75 превращается в 8 6 5 8 12 20 26 31. Любой инструмент на libjpeg при таком качестве даст ровно эти числа.
Но многие производители не используют стандартные таблицы. Камеры, телефоны, Photoshop, веб-службы и мессенджеры нередко применяют свои собственные, подобранные под их задачи. Эксперты по криминалистике изображений описали это ещё в 2000-х: по таблицам можно определить, прошло ли изображение через конкретный редактор, камеру или сервис. Это не точный отпечаток одного устройства, а отпечаток семейства, но в сочетании с остальными признаками картина сужается быстро.
Есть и вторая особенность, о которой мало говорят. При повторном сжатии в файле остаётся статистический след предыдущего: в гистограммах коэффициентов DCT появляются характерные периодические провалы. Метод называют обнаружением двойного сжатия, и он показывает, что картинку пересохраняли, а часто и с какими параметрами она сжималась в первый раз. Так что одной зачистки таблиц мало: если пиксели уже побывали в сжатии, это видно.
Посмотреть таблицы просто. В Python: Image.open("a.jpg").quantization из Pillow выдаёт словарь с тремя-четырьмя таблицами. Ещё identify -format "%Q" a.jpg оценивает «качество», и если число получилось нестандартным или таблицы не совпадают с libjpeg, значит, тут работал другой кодировщик.
Структура файла
Помимо таблиц, у кодировщика есть привычки. Какие используются таблицы Хаффмана (стандартные или оптимизированные), как задана субдискретизация цвета (4:4:4, 4:2:2, 4:2:0), базовый ли это JPEG или прогрессивный, есть ли restart-маркеры, в каком порядке идут сегменты APPn и есть ли заголовок JFIF, Exif или оба. Сама последовательность блоков уже подпись. Камеры, редакторы и библиотеки укладывают их по-разному.
Среди сегментов есть те, о которых забывают. APP1 несёт EXIF и XMP, в APP2 лежат ICC-профиль и данные Multi-Picture Format, в APP13 данные Photoshop. Внутри XMP бывает история правок и идентификаторы документа (DocumentID, InstanceID, OriginalDocumentID), которые связывают разные версии одного изображения между собой, даже если пиксели менялись.
ICC-профиль
Профиль описывает цветовое пространство. Многие смартфоны Apple встраивают профиль Display P3, а многие другие устройства и сервисы sRGB. Профиль, его имя, версия и контрольная сумма уже признак: по ним нередко можно отличить платформу и конвейер обработки. Скриншоты на macOS обычно несут профиль монитора, а значит, иногда и название экрана.
Интересная деталь: если ты удаляешь профиль без конвертации в sRGB, цвета на изображении смещаются, и тот, кто смотрит на него, видит, что картинку «чистили», а нестандартный размер или цветовой сдвиг дополнительно выделяет файл среди остальных.
Миниатюры и всё, что лежит внутри
В EXIF обычно встроена уменьшенная копия изображения. Известная ошибка: редактор обрезает или закрашивает часть снимка, а миниатюру не обновляет, и в файле остаётся уменьшенный оригинал. Старые случаи с утечками закрашенных фрагментов именно из такого рода.
Ещё интереснее хвост файла. Некоторые телефоны дописывают после маркера конца изображения дополнительные данные: видеоклип для «живых фото», карту глубины, карту усиления для HDR, служебные блоки производителя. Отдельная известная уязвимость acropalypse (CVE-2023-21036 в Google Pixel Markup, подобная ей в Windows Snipping Tool): отредактированный файл записывался поверх старого без усечения, и после конца нового изображения оставался хвост исходного.
Проверка: exiftool -a -G1 -s файл.jpg покажет все блоки, а предупреждение о лишних данных после конца JPEG сразу укажет на хвост. Извлечь миниатюру: exiftool -b -ThumbnailImage файл.jpg > t.jpg. Для поиска вложенных файлов подойдёт binwalk файл.jpg.
Шум матрицы (PRNU)
Самый глубокий отпечаток находится в самих пикселях. Фотоматрица каждого экземпляра камеры имеет микроскопические неоднородности чувствительности пикселей, и они образуют стабильный паттерн шума. В 2006 году Лукаш, Фридрих и Голян показали, что по нему снимки связываются с конкретной камерой с высокой достоверностью: усредняя шумовые остатки множества снимков, получают «отпечаток» устройства, а затем сравнивают его с шумом спорного изображения.
Главное, что отличает PRNU от остального: он живёт в содержимом. Удаление метаданных на него не действует. Паттерн ослабляется при сильном сжатии, масштабировании и обрезке, но не исчезает полностью, а в исследованиях по контрмерам описаны как способы стирания отпечатка, так и способы его подделки. Надёжность разных приёмов зависит от условий, и полагаться на единичный способ нельзя.
Путь файла
Последний слой это следы, оставленные путём. Мессенджер перекодирует изображение, и результат несёт отпечаток его конвейера: новые таблицы, новый размер, иногда характерные артефакты. Если отправить файл как документ, а не как фото, он сохранится без изменений вместе со всеми блоками. Скриншот передаёт отпечаток экрана и программы. Всё, что прошло через несколько сервисов, накапливает следы каждого.
Что с этим делать
Зачистка метаданных утилитой удаляет только верхний слой. Для остальных нужен другой подход: декодировать до пикселей и закодировать заново чистым кодировщиком.
Грубая схема на ImageMagick:
magick in.jpg -auto-orient -profile sRGB.icc -strip \<br> -interlace None -sampling-factor 4:2:0 -quality 85 out.jpg<br>
Порядок существенен: сначала применить ориентацию (после очистки её информация пропадёт), потом перевести цвета в sRGB по встроенному профилю, и лишь затем убрать профиль, иначе цвета сместятся. Мозаику параметров подбирай так, чтобы они совпадали с самой распространённой конфигурацией, а не с экзотической: необычная комбинация сама становится уникальным признаком.
Для шума матрицы помогают изменение размера на нецелый коэффициент, обрезка, умеренное пересжатие, а наиболее радикальный путь вывести изображение через физический носитель: печать и сканирование заменяют отпечаток камеры на отпечаток сканера. Ни один из этих способов не гарантирует результата против серьёзного анализа.
После любой чистки проверь итог тем же инструментом, которым смотрел исходник. Сделай exiftool -a -G1 -s на выходном файле, сравни таблицы через Pillow, убедись, что нет хвоста и миниатюры. Нельзя считать файл чистым, пока не прочитал его так, как прочитал бы наблюдатель.
Об ограничениях
Все эти методы вероятностные. Совпадение таблиц говорит о типе конвейера, а не о конкретном человеке. PRNU требует образцов с той же камеры, а значит, опасен для того, у кого они есть. Но множество анонимности здесь работает так же, как везде: каждый особый признак вычитает биты из толпы. Если твои изображения всегда проходят один и тот же необычный конвейер, они связаны между собой, даже когда по отдельности безымянны.
Поэтому правило звучит так: не пытайся стереть себя, а постарайся выглядеть как самая обычная картинка из самого обычного конвейера, и не смешивай этот конвейер между разными личностями. Хисс был пойман машинкой, которая отличалась от остальных. Побеждает тот, кто ничем не отличается.




