Привет, Хабр!
Стеганография — искусство сокрытия информации — чаще всего ассоциируется с изображениями и аудиофайлами. Но что если нам нужно спрятать данные не в медиафайле, а в обычном офисном документе, например, в .docx
или .xlsx
?
На первый взгляд, задача кажется сложной. Документы имеют строгую структуру, и любое неосторожное изменение может повредить файл. Однако современные форматы Office, основанные на Open XML, предоставляют удивительно элегантные и надежные способы для встраивания сторонних данных.

В этой статье мы раскроем технологию, которая лежит в основе нашего приложения ChameleonLab. Мы разберем один из самых интересных методов — встраивание данных через Custom XML Parts, заглянем «под капот» формата .docx
и покажем, почему этот способ на порядок превосходит другие.
Почему не LSB? Краткий обзор методов для документов
Прежде чем перейти к нашему основному методу, давайте быстро рассмотрим, какие вообще существуют подходы к сокрытию данных в документах и почему многие из них не подходят для серьезных задач.
-
Метаданные файла. Поля «Автор», «Комментарии», «Теги» — самое очевидное место.
Минусы: Очень легко обнаружить. Вместимость крайне мала.
-
«Белый» текст. Сделать текст того же цвета, что и фон.
Минусы: Обнаруживается простым выделением всего текста (Ctrl+A).
-
Скрытие в неиспользуемых частях структуры. В сложных форматах вроде OLE (старые
.doc
) или PDF существуют неиспользуемые блоки, куда можно что-то записать.Минусы: Требует глубокого знания спецификаций. Высокий риск повредить файл.
-
Изменение наименее значимых бит в данных встроенных объектов. Например, LSB для картинок внутри документа.
Минусы: Работает, но это уже стеганография в изображениях, а не в самом документе.
Все эти методы либо ненадежны, либо легко обнаружимы. Нам нужен способ, который был бы одновременно вместительным, устойчивым к пересохранению и максимально незаметным. И такой способ есть.
Анатомия Open XML: DOCX — это ZIP-архив
Ключ к пониманию нашего метода лежит в устройстве современных офисных форматов (.docx
, .xlsx
, .pptx
). Это не монолитные бинарные файлы, а обычные ZIP-архивы, содержащие набор XML-файлов и ресурсов.
Вы можете убедиться в этом сами: просто возьмите любой .docx
файл, поменяйте его расширение на .zip
и распакуйте. Внутри вы увидите примерно такую структуру:
/
├── _rels/
│ └── .rels
├── word/
│ ├── _rels/
│ │ └── document.xml.rels
│ ├── document.xml
│ └── ...
└── [Content_Types].xml
[Content_Types].xml
— «оглавление» архива.word/document.xml
— основной файл, содержащий текст и структуру документа.Папки
_rels
— содержат файлы связей (relationships). Они говорят приложению (например, MS Word), как различные части документа связаны друг с другом, включая пользовательские XML-данные.
Именно последняя возможность нас и интересует. Спецификация Open XML позволяет встраивать в пакет произвольные XML-файлы (Custom XML Parts) и связывать их с основным документом. Эти данные не отображаются при просмотре, но сохраняются вместе с файлом. Идеальное место для наших «невидимых чернил»!
Технология ChameleonLab: встраивание данных в Custom XML
Наш подход заключается в следующем:
Распаковать исходный
.docx
во временную папку.Создать собственный XML-файл, содержащий секретные данные.
Добавить этот файл в структуру пакета в папку
customXml/
.Зарегистрировать наш файл в файле связей (
word/_rels/document.xml.rels
).Запаковать все обратно в ZIP-архив и вернуть ему расширение
.docx
.
И здесь кроется важнейший нюанс: нельзя просто добавить файл в ZIP-архив. Офисные приложения строго следуют «карте» документа, описанной в файлах связей (.rels
). Если какой-то файл физически присутствует в архиве, но не зарегистрирован должным образом, он будет в лучшем случае проигнорирован, а в худшем — приложение выдаст ошибку о повреждении документа. Именно поэтому ключевой шаг нашего алгоритма — это не столько добавление файла, сколько корректное обновление файла связей.
Давайте посмотрим на упрощенный пример кода, который демонстрирует этот принцип.
Пример логики встраивания
import zipfile
import shutil
import os
from xml.etree import ElementTree as ET
# Уникальные идентификаторы для данных
CUSTOM_XML_PART = 'customXml/item1.xml'
CUSTOM_SCHEMA_URI = 'https://schemas.chameleonlab.app/steganography/v1'
RELATIONSHIP_TYPE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml'
def embed_payload_example(src_path: str, dest_path: str, payload: bytes):
# ...
try:
# 1. Распаковываем исходный контейнер
with zipfile.ZipFile(src_path, 'r') as docx_zip:
docx_zip.extractall(temp_dir)
# 2. Создаем наш XML с полезной нагрузкой (в HEX)
payload_hex = payload.hex()
root = ET.Element('chameleonData', {'xmlns': CUSTOM_SCHEMA_URI})
root.text = payload_hex
# ... (сохраняем XML)
# 3. Редактируем файл связей (.rels) — САМЫЙ ВАЖНЫЙ ШАГ
rels_path = os.path.join(temp_dir, 'word/_rels/document.xml.rels')
# ... (код для парсинга и добавления новой связи)
new_rid = "rId99" # Пример
ET.SubElement(rels_root, 'Relationship', {
'Id': new_rid, 'Type': RELATIONSHIP_TYPE,
'Target': '../customXml/item1.xml'
})
# ... (сохраняем .rels)
# 4. Запаковываем все обратно
shutil.make_archive(dest_path_base, 'zip', temp_dir)
shutil.move(dest_path_base + '.zip', dest_path)
finally:
# ... (очистка)
Преимущества и недостатки метода Custom XML
Преимущества:
Полная совместимость: MS Office и другие редакторы открывают модифицированный файл без каких-либо ошибок или предупреждений, так как мы действуем строго в рамках стандарта Open XML.
Огромная вместимость: В отличие от других методов, здесь можно спрятать действительно большие объемы данных. Как сказано в документации нашего приложения, «метод встраивания в документы Office... позволяет скрыть файл практически любого размера. Ограничением является только свободное место на диске».
Надежность: Данные не теряются при открытии, редактировании и пересохранении документа.
Кроссплатформенность: Работает со всеми современными офисными пакетами.
Низкая обнаружимость: Стандартные средства не показывают наличие Custom XML.
Недостатки:
Обнаружимость при экспертизе: Эксперт, знающий об этой возможности, легко найдет кастомные XML-части, просто распаковав архив.
Не подходит для старых форматов: Метод не работает со старыми бинарными форматами вроде
.doc
или.xls
.
Насколько уникален этот метод? Аналоги в сети
Идея скрытия данных в OOXML не нова и обсуждалась в основном в академических кругах. Существуют и старые утилиты, реализующие похожие концепции, например, проект «Steganography for OfficeXML file» на SourceForge, датированный 2013 годом.
Однако в большинстве современных и популярных стеганографических инструментов эта функция отсутствует. Как правило, они фокусируются на медиафайлах.
Заключение
Сокрытие данных в офисных документах — это не магия, а грамотное использование возможностей самого формата. Метод Custom XML Parts представляет собой мощный и надежный способ стеганографии, который на порядок превосходит устаревшие подходы.
Мы в ChameleonLab реализовали эту технологию, чтобы предоставить пользователям удобный и надежный инструмент. Мы решили не открывать исходный код, сосредоточившись на развитии продукта как готового решения.

