Последнее обновление: 16 сент., 2026

PPTX Reverse Engineering: Understanding PowerPoint Files Internally

Обратный Инжиниринг файлов PPTX: Руководство для разработчиков

Современные презентационные наборы поддерживают всё — от презентаций для инвесторов до внутренних квартальных метрик. Но если вам когда‑нибудь приходилось программно извлекать текст, заменять шаблоны во время выполнения, создавать автоматические генераторы слайдов или очищать конфиденциальные презентации, вы, вероятно, быстро поняли следующее: стандартные высокоуровневые библиотеки для работы с презентациями могут ощущаться как непредсказуемый «чёрный ящик».

Когда такие библиотеки, как python-pptx, Apache POI или OpenXML SDK, достигают своих пределов — или вводят недокументированные ошибки макета — единственный выход — пройти сквозь них. Вам необходимо понять, что собой представляет презентация PowerPoint на уровне байтов и схемы.

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

1. Что такое файл .pptx на самом деле?

По сути, файл .pptx не является проприетарным монолитным бинарным файлом, как древний формат .ppt 1990‑х годов. С тех пор как Microsoft представила Office Open XML (ECMA‑376 и ISO/IEC 29500), современные документы Office являются архивами Open Packaging Conventions (OPC).

Простыми словами: файл .pptx — это просто zip‑архив, содержащий XML‑документы и медиа‑ресурсы, организованные в детерминированное дерево каталогов.

Вы можете доказать это за секунды, используя стандартные инструменты терминала:

# Rename the extension and unpack it
cp presentation.pptx presentation.zip
unzip presentation.zip -d presentation_unpacked/
cd presentation_unpacked/
tree -L 2

Получившееся дерево каталогов выглядит удивительно согласованно:

.
├── [Content_Types].xml
├── _rels/
│   └── .rels
├── docProps/
│   ├── app.xml
│   └── core.xml
└── ppt/
    ├── presentation.xml
    ├── _rels/
    ├── slides/
    ├── slideLayouts/
    ├── slideMasters/
    ├── theme/
    └── media/

Каждый отдельный визуальный ресурс, переход, наследование шаблона слайда, координаты текстового поля и векторная графика закодированы в этой иерархии файлов.

2. Структура пакета: ключевые подсистемы

Чтобы эффективно проводить обратный инжиниринг презентаций, вы должны понимать функции каждого компонента верхнего уровня.

[Content_Types].xml

Это манифест входа для читателя OPC. Он сопоставляет расширения файлов и явные внутренние имена частей со стандартными типами MIME/контента. Если вы создаёте новый слайд или добавляете изображение и не укажете его в [Content_Types].xml, PowerPoint объявит набор повреждённым и предложит восстановление.

Пример фрагмента:

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="xml" ContentType="application/xml"/>
  <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
  <Default Extension="png" ContentType="image/png"/>
  <Override PartName="/ppt/presentation.xml" 
            ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>
</Types>

Граф отношений _rels/

Одна из самых важных концепций в OpenXML — непрямой доступ через отношения. Части редко указывают напрямую на сырые пути к файлам. Вместо этого файл (например, slide1.xml) имеет связанный файл отношений, расположенный в соседней папке _rels (например, _rels/slide1.xml.rels).

Отношения определяют:

  • Гиперссылки (r:id="rId2", TargetMode=“External”)
  • Изображения и аудиодорожки, хранящиеся в ppt/media/
  • Указатели наследования макета (slideLayout1.xml)
  • Слайды заметок, комментарии и встроенные шрифты

docProps/ (Метаданные)

  • core.xml: метаданные Dublin Core — автор, заголовок, дата создания, метка времени изменения.
  • app.xml: специфическая для приложения статистика — версия PowerPoint, общее количество слайдов, количество скрытых слайдов, количество слов, имена шаблонов презентаций.

ppt/ (Движок презентаций)

