Определение модификации PDF: как это работает и где метод не работает
Вопрос звучит просто: был ли этот PDF-файл отредактирован после создания? На практике определение модификации PDF требует понимания того, как формат хранит историю изменений на уровне байтов — и почему любой подход к детекции имеет принципиальные ограничения.
В этой статье разберём технику бинарного анализа PDF: какие сигналы ищем, почему они надёжны, где метод даёт ложные срабатывания, а где оказывается бессилен.
Почему это нетривиально
Большинство форматов файлов при сохранении изменений перезаписывают себя целиком. PDF — нет.
Стандарт PDF предусматривает механизм incremental save: при редактировании большинство редакторов не переписывают файл, а дописывают изменения в конец. Оригинальное тело остаётся нетронутым. Новые или изменённые объекты добавляются после маркера %%EOF. Затем — новая таблица перекрёстных ссылок (xref), новый трейлер с указателем на предыдущую xref-таблицу, ещё один %%EOF.
Это решение принято намеренно: incremental save ускоряет работу с большими файлами, поддерживает историю изменений и необходим для корректной работы цифровых подписей. Но это же оставляет в файле явный структурный след.
PDF с несколькими секциями %%EOF, несколькими xref-таблицами и трейлером с полем /Prev был сохранён больше одного раза. Это не означает автоматически, что файл подделан, но однозначно означает: файл изменяли после первоначального создания.
Структура PDF: что нас интересует
Для понимания детекции нужна базовая карта формата. PDF-файл состоит из четырёх компонентов:
Заголовок — версия формата (
%PDF-1.7)Тело — набор пронумерованных объектов: страницы, шрифты, изображения, метаданные
Таблица перекрёстных ссылок (xref) — индекс, отображающий номера объектов в байтовые смещения
Трейлер — указывает на xref-таблицу и корневой объект документа
Минимальный трейлер выглядит так:
trailer
<<
/Size 42
/Root 1 0 R
/Info 2 0 R
>>
startxref
9876
%%EOF
/Info указывает на информационный словарь документа — там хранятся метаданные.
Метаданные PDF: информационный словарь как свидетель
Словарь /Info содержит поля, описывающие происхождение и историю документа:
Поле | Значение |
|---|---|
| Дата и время создания документа |
| Дата и время последнего изменения |
| Приложение, создавшее исходный документ (например, Microsoft Word) |
| PDF-библиотека или инструмент, сгенерировавший PDF (например, macOS Quartz PDFContext) |
| Автор документа |
| Заголовок документа |
Даты кодируются в формате:
D:20231015143022+03'00'
То есть: 2023-10-15 в 14:30:22, UTC+3. Смещение часового пояса важно — вернёмся к этому ниже.
Разница между Creator и Producer — ключевая для детекции. Когда пользователь создаёт документ в Microsoft Word и экспортирует в PDF:
Creator = Microsoft Word
Producer = Microsoft Word (или внутренний PDF-движок Word)
Когда затем кто-то открывает этот PDF в Adobe Acrobat и редактирует:
Creator = Microsoft Word (сохранился из оригинала)
Producer = Adobe Acrobat 23.0 (инструмент, записавший новую версию)
Это несоответствие — сильный сигнал модификации.
Что конкретно проверяет детектор при определении модификации PDF
Надёжный инструмент комбинирует несколько независимых сигналов.
1. Анализ временных меток
Очевидная проверка: ModDate позже CreationDate? Если да — файл изменяли. Но есть нюансы:
ModDate == CreationDateне означает отсутствие правок. Многие редакторы сбрасываютModDateв значениеCreationDate, чтобы скрыть модификацию.ModDateраньшеCreationDate— физически невозможная ситуация, прямое указание на вмешательство в метаданные.Разные часовые пояса в
CreationDateиModDate(например, создание в+03'00', изменение вZ) говорят о том, что файл был изменён на другой машине или другим инструментом.
Важная деталь реализации: некоторые PDF-генераторы (например, Aspose.PDF) устанавливают CreationDate при инициализации объекта, а ModDate — при вызове Save(). Разница может составлять несколько секунд для совершенно легитимного файла. Порог в 15 секунд — разумный компромисс.
2. Анализ xref-таблиц
Количество xref-секций показывает количество операций сохранения:
1 xref-секция: файл сохранён ровно один раз — типично для свежеэкспортированных PDF
2+ секции: файл изменялся минимум один раз после создания
3+ секции: несколько итераций редактирования
Важен и состав изменений: если среди обновлённых объектов фигурирует словарь /Info, это означает, что метаданные были изменены после создания документа.
3. Несоответствие Creator/Producer
Поддерживается база данных известных PDF-инструментов с ожидаемыми комбинациями. Некоторые несоответствия не вызывают подозрений:
Creator: Word + Producer: Adobe PDF Printer → нормально, Word напечатал в PDF
Creator: Google Docs + Producer: Skia/PDF → стандартный экспорт Google Docs
Подозрительные комбинации:
Creator: Microsoft Excel + Producer: iLovePDF → файл обработан онлайн-редактором
Creator: LibreOffice + Producer: Adobe Acrobat → файл открыт и пересохранён в Acrobat
Creator: (пусто) + Producer: FPDF → программная генерация, возможно реконструированный документ
Отдельный паттерн — инструменты с известной историей использования в мошеннических схемах: определённые онлайн-редакторы и утилиты с функциями очистки истории.
4. Целостность цифровых подписей
PDF поддерживает криптографические цифровые подписи (объекты /Sig). Подпись покрывает конкретные байтовые диапазоны файла. При изменении:
Если контент вне покрытых диапазонов изменён — подпись недействительна.
Если объект подписи удалён и документ пересохранён — история ревизий фиксирует факт её предыдущего присутствия.
5. Аномалии объектных потоков
PDF 1.5+ поддерживает сжатые объектные потоки. Легитимные PDF-генераторы создают согласованные, корректно сформированные потоки. Проверяемые аномалии:
Объекты с непоследовательными номерами поколений (generation numbers)
Изолированные объекты, недостижимые из корневого объекта документа
Объекты, существующие в xref-таблице, чьи байтовые смещения указывают на объекты другого типа — признак попытки частичной перезаписи
Взвешенный скоринг
Ни один сигнал не является однозначно определяющим. Документ с ModDate > CreationDate может быть совершенно легитимным. Документ с совпадающими временными метками — подделанным инструментом, который их сбрасывает.
Пример весовой таблицы:
Сигнал | Вес | Обоснование |
|---|---|---|
Несколько xref-секций | Высокий | Трудно подделать без знания формата |
Несоответствие Creator/Producer с известным редактором | Средне-высокий | Встречается и в легитимных сценариях |
Невозможная дата | Высокий | Никогда не бывает легитимным |
Совпадение дат при наличии других сигналов | Средний | Требует комбинации признаков |
Producer из категории инструментов с историей злоупотреблений | Средний | Контекстно-зависимо |
Удалённая цифровая подпись | Высокий | Сильный индикатор постподписочной модификации |
Результат выше порога → вердикт «Modified». Ниже порога → зависит от происхождения: PDF от потребительских инструментов (Word, LibreOffice, Google Docs, print-to-PDF) получают «Cannot Verify» — создать документ с нуля этими инструментами не требует никаких технических навыков, проверка целостности лишена смысла. Прочие документы получают «Intact».
Ложные срабатывания: когда неизменённый PDF выглядит изменённым
Конвертация в PDF/A модифицирует файловую структуру. ModDate будет отличаться от CreationDate, даже если содержимое не изменилось.
Добавление цифровой подписи — это само по себе модификация. Подписанный после создания документ покажет несколько xref-секций, хотя содержимое нетронуто.
Оптимизация инструментами типа Ghostscript или функцией «Уменьшить размер файла» в Acrobat перезаписывает весь файл, сбрасывая xref-структуру, но потенциально сохраняя старые временные метки. Возникают несоответствия структуры и метаданных.
Корпоративные print-workflow — некоторые enterprise-системы переобрабатывают PDF при отправке: добавляют водяные знаки, штампы соответствия. Содержимое аутентично, структура — изменена.
Объединение и разбивка PDF — PDFtk, iLovePDF и аналоги создают новый документ с новым Producer и потенциально несогласованными метаданными из исходных файлов.
Ложные отрицания: когда изменённый PDF выглядит оригинальным
Более опасный сценарий.
Полная реконструкция через print-to-PDF. Самый простой способ обхода: открыть изменённый PDF и распечатать в PDF. Результат — совершенно новый файл: свежая xref-структура, согласованные временные метки, единственная чистая ревизия. Все следы истории уничтожены. Ни один инструмент это не обнаружит.
Зачистка метаданных. exiftool и аналоги могут перезаписать все поля метаданных, включая временные метки и сведения об инструменте. Грамотный фальсификатор устанавливает CreationDate = ModDate и задаёт Producer, соответствующий ожидаемому оригинальному инструменту.
Редактирование исходного документа. Если у фальсификатора есть доступ к исходнику (например, к docx-файлу), он изменяет источник и экспортирует в PDF заново. В полученном PDF нет следов модификации — он был создан заново из изменённого источника.
Специализированные инструменты реконструкции PDF. Разбирают изменённый PDF и пересобирают как чистый однобайтовый файл, стирая всю историю incremental save.
Фундаментальное ограничение: бинарная детекция работает со структурой файла, а не с содержимым. Мы можем обнаружить, что структура файла показывает признаки модификации, но не можем проверить, верны ли числа или текст. Достаточно квалифицированный фальсификатор, понимающий внутренности PDF, обойдёт структурную детекцию полностью.
Реализация: ключевые моменты
Для разработчиков, которые строят аналогичный инструментарий:
Библиотеки:
pdf-lib (JavaScript/Node.js) — парсинг PDF-структуры, чтение xref-таблиц, доступ к объектным потокам
PyMuPDF / fitz (Python) — комплексный анализ, поддержка большинства версий PDF
pdfminer.six (Python) — низкоуровневый доступ к внутренностям PDF
iTextSharp (.NET) — коммерческого уровня, хорошо справляется с повреждёнными файлами
Базовый алгоритм:
Парсинг xref-таблицы (таблиц) — подсчёт ревизий
Извлечение словаря
/Info— сравнение временных меток, анализ Creator/ProducerОбход цепочки xref через указатели
/Prev— определение, какие объекты изменились между ревизиямиПроверка объектов
/Sig— наличие цифровой подписи и охватываемые диапазоныСкоринг каждого сигнала — взвешивание и объединение
Сложность реализации — обработка некорректных PDF. Реальные документы регулярно нарушают спецификацию. Необходимо уметь обрабатывать:
Отсутствующие или повреждённые xref-таблицы (PDF-ридеры используют режим восстановления)
Линеаризованные PDF (другая структура для веб-оптимизированных файлов)
Зашифрованные PDF (метаданные могут быть доступны даже при недоступности содержимого)
PDF 2.0 с новыми структурными возможностями
Вывод
Бинарная детекция модификаций PDF — надёжная эвристика, а не криптографическое доказательство. Она отвечает на вопрос «показывает ли структура этого файла признаки изменения?» с высокой точностью для повседневных случаев документального мошенничества. Против квалифицированного противника, понимающего внутренности PDF, структурной детекции в одиночку недостаточно.
Результат имеет три состояния:
Intact — признаков модификации не обнаружено
Modified — модификация выявлена
Cannot Verify — PDF создан потребительским инструментом (Word, LibreOffice, print-to-PDF); подделка с этими инструментами не требует технических знаний, проверка целостности не имеет смысла
Критическое ограничение, применимое ко всем трём результатам: инструмент обнаруживает постсоздательные модификации, а не документы, сфабрикованные с нуля. Фиктивная банковская выписка, набранная в Word и экспортированная в PDF, получит статус Intact — потому что создана заново, а не изменена. Проверка отвечает на вопрос «был ли файл изменён после генерации», а не «правдиво ли содержимое».
Честный ответ на вопрос «был ли этот PDF отредактирован?»: мы можем сказать, что показывает структура файла. Для большинства случаев мошенничества — изменённые счета-фактуры, подделанные банковские выписки, фальсифицированные договоры — этого достаточно.