Laatst bijgewerkt: 16 sept., 2026

Reverse Engineering PPTX Bestanden: Een gids voor ontwikkelaars
Moderne presentatiedeks drijven alles aan, van investeerderspitches tot interne kwartaalcijfers. Maar als je ooit programmatisch tekst moest extraheren, sjablonen tijdens runtime moest vervangen, geautomatiseerde dia-generatoren moest bouwen, of vertrouwelijke presentaties moest saneren, heb je waarschijnlijk al snel iets gerealiseerd: standaard high‑level presentatielibraries kunnen aanvoelen als een onvoorspelbare black box.
Wanneer bibliotheken zoals python-pptx, Apache POI of OpenXML SDK hun grenzen bereiken — of ongedocumenteerde lay-outbugs introduceren — is de enige uitweg erdoorheen. Je moet begrijpen wat een PowerPoint‑presentatie eigenlijk is op byte‑ en schema‑niveau.
In deze diepgaande duik zullen we het gordijn oplichten over het .pptx‑formaat, de interne structuur uitpakken, de relatiegrafiek volgen, de tekenhiërarchieën ontleden, en kijken naar praktische strategieën voor reverse engineering, inspectie en manipulatie van presentaties met ruwe code.
1. Wat is een .pptx-bestand echt?
In essentie is een .pptx-bestand geen propriëtair monolithisch binair bestand zoals het oude .ppt-formaat uit de jaren 90. Sinds Microsoft Office Open XML (ECMA-376 en ISO/IEC 29500) heeft geïntroduceerd, zijn moderne Office-documenten Open Packaging Conventions (OPC)-archieven.
In eenvoudige bewoordingen: een .pptx-bestand is simpelweg een zip-archief dat XML-documenten en media‑assets bevat, georganiseerd in een deterministische mapstructuur.
Je kunt dit in enkele seconden aantonen met standaard terminalgereedschap:
# Rename the extension and unpack it
cp presentation.pptx presentation.zip
unzip presentation.zip -d presentation_unpacked/
cd presentation_unpacked/
tree -L 2
De resulterende mapstructuur ziet er opmerkelijk consistent uit:
.
├── [Content_Types].xml
├── _rels/
│ └── .rels
├── docProps/
│ ├── app.xml
│ └── core.xml
└── ppt/
├── presentation.xml
├── _rels/
├── slides/
├── slideLayouts/
├── slideMasters/
├── theme/
└── media/
Elk afzonderlijk visueel asset, elke overgang, slide‑master‑overerving, tekstvakcoördinaat en vectorafbeelding is gecodeerd in deze bestandshiërarchie.
2. Anatomie van het pakket: belangrijke subsystemen
Om presentaties effectief te reverse‑engineeren, moet je de verantwoordelijkheden van elk top‑level component begrijpen.
[Content_Types].xml
Dit is het ingangsmanifest voor de OPC-lezer. Het koppelt bestandsextensies en expliciete interne onderdeelnamen aan gestandaardiseerde MIME-/contenttypes. Als je een nieuwe dia maakt of een afbeelding toevoegt en deze niet declareert in [Content_Types].xml, zal PowerPoint de presentatie als corrupt aangeven en om herstel vragen.
Voorbeeldfragment:
<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>
De _rels/ Relatiegrafiek
Een van de belangrijkste concepten in OpenXML is indirectie via relaties. Onderdelen verwijzen zelden rechtstreeks naar ruwe bestandspaden. In plaats daarvan heeft een bestand (bijv. slide1.xml) een bijbehorend relatiebestand dat zich bevindt in een broederlijke _rels map (bijv. _rels/slide1.xml.rels).
Relaties definiëren:
- Hyperlinks (
r:id=\"rId2\", TargetMode="External") - Afbeeldingen en audiotracks opgeslagen in
ppt/media/ - Layout‑erfenis‑pointers (
slideLayout1.xml) - Notitieslides, opmerkingen en ingesloten lettertypen
docProps/ (Metadata)
core.xml: Dublin Core‑metadata—auteur, titel, aanmaakdatum, wijzigings‑tijdstempel.app.xml: Toepassingsspecifieke statistieken—PowerPoint‑versie, totaal aantal dia’s, aantal verborgen dia’s, woordtelling, namen van presentatiesjablonen.
ppt/ (De presentatiemotor)
Dit is waar de daadwerkelijke presentatie zich bevindt:
presentation.xml: De master‑ruggengraat. Het registreert dia‑ID’s, dia‑afmetingsdimensies, notitie‑masterreferenties en standaardlettertype‑instellingen.slides/: De individuele dia’s (slide1.xml,slide2.xml, enz.).slideLayouts/: Master‑structuur‑presets (Titel-dia, Twee‑kolom, Sectiekop).slideMasters/: Globale stijlen, standaardpaletten, achtergrondvullingen en plaatsaanduidings‑overerving.theme/: Kleurpaletten (accent 1 tot 6, donkere/licht variaties) en lettertype‑schema’s (hoofd‑/sublettertypen).media/: Raw images (PNG, JPEG, SVG), audio, and video files.
3. Een dia ontleden: de PresentationML (p:) & DrawingML (a:) dialecten
Wanneer je ppt/slides/slide1.xml opent, kom je twee primaire XML‑naamruimtes tegen:
- PresentationML (
p:): Governs structural presentation elements (slides, shape trees, canvas groups). - DrawingML (
a:): Governs typography, geometry, 2D coordinates, gradient fills, and vector rendering.
Hier is een vereenvoudigd voorbeeld van hoe een standaard tekstvorm eruitziet:
<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>
Cruciale meeteenheden: EMU’s en honderdsten van een punt
Let op de coördinatennummers in <a:xfrm>:
x="1524000"cx="9144000"
Dit zijn English Metric Units (EMUs).
- $1 \text{ inch} = 914,400 \text{ EMUs}$
- $1 \text{ cm} = 360,000 \text{ EMUs}$
- $1 \text{ pt} = 12,700 \text{ EMUs}$
EMU’s stellen gehele getallen in staat exacte breuken van zowel inches als millimeters weer te geven zonder afrondingsfouten van floating‑point getallen op verschillende hardware‑architecturen.
Let ook op de lettergrootte:
sz="3200"means 32.00 pt. Font sizes in DrawingML are measured in hundredths of a point.
4. De overervingsketen: waarom vormen onzichtbare stijlen overerven
Een van de meest voorkomende valkuilen bij het reverse engineeren van PPTX‑bestanden is ervan uitgaan dat de visuele styling van een vorm volledig is gedeclareerd in zijn eigen slideX.xml.
In werkelijkheid vertrouwt OpenXML op een strikt 4‑laag cascaderend overervingsmodel:
[Theme: ppt/theme/theme1.xml]
│
▼
[Slide Master: ppt/slideMasters/slideMaster1.xml]
│
▼
[Slide Layout: ppt/slideLayouts/slideLayout1.xml]
│
▼
[Slide: ppt/slides/slide1.xml]
Als een tekstvak op slide1.xml bevat:
<a:p>
<a:r>
<a:t>Revenue Projections</a:t>
</a:r>
</a:p>
Er is geen lettertypefamilie, geen expliciete kleur en geen grootte gedeclareerd in de run (<a:r>). Om te achterhalen hoe PowerPoint deze tekst rendert, moet uw parser:
- Identify the placeholder type (
<p:ph type="title"/>). - Read the layout referenced in
slide1.xml.rels. - Check if
slideLayout1.xmlprovides styling overrides for that placeholder. - Fall back to
slideMaster1.xmlfor default title text body styles. - Trace color tokens like
accent1ortx1intotheme1.xmlto find the hexadecimal color code.
Als u deze overervingsgrafiek overslaat, zal uw parser stijlen verkeerd lezen, waardoor lettertypen, lettergroottes en lay-outankers ontbreken.
5. Praktische Reverse Engineering-werkwijze
Wanneer u moet onderzoeken hoe een bepaalde PowerPoint-functie onder de motorkap werkt (bijv. morph-transities, complexe tabellen, vectorpaden), volg dan deze empirische aanpak:
Stap 1: Maak een minimale “Diff Pair”
- Open PowerPoint and create a blank slide.
- Save it as
before.pptx. - Apply the exact single change you wish to reverse engineer (e.g., add a drop shadow to a circle, change a bullet style, insert an embedded video).
- Save it as
after.pptx.
Stap 2: Pak beide archieven uit
unzip before.pptx -d before/
unzip after.pptx -d after/
Stap 3: Formatteer de XML
Ruwe XML in Office-archieven wordt meestal ontdaan van inspringing en regeleinde-tekens. Formatteer de bestanden vóór het vergelijken:
find before/ after/ -name "*.xml" -exec xmllint --format {} --output {} \;
Stap 4: Voer een Unified Diff uit
diff -uNr before/ after/ > changes.patch
Het bekijken van changes.patch onthult de exacte tagnaam, namespace-attribuut en containerhiërarchie die PowerPoint heeft geïntroduceerd. Dit is de snelste manier om ongedocumenteerde of obscure schema-eigenschappen te ontdekken zonder door duizenden pagina’s ECMA-376-documentatie te graven.
6. Een aangepaste micro-engine bouwen: uitpakken, wijzigen, opnieuw inpakken
Soms wil je geen zware enterprise-afhankelijkheid zoals Apache POI of de Microsoft OpenXML SDK—vooral niet in lichtgewicht serverless-omgevingen (AWS Lambda, Cloudflare Workers, edge-nodes).
Hier is een zelfstandige Python-patroon dat laat zien hoe je veilig een in-memory PPTX kunt uitpakken, aangepaste gegevens kunt injecteren met standaardbibliotheek-tools, en het vervolgens opnieuw kunt verpakken:
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()
Belangrijke valkuilen bij het wijzigen van bestanden op byte-niveau:
- Namespace Preservation: XML parsers often rewrite prefixes (
xmlns:pmight becomexmlns:ns0). While valid XML, PowerPoint’s strict internal schema validation occasionally rejects non-standard prefix aliases. Register namespaces explicitly. - ZIP Compression Methods: Ensure you write files back using standard deflate compression (
zipfile.ZIP_DEFLATED). - Stream Flushing: Always check that your zip buffer closes and flushes completely before sending bytes downstream.
- Preserve Relationships: If you remove a slide, you must also remove its entry from
ppt/presentation.xml, delete its relationship inppt/_rels/presentation.xml.rels, and scrub its content type from[Content_Types].xml.
7. Prestaties- en beveiligingsoverwegingen
Reverse engineering van PPTX-bestanden gaat niet alleen over het bewerken van dia’s; het gaat ook over het auditen van wat je systemen binnenkomt.
Beveiliging: Miljard Lachjes & XXE
Omdat PPTX-bestanden XML parseren, is elke server-side pipeline die door gebruikers ingediende presentaties verwerkt kwetsbaar voor:
- XML External Entity (XXE) Injection: Malicious XML attempting to access
/etc/passwdor query internal cloud metadata endpoints (http://169.254.169.254/). - Entity Expansion Attacks (Billion Laughs): Exponential entity loops exhausting system RAM.
Mitigatie: Schakel altijd resolve_entities, load_dtd en externe netwerkresolutie uit in uw XML-parser (bijv. met defusedxml in Python).
Beveiliging: Macro Payloads en Verborgen Streams
Inspecteer bestanden op .pptm-inhoud die zich voordoet als .pptx-extensies. Let op ppt/vbaProject.bin, dat gecompileerde Visual Basic-code bevat. In standaard .pptx-bestanden is VBA-code verboden; het vinden van binaire payload-referenties in relaties moet onmiddellijk quarantaine‑signalen activeren.
Conclusie
Reverse engineering van .pptx-bestanden ontrafelt presentatiesoftware. Zodra u beseft dat PowerPoint‑bestanden simpelweg gestructureerde zip‑pakketten zijn gevuld met coördinaten, schemareferenties en XML‑relatie‑bomen, bent u niet langer beperkt door bestaande derden‑abstracties.
Of u nu de doorvoersnelheid van slide‑generatie optimaliseert, aangepaste geautomatiseerde sanitizers schrijft, of renderingsfouten oplost, direct naar de onderliggende OpenXML‑architectuur kijken geeft u volledige controle over de presentatiestroom.
Veelgestelde vragen (FAQ)
**Q: Kunt u een .pptx converteren naar een standaard map en bestanden rechtstreeks in een IDE bewerken?
A1: Ja, u kunt het archief uitpakken, de XML bewerken in een editor zoals VS Code, en de mapinhoud opnieuw zippen om het weer te openen in PowerPoint.
**Q: Waarom zegt PowerPoint dat mijn handmatig aangepaste PPTX‑bestand reparatie nodig heeft?
A2: Dit gebeurt meestal als je misvormde XML hebt geïntroduceerd, een nieuw asset hebt weggelaten uit [Content_Types].xml, of een zwevende verwijzing hebt achtergelaten in een bijbehorend .rels‑bestand.
**Q: Welke meeteenheid gebruikt PowerPoint voor de positie en marges van vormen?
A3: PowerPoint gebruikt Engelse metrische eenheden (EMU’s), waarbij 1 inch gelijk is aan 914.400 EMU’s en 1 punt gelijk is aan 12.700 EMU’s.
**Q: Hoe kan ik alle afbeeldingen uit een presentatie programmeermatig extraheren zonder externe bibliotheken?
A4: Open eenvoudig het .pptx‑bestand met een standaard zip‑hulpmiddel en extraheer alle binaire bestanden die zich bevinden in de map ppt/media/.
**Q: Is het veilig om door gebruikers geüploade PPTX‑bestanden te parseren met standaard XML‑parsers?
A5: Nee, je moet je parser versterken of veilige wrappers gebruiken zoals defusedxml om XML External Entity (XXE)‑ en zip‑bom‑aanvallen te blokkeren.