Здесь находится фактическая презентация:

  • presentation.xml: Главный каркас. Он регистрирует идентификаторы слайдов, размеры слайдов, ссылки на мастер заметок и настройки шрифта по умолчанию.
  • slides/: Отдельные слайды (slide1.xml, slide2.xml и т.д.).
  • slideLayouts/: Предустановки основной структуры (Титульный слайд, Два столбца, Заголовок раздела).
  • slideMasters/: Глобальные стили, палитры по умолчанию, фоновые заливки и наследование заполнителей.
  • theme/: Цветовые палитры (акцент 1‑6, тёмные/светлые варианты) и схемы шрифтов (основные/второстепенные шрифты).
  • media/: Исходные изображения (PNG, JPEG, SVG), аудио и видеофайлы.

3. Разбор слайда: диалекты PresentationML (p:) & DrawingML (a:)

Когда вы открываете ppt/slides/slide1.xml, вы сталкиваетесь с двумя основными XML‑пространствами имён:

  1. PresentationML (p:): Управляет структурными элементами презентации (слайды, древовидные структуры фигур, группы холста).
  2. DrawingML (a:): Управляет типографикой, геометрией, 2‑мерными координатами, градиентными заливками и векторным рендерингом.

Ниже приведён упрощённый пример того, как выглядит стандартная текстовая фигура:

<p:sp>
  <!-- 1. Non-visual shape properties (Identifiers, names) -->
  <p:nvSpPr>
    <p:cNvPr id="4" name="Title Box 1"/>
    <p:cNvSpPr>
      <a:spLocks noGrp="1"/>
    </p:cNvSpPr>
    <p:nvPr>
      <p:ph type="title"/>
    </p:nvPr>
  </p:nvSpPr>

  <!-- 2. Visual shape properties (Position, size, geometry) -->
  <p:spPr>
    <a:xfrm>
      <a:off x="1524000" y="1143000"/>
      <a:ext cx="9144000" cy="1828800"/>
    </a:xfrm>
    <a:prstGeom prst="rect">
      <a:avLst/>
    </a:prstGeom>
    <a:solidFill>
      <a:schemeClr val="accent1"/>
    </a:solidFill>
  </p:spPr>

  <!-- 3. Text Body (Paragraphs, runs, styling) -->
  <p:txBody>
    <a:bodyPr rtlCol="0" anchor="ctr"/>
    <a:lstStyle/>
    <a:p>
      <a:r>
        <a:rPr lang="en-US" sz="3200" b="1"/>
        <a:t>Mission Critical Architecture</a:t>
      </a:r>
    </a:p>
  </p:txBody>
</p:sp>

Ключевые единицы измерения: EMU и сотые доли пункта

Обратите внимание на числовые координаты в <a:xfrm>:

  • x="1524000"
  • cx="9144000"

Это английские метрические единицы (EMUs).

  • $1 \text{ inch} = 914,400 \text{ EMUs}$
  • $1 \text{ см} = 360,000 \text{ EMUs}$
  • $1 \text{ пт} = 12,700 \text{ EMUs}$

EMUs позволяют использовать целые числа для точного представления дробей как дюймов, так и миллиметров без ошибок округления с плавающей точкой на разных аппаратных архитектурах.

Обратите также внимание на размер шрифта:

  • sz="3200" означает 32.00 пт. Размеры шрифтов в DrawingML измеряются в сотых долях пункта.

4. Цепочка наследования: почему фигуры наследуют невидимые стили

Одной из самых распространённых ловушек при обратном проектировании файлов PPTX является предположение, что визуальное оформление фигуры полностью объявлено внутри её собственного slideX.xml.

На самом деле OpenXML опирается на строгую четырёхуровневую каскадную модель наследования:

[Theme: ppt/theme/theme1.xml]
[Slide Master: ppt/slideMasters/slideMaster1.xml]
[Slide Layout: ppt/slideLayouts/slideLayout1.xml]
[Slide: ppt/slides/slide1.xml]

Если текстовое поле в slide1.xml содержит:

<a:p>
  <a:r>
    <a:t>Revenue Projections</a:t>
  </a:r>
</a:p>