Наше приложение — это результат длительных исследований и разработок, и мы рады предложить его вам. Готовые сборки ChameleonLab уже доступны для Windows и macOS. Вы можете скачать их и опробовать все возможности, описанные в этой статье.
Скачать последнюю версию на macOS: ChameleonLab 1.3.0.0
Скачать последнюю версию на Windows: ChameleonLab 1.3.0.0
Telegram-канал: t.me/ChameleonLab
Будем рады вашим отзывам и вопросам в комментариях!
Комментарии (15)
Wesselloff
22.08.2025 22:39Какова цель вот этого всего?
Lomakn Автор
22.08.2025 22:39Цеть простая создать обучающий продукт по поиску скрытых данных и анализу
Lomakn Автор
22.08.2025 22:39Интересно узнать какие у кого есть идеи для формата PDF. Много способов перебрали, но к сожалению пока не получается реализовать.
RranAmaru
22.08.2025 22:39Только это ни разу не стеганография.
И, кстати, lsb - не единственный способ скрыть данные в картинке или звуке.
phaggi
22.08.2025 22:39Один знакомый, который работал в компании, где закачка исполняемых файлов с интернет была ограничена ИБшными сетевыми фильтрами, таким образом переправлял себе на офисный комп разные полезные утилитки. Даже скриптики написал, которые рубили бинарники на части, распихивали по вордовым документам, отправляли по почте, а на том конце собирали из почты и склеивали обратно.
IgnatF
22.08.2025 22:39А не проще было такие файлы просто переименовывать в ворд формат документики?
phaggi
22.08.2025 22:39Увы, нет. Современные системы ИБ легко читают заголовки присоединенных файлов, включая заархивированные и заююканные. А запароленные архивы просто выкусывают из писем.
IgnatF
22.08.2025 22:39да там не думаю что серьезные фильтры были. Про файлы архивы тут согласен. Убивать их нужно всех.
checkpoint
22.08.2025 22:39Еще можно добавить несуществующее поле в существующий тэг в каком нибудь document.xml и хранить в нём Base64-encoded данные. Проверил, работает, LibreOffice никаких сообщений об ошибке не выдает. Но после пересохранения документа все такие инородные поля ожидаемо пропадают.
phaggi
22.08.2025 22:39Ну кстати ничто не мешает положить base64 прям в текст документа, где-то с 13 страницы :))
slavcopost
Вайб-хакерство какое-то. Вот уж "сокрытие" данных, аналоговнет.
Lomakn Автор
Для macOS нет практически программ по стеганографии. У нас упор идет на анализ и поиск.
Wesha
Это ещё что! Тут не так давно на ту же тему была статья от Ыксперда-криминалиста, да простят меня понимающие в современных форматаx MS Office.
novoselov
Не знаю что там за обсуждение SourceForge от 2013 года, но мы еще 15 лет назад (начиная с Office 2007) использовали Custom XML Parts, чтобы хранить мета/данные в шаблонах документов. Приложение просто прописывало значения в xml и поля в шаблоне автоматически заполнялись в нужных местах документа. Воистину забытые технологии предыдущей цивилизации.