מישהו הריץ את DOOM בתוך קובץ PDF. זה מלמד משהו

גור חתולים בשריון Doomguy לצד מחשב נייד שמריץ את DOOM בתוך קובץ PDF

בעולם המחשוב מסתובבת בדיחה ותיקה: בסופו של דבר DOOM ירוץ על הכול. לא כמחמאה למשחק, אלא כאתגר. את משחק היריות מ־1993 כבר הריצו על כספומטים, מדפסות, בדיקות היריון, מחשבונים, לבנת LEGO בודדת ועל ה־Touch Bar של מקבוק.

בינואר 2025 הוסיף תלמיד תיכון פריט נוסף לרשימה. הוא הריץ את DOOM בתוך קובץ PDF.

DOOM רץ בתוך קובץ PDF, מצויר בתווי ASCII

בקצרה

תלמיד תיכון הידר את DOOM ל־asm.js בעזרת גרסת Emscripten משנת 2020 והריץ אותו בתוך PDF, כששדה טופס אחד משמש כל שורה במסך: 320×200, שישה גווני אפור, כ־80 מילישניות לפריים. שום פרצת אבטחה לא הייתה מעורבת. כל יכולת שנעשה בה שימוש היא חלק מתועד ממפרט ה־PDF, שפועל בדיוק כפי שתוכנן. זה בדיוק החלק המעניין — וזו הסיבה להקדיש למסמכים עשר דקות, פעם אחת.

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

איך זה עובד באמת

הפרויקט נקרא doompdf, של מפתח שמכנה עצמו ading2210. המנגנון מעניין יותר מהתעלול עצמו, והוא מורכב מארבעה חלקים.

PDF תומך ב־JavaScript. לא כתוסף ולא כתוספת חיצונית — זה חלק מהפורמט, עם ספרייה סטנדרטית משלו, והדפדפנים מיישמים אותו במנועי ה־PDF המובנים שלהם. הוא קיים כדי שטפסים יוכלו לאמת את מה שמקלידים בהם ומסמכים אינטראקטיביים יגיבו ללחיצות. איש לא הוסיף אותו במחשבה על משחקים.

קוד המקור של DOOM פתוח — אם כי הסיפור מדויק יותר ממה שהקיצור מרמז. id Software פרסמה את הקוד ב־23 בדצמבר 1997, אך ברישיון שהתיר שימוש לימודי בלבד, וזה היה הקוד של הגרסה ללינוקס, לא של המקור ל־DOS, בגלל הרישיון הנפרד של ספריית הצליל DMX. המעבר ל־GPL הגיע כמעט שנתיים לאחר מכן, ב־3 באוקטובר 1999. דווקא התאריך השני הוא החשוב: הוא הפך את DOOM ממשהו שאפשר לקרוא למשהו שאפשר לבנות מחדש כחוק. משום כך המשחק ממשיך לצוץ במקומות בלתי צפויים.

את שני העולמות חיבר מהדר מיושן במכוון. ading2210 השתמש ב־Emscripten 1.39.20 — גרסה מ־2020 — משום שהיא מייצרת asm.js ולא WebAssembly. Emscripten עדכני מייצר WebAssembly, ול־PDF אין סביבת ריצה ל־WebAssembly. asm.js הוא ניב מצומצם של JavaScript רגיל, ולכן הוא רץ בכל מקום שבו רץ JavaScript. החזרה לכלים הישנים לא הייתה נוסטלגיה אלא הדרך היחידה פנימה.

נותרה התצוגה, החלק שמצחיק בקול רם. ל־PDF אין בד ציור, אין חוצץ תמונה, אין דבר שאפשר לצייר עליו פיקסלים. מה שיש לו הוא שדות טופס. לכן פלט 320×200 של המשחק מצויר בתווי ASCII — שדה טקסט אחד לכל שורה במסך, בשישה גווני אפור — ומתרענן במהירות שבה אפשר לשכתב את הטקסט הזה, כלומר כ־80 מילישניות לפריים. גם הקלט עובר באותה דרך: דרך שדות וכפתורים שמנוע ה־PDF כבר יודע לטפל בהם. משחקים ב־DOOM, פשוטו כמשמעו, בתוך טופס למילוי.

זה רץ לאט. זה מונוכרומטי. זה שחיק לחלוטין, מופץ תחת GPL v2 כמו הקוד שעליו הוא מבוסס, ואפשר לנסות אותו בדפדפן מבוסס Chromium. הגרסה אפילו מאפשרת להכניס קובץ WAD משלכם.

ואז הוא הריץ בתוכו לינוקס

כמה שבועות לאחר מכן פרסם אותו מפתח את linuxpdf: ליבת לינוקס מלאה שעולה בתוך קובץ PDF, על ידי הידור המדמה TinyEMU מסוג RISC-V באותו תרגיל asm.js. הליבה עולה תוך 30 עד 60 שניות — המחבר מעריך זאת כאיטית פי מאה ויותר מחומרה אמיתית — ושולטים בה במקלדת וירטואלית הבנויה מכפתורי PDF.

DOOM בתוך מסמך הוא בדיחה. מעבד מדומה שמאתחל מערכת הפעלה בתוך מסמך הוא כבר טענה. אי־שם בין השניים העניין מפסיק להיות על DOOM.

החלק שאינו מצחיק

הנה המחשבה שכדאי לשבת איתה. שום דבר ב־doompdf אינו ניצול פרצה. לא נמצאה שום חולשה, שום דבר לא נשבר, שום חור אבטחה לא היה מעורב. כל פרט שהוא משתמש בו הוא יכולת מתועדת ומכוונת של מפרט ה־PDF, שעובדת בדיוק כפי שתוכננה.

