עודכן לאחרונה: 16 ספטמבר, 2026

PPTX Reverse Engineering: Understanding PowerPoint Files Internally

הנדסה הפוכה PPTX קבצים: מדריך למפתח

חבילות מצגות מודרניות מניעות הכל, מהצגות משקיעים ועד מדדי רבעון פנימיים. אבל אם אי פעם נאלצתם לחלץ טקסט באופן תכנותי, להחליף תבניות בזמן ריצה, לבנות מחוללי שקפים אוטומטיים, או לנקות מצגות סודיות, סביר שהבנתם מהר משהו: ספריות מצגות ברמה גבוהה נראות כמו קופסה שחורה בלתי צפויה.

כאשר ספריות כמו python-pptx, Apache POI או OpenXML SDK מגיעות למגבלותיהן—או מציגות באגים בלתי מתועדים בפריסות—הפתרון היחיד הוא להמשיך. עליכם להבין מהי מצגת PowerPoint ברמת הבייט והסכמה.

בצפייה מעמיקה זו נחשוף את פורמט ה-.pptx, נפענח את המבנה הפנימי שלו, נעקוב אחרי גרף הקשרים, ננתח את היררכיות הציור, ונבחן אסטרטגיות מעשיות להנדסה הפוכה, בדיקה, ולשינוי מצגות באמצעות קוד גולמי.

1. מהו קובץ .pptx באמת?

בבסיסה, קובץ .pptx אינו בינארי מונוליתי קנייני כמו פורמט .ppt העתיק של שנות ה‑90. מאז שמיקרוסופט הציגה את 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:): שולט על טיפוגרפיה, גאומטריה, קואורדינטות דו‑ממדיות, מילוי גרדיאנטי, והדמיית וקטורים.

הנה דוגמה מצומצמת של איך נראית צורת טקסט סטנדרטית:

<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{ cm} = 360,000 \text{ EMUs}$
  • $1 \text{ pt} = 12,700 \text{ EMUs}$

EMUs מאפשרים למספרים שלמים לייצג שברים מדויקים של אינצ’ים ומילימטרים ללא שגיאות עיגול של נקודה צפה במגוון ארכיטקטורות חומרה.

שימו לב גם לגודל הגופן:

  • sz="3200" משמעותו 32.00 pt. גדלי גופן ב‑DrawingML נמדדים במאות של נקודה.

4. שרשרת הירושה: למה צורות יורשות סגנונות בלתי נראים

אחת מהמכשולים הנפוצים ביותר בעת הנדסה הפוכה של קבצי PPTX היא ההנחה שסגנון הוויזואלי של הצורה מוכרז במלואו בתוך הקובץ slideX.xml שלה.

במציאות, OpenXML מתבסס על מודל ירושה מדורג של 4 רמות קפדני:

[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 פועלת מאחורי הקלעים (למשל, מעברי morph, טבלאות מורכבות, נתיבי וקטור), פעל לפי הגישה האמפירית הזו:

שלב 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 -uNr before/ after/ > changes.patch

בבדיקת changes.patch מתגלה שם התג המדויק, מאפיין מרחב השם והיררכיית המכולה שהוסיפה PowerPoint. זוהי הדרך המהירה ביותר לגלות תכונות סכימה שלא מתועדות או מעורפלות ללא חפירה באלפי עמודים של תיעוד ECMA-376.

6. בניית מיקרו-מנוע מותאם אישית: פריקה, שינוי, אריזה מחדש

לפעמים אינך רוצה תלות ארגונית כבדה כמו Apache POI או Microsoft OpenXML SDK—במיוחד בסביבות ריצה ללא שרת קלות משקל (AWS Lambda, Cloudflare Workers, קצוות רשת).

להלן תבנית 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 buffer נסגר ומשתחרר במלואו לפני שליחת הבייטים למטה.
  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/).
  • התקפות הרחבת ישויות (ביליון צחוקים): לולאות ישויות אקספוננציאליות שמרוקנות את זיכרון ה‑RAM של המערכת.

הפחתה: תמיד יש לבטל את resolve_entities, load_dtd, ואת פתרון הרשת החיצונית במפענח ה-XML שלך (לדוגמה, באמצעות defusedxml בפייתון).

אבטחה: מטעני מאקרו וזרמים מוסתרים

בדוק קבצים עבור תוכן .pptm המתחזים תחת הרחבות .pptx. שים לב ל-ppt/vbaProject.bin, המכיל קוד Visual Basic מקומפל. בקבצים סטנדרטיים .pptx, קוד VBA אסור; מציאת הפניות למטען בינארי במערכות היחסים צריכה לגרום מיד לסימון בידוד.

סיכום

הנדסה הפוכה של קבצי .pptx מסירה את המסתוריות מתוכנת המצגות. ברגע שאתה מבין שקבצי PowerPoint הם פשוט חבילות zip מובנות שמלאות בקואורדינטות, הפניות לסכימות, ועצי יחסי XML, אינך עוד מוגבל על ידי האבסטרקציות של צד שלישי קיימות.

בין אם אתה ממטב את קצב יצירת השקופיות, כותב מנקים אוטומטיים מותאמים, או מתמודד עם תקלות רינדור, הסתכלות ישירה על ארכיטקטורת OpenXML הבסיסית נותנת לך שליטה מלאה על צינור ההצגה.

שאלות נפוצות (FAQ)

**Q: האם ניתן להמיר קובץ .pptx לתיקייה סטנדרטית ולערוך קבצים ישירות ב-IDE?

A1: כן, ניתן לחלץ את הארכיון, לערוך את ה-XML בעורך כגון VS Code, ולדחוס מחדש את תוכן התיקייה כדי לפתוח אותו שוב ב-PowerPoint.

**Q: למה PowerPoint אומר שהקובץ PPTX שהשתנתי ידנית צריך תיקון?

A2: זה בדרך כלל קורה אם הכנסת XML פגום, השמטת נכס חדש מ-[Content_Types].xml, או השארת הפנייה תלויה בקובץ .rels משויך.

**Q: איזו יחידת מדידה PowerPoint משתמשת למיקום הצורות והמרווחים?

A3: PowerPoint משתמשת ביחידות מדידה אנגליות (EMUs), כאשר אינץ’ אחד שווה ל‑914,400 EMUs ונקודה אחת שווה ל‑12,700 EMUs.

**Q: איך אני יכול לחלץ באופן תכנותי את כל התמונות מהמצגת ללא ספריות חיצוניות?

A4: פשוט פתח את הקובץ .pptx עם כל כלי zip סטנדרטי והוצא את כל הקבצים הבינריים שנמצאים בתוך התיקייה ppt/media/.

**Q: האם בטוח לנתח קבצי PPTX שהועלו על ידי משתמשים עם מפענחי XML סטנדרטיים?

A5: לא, עליך לחזק את המפענח שלך או להשתמש במעטפות בטוחות כמו defusedxml כדי לחסום התקפות XML External Entity (XXE) והתקפות zip‑bomb.

ראה גם