Для запуска (<a:r>) не указаны семейство шрифтов, явный цвет и размер. Чтобы понять, как PowerPoint отображает этот текст, ваш парсер должен:

  1. Определите тип заполнителя (<p:ph type="title"/>).
  2. Прочитайте макет, указанный в slide1.xml.rels.
  3. Проверьте, предоставляет ли slideLayout1.xml переопределения стилей для этого заполнителя.
  4. Обратитесь к slideMaster1.xml для получения стилей текста заголовка по умолчанию.
  5. Отследите цветовые токены, такие как accent1 или tx1, в theme1.xml, чтобы найти шестнадцатеричный код цвета.

Если вы пропустите эту графу наследования, ваш парсер неправильно прочитает стили, пропустит шрифты, размеры шрифтов и привязки макета.

5. Практический процесс обратного проектирования

Когда необходимо исследовать, как работает конкретная функция PowerPoint изнутри (например, морф‑переходы, сложные таблицы, векторные пути), следуйте этому эмпирическому подходу:

Шаг 1: Создать минимальную “Пару различий”

  1. Откройте PowerPoint и создайте пустой слайд.
  2. Сохраните его как before.pptx.
  3. Внесите точное единственное изменение, которое вы хотите проанализировать (например, добавьте теневой эффект к кругу, измените стиль маркера, вставьте встроенное видео).
  4. Сохраните его как after.pptx.

Шаг 2: Распаковать оба архива

unzip before.pptx -d before/
unzip after.pptx -d after/

Шаг 3: Форматировать XML

Сырой XML внутри архивов Office обычно лишён отступов и символов новой строки. Перед сравнением отформатируйте файлы:

find before/ after/ -name "*.xml" -exec xmllint --format {} --output {} \;

Шаг 4: Выполнить объединённый diff

diff -uNr before/ after/ > changes.patch

Просмотр changes.patch показывает точное имя тега, атрибут пространства имён и иерархию контейнеров, которые добавил PowerPoint. Это самый быстрый способ обнаружить недокументированные или малоизвестные свойства схемы без необходимости просматривать тысячи страниц документации ECMA-376.

6. Создание пользовательского микродвижка: распаковать, изменить, упаковать заново

Иногда вам не нужна тяжёлая корпоративная зависимость, такая как Apache POI или Microsoft OpenXML SDK — особенно в лёгких безсерверных средах выполнения (AWS Lambda, Cloudflare Workers, edge‑узлы).

Ниже приведён автономный пример на Python, демонстрирующий, как безопасно распаковать PPTX в памяти, внедрить пользовательские данные с помощью стандартных библиотек и упаковать его обратно:

import zipfile
import io
import xml.etree.ElementTree as ET

def modify_slide_title(input_pptx_bytes: bytes, new_title: str) -> bytes:
    input_zip = zipfile.ZipFile(io.BytesIO(input_pptx_bytes))
    output_buffer = io.BytesIO()
    
    with zipfile.ZipFile(output_buffer, "w", zipfile.ZIP_DEFLATED) as output_zip:
        for item in input_zip.infolist():
            content = input_zip.read(item.filename)
            
            # Target slide 1
            if item.filename == "ppt/slides/slide1.xml":
                namespaces = {
                    'p': 'http://schemas.openxmlformats.org/presentationml/2006/main',
                    'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'
                }
                
                # Register namespaces to preserve prefixes
                for prefix, uri in namespaces.items():
                    ET.register_namespace(prefix, uri)
                    
                root = ET.fromstring(content)
                
                # Find title placeholder text run
                for title_run in root.findall(".//p:sp[p:nvSpPr/p:nvPr/p:ph[@type='title']]//a:t", namespaces):
                    title_run.text = new_title
                    break
                
                content = ET.tostring(root, encoding="utf-8", xml_declaration=True)
            
            output_zip.writestr(item, content)
            
    return output_buffer.getvalue()