חתול מול מחשב — DOOM הומר כמעט לכל מכשיר שאפשר להעלות על הדעת

כלומר, היכולת שמאפשרת ל־PDF להריץ משחק יריות מ־1993 קיימת גם בחשבונית שתפתחו מחר. היא לא אורבת ולא מוסתרת — היא פשוט שם, ללא שימוש, כי לרוב המסמכים אין סיבה להשתמש בה.

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

מה סקריפט בתוך PDF יכול ומה לא

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

יכולתמציג הדפדפן (Chrome, Edge, Firefox)Adobe Acrobat Reader
הרצת סקריפט בעת הפתיחהכןכן, אלא אם כובה
קריאה וכתיבה של שדות טופסכןכן
קריאת עוגיות או אחסון הדפדפןלאלא רלוונטי
גישה לדף ה־HTML שמסביב (ה־DOM)לאלא רלוונטי
ביצוע בקשות רשתמוגבל מאודרחב יותר — כאן חיו פיקסלי מעקב ודליפות NTLM
גישה לקבצים מקומייםלאמוגבלת, אך שטח ה־API גדול בהרבה
הפעלת תוכניות חיצוניות או קבצים מצורפיםלאבאישור — היסטורית, הדרך של מסמכים זדוניים

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

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

שלושה דברים, אם כן, נשארים נכונים בכל תוכנה, וכדאי להפנים אותם.

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

שום דבר מזה אינו הופך קובצי PDF למסוכנים במובן היומיומי. תפתחו עשרות מהם החודש והכול יהיה בסדר. אבל זה כן אומר שהמודל שרובנו נושאים בראש — "זה רק מסמך" — שגוי באופן שלפעמים משנה.

ההגדרה שכמעט אף אחד לא מכיר

העצה המקובלת היא "כבו JavaScript בקורא ה־PDF", והיא עצה טובה. כשלעצמה היא גם חלקית — כי רוב האנשים כבר לא פותחים PDF בקורא PDF. הם פותחים אותו בלשונית של דפדפן, ולדפדפן יש מתג נפרד משלו.

Firefox מגיע כשסקריפטים ב־PDF מופעלים. ההעדפה נקראת pdfjs.enableScripting ב־about:config; היא הייתה false עד Firefox 87 והיא true מ־Firefox 88. המתג הכללי javascript.enabled אינו נוגע בה: מציג ה־PDF הוא עולם נפרד עם הגדרה נפרדת.

Chrome ו־Edge אינם מציעים כלל מתג ייעודי לסקריפטים ב־PDF. סקריפט בתוך PDF כפוף להרשאת ה־JavaScript של האתר שממנו הגיע הקובץ; אפשר לכבות אותה לאתר מסוים דרך הפקדים שליד שורת הכתובת, או באופן גורף ב־chrome://settings/content/javascript — כלי גס בהרבה.

Adobe Acrobat Reader הוא בעל המתג שכולם מתכוונים אליו: העדפות → JavaScript → הפעל JavaScript של Acrobat. זה הסימון שכדאי להסיר, כי Acrobat הוא הקורא בעל הממשק הגדול, וכמעט איש אינו משתמש ביודעין ב־PDF עם סקריפטים בעבודה רגילה.

מעשית: לכבות את זה ב־Acrobat ולהניח לדפדפן היא בחירה סבירה ומידתית. להאמין שכיביתם בכל מקום, כשכיביתם רק ב־Acrobat, אינה כזו.

מה לעשות עם המידע הזה

התגובה המעשית קטנה ושווה את עשר הדקות.

כבו JavaScript בקורא השולחני. ב־Acrobat Reader: העדפות → JavaScript. זה מסלק קטגוריה שלמה של סיכון ואינו עולה דבר, מלבד — יש להודות — היכולת לשחק ב־DOOM בתוך שדה טופס.

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

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

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

למה הפרויקט הזה ראוי לתשומת הלב שקיבל

קל היה לתייק את doompdf תחת "סקרנות אינטרנטית" ולהמשיך הלאה. אני טוען שהוא מועיל יותר מכך, מסיבה שאין לה דבר עם תיאטרון אבטחה.

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

משחק שחיק בתוך מסמך עושה בעשר שניות את מה שמאמר מתאמץ לעשות באלף מילים. הוא מחליף טענה מופשטת במשהו שאפשר ללחוץ עליו.

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

מה נשאר מכל זה ליומיום

שום דבר כאן אינו טענה נגד PDF. הוא נשאר הפורמט הטוב ביותר לשליחת מסמך שייראה זהה בכל מקום, בכל מכונה, גם בעוד שנים. זו בעיה קשה באמת, ו־PDF פתר אותה. היכולות שמאפשרות את doompdf הן אותן יכולות שמאפשרות טופס מס למילוי.

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

זה גם חלק מהסיבה ש־PDF Manipulator פועל כולו על המחשב שלכם. במיזוג, בפיצול או בהמרה של קבצים, ככל שמעורבים פחות גורמים כך טוב יותר — לא משום ששירותים מקוונים מרושעים, אלא משום שמסמך שמעולם לא עזב את המכונה שלכם פשוט קל יותר להבנה ממסמך ששהה בשרת של מישהו אחר.

עבדו עם קובצי ה־PDF שלכם לגמרי במצב לא מקוון — PDF Manipulator חינמי →

מקורות

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

Scroll to Top