Вопрос звучит просто: был ли этот PDF-файл отредактирован после создания? На практике определение модификации PDF требует понимания того, как формат хранит историю изменений на уровне байтов — и почему любой подход к детекции имеет принципиальные ограничения.

В этой статье разберём технику бинарного анализа PDF: какие сигналы ищем, почему они надёжны, где метод даёт ложные срабатывания, а где оказывается бессилен.


Почему это нетривиально

Большинство форматов файлов при сохранении изменений перезаписывают себя целиком. PDF — нет.

Стандарт PDF предусматривает механизм incremental save: при редактировании большинство редакторов не переписывают файл, а дописывают изменения в конец. Оригинальное тело остаётся нетронутым. Новые или изменённые объекты добавляются после маркера %%EOF. Затем — новая таблица перекрёстных ссылок (xref), новый трейлер с указателем на предыдущую xref-таблицу, ещё один %%EOF.

Это решение принято намеренно: incremental save ускоряет работу с большими файлами, поддерживает историю изменений и необходим для корректной работы цифровых подписей. Но это же оставляет в файле явный структурный след.

PDF с несколькими секциями %%EOF, несколькими xref-таблицами и трейлером с полем /Prev был сохранён больше одного раза. Это не означает автоматически, что файл подделан, но однозначно означает: файл изменяли после первоначального создания.


Структура PDF: что нас интересует

Для понимания детекции нужна базовая карта формата. PDF-файл состоит из четырёх компонентов:

  1. Заголовок — версия формата (%PDF-1.7)

  2. Тело — набор пронумерованных объектов: страницы, шрифты, изображения, метаданные

  3. Таблица перекрёстных ссылок (xref) — индекс, отображающий номера объектов в байтовые смещения

  4. Трейлер — указывает на xref-таблицу и корневой объект документа

Минимальный трейлер выглядит так:

trailer
<<
  /Size 42
  /Root 1 0 R
  /Info 2 0 R
>>
startxref
9876
%%EOF

/Info указывает на информационный словарь документа — там хранятся метаданные.


Метаданные PDF: информационный словарь как свидетель

Словарь /Info содержит поля, описывающие происхождение и историю документа:

Поле

Значение

/CreationDate

Дата и время создания документа

/ModDate

Дата и время последнего изменения

/Creator

Приложение, создавшее исходный документ (например, Microsoft Word)

/Producer

PDF-библиотека или инструмент, сгенерировавший PDF (например, macOS Quartz PDFContext)

/Author

Автор документа

/Title

Заголовок документа

Даты кодируются в формате:

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) — коммерческого уровня, хорошо справляется с повреждёнными файлами

Базовый алгоритм:

  1. Парсинг xref-таблицы (таблиц) — подсчёт ревизий

  2. Извлечение словаря /Info — сравнение временных меток, анализ Creator/Producer

  3. Обход цепочки xref через указатели /Prev — определение, какие объекты изменились между ревизиями

  4. Проверка объектов /Sig — наличие цифровой подписи и охватываемые диапазоны

  5. Скоринг каждого сигнала — взвешивание и объединение

Сложность реализации — обработка некорректных PDF. Реальные документы регулярно нарушают спецификацию. Необходимо уметь обрабатывать:

  • Отсутствующие или повреждённые xref-таблицы (PDF-ридеры используют режим восстановления)

  • Линеаризованные PDF (другая структура для веб-оптимизированных файлов)

  • Зашифрованные PDF (метаданные могут быть доступны даже при недоступности содержимого)

  • PDF 2.0 с новыми структурными возможностями


Вывод

Бинарная детекция модификаций PDF — надёжная эвристика, а не криптографическое доказательство. Она отвечает на вопрос «показывает ли структура этого файла признаки изменения?» с высокой точностью для повседневных случаев документального мошенничества. Против квалифицированного противника, понимающего внутренности PDF, структурной детекции в одиночку недостаточно.

Результат имеет три состояния:

  • Intact — признаков модификации не обнаружено

  • Modified — модификация выявлена

  • Cannot Verify — PDF создан потребительским инструментом (Word, LibreOffice, print-to-PDF); подделка с этими инструментами не требует технических знаний, проверка целостности не имеет смысла

Критическое ограничение, применимое ко всем трём результатам: инструмент обнаруживает постсоздательные модификации, а не документы, сфабрикованные с нуля. Фиктивная банковская выписка, набранная в Word и экспортированная в PDF, получит статус Intact — потому что создана заново, а не изменена. Проверка отвечает на вопрос «был ли файл изменён после генерации», а не «правдиво ли содержимое».

Честный ответ на вопрос «был ли этот PDF отредактирован?»: мы можем сказать, что показывает структура файла. Для большинства случаев мошенничества — изменённые счета-фактуры, подделанные банковские выписки, фальсифицированные договоры — этого достаточно.