Ключевые подводные камни при модификации файлов на уровне необработанных байтов:

  1. Сохранение пространств имён: XML‑парсеры часто переписывают префиксы (xmlns:p может стать xmlns:ns0). Хотя это валидный XML, строгая внутренняя проверка схемы PowerPoint иногда отклоняет нестандартные псевдонимы префиксов. Регистрируйте пространства имён явно.
  2. Методы сжатия ZIP: Убедитесь, что вы записываете файлы обратно, используя стандартное сжатие deflate (zipfile.ZIP_DEFLATED).
  3. Сброс потока: Всегда проверяйте, что ваш zip‑буфер закрывается и полностью сбрасывается перед передачей байтов дальше.
  4. Сохранение связей: Если вы удаляете слайд, необходимо также удалить его запись из ppt/presentation.xml, удалить его связь в ppt/_rels/presentation.xml.rels и очистить его тип содержимого из [Content_Types].xml.

7. Соображения производительности и безопасности

Реверс‑инжиниринг файлов PPTX — это не только редактирование слайдов; это также аудит того, что попадает в ваши системы.

Безопасность: Миллиард Смехов и XXE

Поскольку файлы PPTX парсят XML, любой серверный конвейер, принимающий пользовательские презентации, уязвим к:

  • Внедрение внешних сущностей XML (XXE): Зловредный XML, пытающийся получить доступ к /etc/passwd или выполнить запрос к внутренним конечным точкам метаданных облака (http://169.254.169.254/).
  • Атаки расширения сущностей (Billion Laughs): Экспоненциальные циклы сущностей, исчерпывающие оперативную память системы.

Смягчение: Всегда отключайте resolve_entities, load_dtd и разрешение внешних сетевых запросов в вашем XML‑парсере (например, используя defusedxml в Python).

Безопасность: Макросные полезные нагрузки и скрытые потоки

Проверяйте файлы на наличие содержимого .pptm под расширением .pptx. Обращайте внимание на ppt/vbaProject.bin, который содержит скомпилированный код Visual Basic. В стандартных файлах .pptx код VBA запрещён; обнаружение ссылок на бинарные полезные нагрузки в отношениях должно немедленно вызвать флаги карантина.

Заключение

Обратный инжиниринг файлов .pptx раскрывает тайны программ для презентаций. Как только вы поймёте, что файлы PowerPoint — это просто структурированные zip‑пакеты, заполненные координатами, ссылками на схемы и деревьями XML‑отношений, вы больше не будете ограничены существующими сторонними абстракциями.

Независимо от того, оптимизируете ли вы пропускную способность генерации слайдов, пишете пользовательские автоматические санитайзеры или устраняете сбои рендеринга, прямой взгляд на базовую архитектуру OpenXML предоставляет вам полный контроль над конвейером презентаций.

Часто задаваемые вопросы (FAQ)

**Q: Можно ли преобразовать .pptx в обычную папку и редактировать файлы напрямую в IDE?

A1: Да, вы можете извлечь архив, отредактировать XML в редакторе, таком как VS Code, и снова упаковать содержимое каталога в zip, чтобы открыть его в PowerPoint.

**Q: Почему PowerPoint сообщает, что мой вручную изменённый файл PPTX нуждается в ремонте?

A2: Это обычно происходит, если вы ввели некорректный XML, пропустили новый ресурс в файле [Content_Types].xml или оставили висячую ссылку в связанном файле .rels.

**Q: Какую единицу измерения использует PowerPoint для позиций фигур и отступов?

A3: PowerPoint использует английские метрические единицы (EMUs), где 1 дюйм равен 914,400 EMU, а 1 пункт — 12,700 EMU.

**Q: Как я могу программно извлечь все изображения из презентации без внешних библиотек?

A4: Просто откройте файл .pptx любой стандартной утилитой zip и извлеките все бинарные файлы, находящиеся в каталоге ppt/media/.

**Q: Безопасно ли разбирать загруженные пользователями файлы PPTX с помощью стандартных XML‑парсеров?

A5: Нет, вам необходимо укрепить ваш парсер или использовать безопасные обёртки, такие как defusedxml, чтобы блокировать атаки XML External Entity (XXE) и zip‑бомбы.

См. также