Ktoś uruchomił DOOM-a w pliku PDF. To coś o PDF-ach mówi

Kotek w zbroi Doomguya obok laptopa, na którym DOOM działa wewnątrz pliku PDF

W informatyce krąży żart, że DOOM prędzej czy później uruchomi się na wszystkim. Nie jako komplement pod adresem gry, tylko jako wyzwanie: strzelankę z 1993 roku zmuszono już do działania na bankomatach, drukarkach, testach ciążowych, kalkulatorach, pojedynczym klocku LEGO i na pasku dotykowym MacBooka.

W styczniu 2025 roku uczeń szkoły średniej dopisał do tej listy kolejną pozycję. Uruchomił DOOM wewnątrz pliku PDF.

DOOM działający wewnątrz pliku PDF, renderowany znakami ASCII

W skrócie

Uczeń liceum skompilował DOOM do asm.js wersją Emscriptena z 2020 roku i uruchomił go w pliku PDF, używając jednego pola formularza na każdy wiersz ekranu: 320×200, sześć odcieni szarości, około 80 milisekund na klatkę. Nie użyto żadnej luki. Każda wykorzystana funkcja to udokumentowany element specyfikacji PDF, działający dokładnie tak, jak zaprojektowano. I to jest w tym najciekawsze — oraz powód, dla którego warto raz poświęcić dokumentom dziesięć minut uwagi.

To świetna robota i bardzo dobry żart. To także najczytelniejszy dowód na coś, co ta witryna powtarza od dawna, a w co ludzie mają pełne prawo nie wierzyć: PDF nie jest obrazkiem strony. Jest pojemnikiem, który potrafi wykonywać kod.

Jak to naprawdę działa

Projekt nazywa się doompdf, a stoi za nim programista podpisujący się ading2210. Mechanizm jest ciekawszy niż sam wyczyn i składa się z czterech części.

PDF obsługuje JavaScript. Nie jako dodatek czy wtyczkę — to część formatu, z własną biblioteką standardową, którą implementują także przeglądarki we wbudowanych silnikach PDF. Istnieje po to, żeby formularze mogły sprawdzać poprawność wpisywanych danych, a interaktywne dokumenty reagować na kliknięcia. Nikt nie dodał jej z myślą o grach.

Kod źródłowy DOOM-a jest publiczny — choć historia jest bardziej szczegółowa, niż sugeruje skrót myślowy. id Software opublikowało kod 23 grudnia 1997 roku, ale na licencji zezwalającej wyłącznie na zastosowania edukacyjne, i to kod linuksowego portu, nie oryginału na DOS — z powodu osobnej licencji biblioteki dźwiękowej DMX. Przejście na GPL nastąpiło prawie dwa lata później, 3 października 1999 roku. To ta druga data ma znaczenie: zamieniła DOOM-a z czegoś, co można przeczytać, w coś, co można legalnie zbudować od nowa. Dlatego gra wciąż pojawia się w nieoczekiwanych miejscach.

Oba światy połączył celowo przestarzały kompilator. ading2210 użył Emscriptena 1.39.20 — wersji z 2020 roku — ponieważ generuje ona asm.js, a nie WebAssembly. Współczesny Emscripten produkuje WebAssembly, a PDF nie ma środowiska uruchomieniowego dla WebAssembly. asm.js to ograniczony dialekt zwykłego JavaScriptu, więc działa wszędzie tam, gdzie działa JavaScript. Sięgnięcie po stare narzędzia nie było sentymentem, tylko jedyną drogą do środka.

Zostaje jeszcze wyświetlanie, czyli ta część, przy której ludzie wybuchają śmiechem. PDF nie ma płótna, nie ma bufora ramki, nie ma czego malować pikselami. Ma za to pola formularza. Obraz gry o rozdzielczości 320×200 jest więc renderowany znakami ASCII — jedno pole tekstowe na każdy wiersz ekranu, w sześciu odcieniach szarości — i odświeżany tak szybko, jak da się przepisać ten tekst, co daje mniej więcej 80 milisekund na klatkę. Sterowanie odbywa się tą samą drogą: przez pola i przyciski, które silnik PDF i tak potrafi obsłużyć. Grasz w DOOM-a dosłownie w formularzu do wypełnienia.

Działa wolno. Jest monochromatyczny. Jest w pełni grywalny, wydany na GPL v2 — tak jak kod, na którym się opiera — i można go samemu wypróbować w przeglądarce opartej na Chromium. Wersja źródłowa pozwala nawet podłożyć własny plik WAD.

Potem uruchomił w nim Linuksa

Kilka tygodni później ten sam programista opublikował linuxpdf: pełne jądro Linuksa startujące wewnątrz pliku PDF, dzięki skompilowaniu emulatora RISC-V TinyEMU tą samą sztuczką z asm.js. Jądro wstaje od 30 do 60 sekund — autor szacuje to na ponad sto razy wolniej niż na prawdziwym sprzęcie — a steruje się nim wirtualną klawiaturą zbudowaną z przycisków PDF.

DOOM w dokumencie to żart. Emulowany procesor uruchamiający system operacyjny w dokumencie to już argument. Gdzieś pomiędzy jednym a drugim przestaje chodzić o DOOM-a.

Ta część, która nie jest zabawna

Oto myśl, przy której warto się zatrzymać. Nic w doompdf nie jest exploitem. Nie znaleziono żadnej podatności, niczego nie złamano, nie użyto żadnej dziury w zabezpieczeniach. Każdy element, z którego korzysta ten projekt, to udokumentowana i zamierzona funkcja specyfikacji PDF, działająca dokładnie tak, jak przewidziano.

Kot przy komputerze — DOOM przeniesiono na niemal każde wyobrażalne urządzenie

To znaczy, że zdolność pozwalająca PDF-owi uruchomić strzelankę z 1993 roku siedzi też w fakturze, którą otworzysz jutro. Nie czai się, nie jest ukryta — po prostu tam jest, nieużywana, bo większość dokumentów nie ma powodu z niej korzystać.

To jest uczciwa wersja tej historii i działa w obie strony. To samo rozumowanie, które mówi „dokument potrafi wykonać kod, więc uważaj”, musi też przyznać, jak wąski jest świat, w którym ten kod działa.

Co skrypt w PDF-ie może, a czego nie może

To miejsce, w którym większość tekstów o doompdf robi się mglista, więc warto być konkretnym. Odpowiedź zależy w całości od tego, w czym otworzyłeś plik — a dwa najczęstsze przypadki różnią się bardzo.

MożliwośćPodgląd w przeglądarce (Chrome, Edge, Firefox)Adobe Acrobat Reader
Wykonanie skryptu przy otwarciuTakTak, o ile nie wyłączono
Odczyt i zapis pól formularzaTakTak
Dostęp do ciasteczek i pamięci przeglądarkiNieNie dotyczy
Dostęp do strony HTML dookoła (DOM)NieNie dotyczy
Żądania siecioweBardzo ograniczoneSzersze — tu mieszkały piksele śledzące i wycieki poświadczeń NTLM
Dostęp do plików lokalnychNieOgraniczony, ale API jest znacznie większe
Uruchamianie programów i załącznikówNieZa potwierdzeniem — historycznie tędy szły złośliwe dokumenty

Tę tabelę trzeba czytać we właściwą stronę. W przeglądarce skryptowany PDF działa w małym, nudnym pudełku — bez ciasteczek, bez pamięci, bez dostępu do strony dookoła. Właśnie dlatego doompdf jest ciekawostką, a nie incydentem, i dlatego „DOOM działa w PDF-ie” nie jest powodem, żeby bać się PDF-ów.

Ciekawa jest kolumna z czytnikiem desktopowym. Ma on pełne API JavaScriptu opisane w specyfikacji, bo służy do obsługi prawdziwych dokumentów firmowych. To środowisko, w którym dokumentowi można kazać zameldować się gdzieś w sieci w chwili otwarcia, zachować się inaczej w zależności od czytnika albo poprosić o otwarcie czegoś, co niósł ze sobą.

Trzy rzeczy pozostają więc prawdą niezależnie od programu i to je warto zapamiętać.

  • PDF może nieść instrukcje wykonywane w chwili otwarcia, zanim cokolwiek przeczytasz.
  • PDF może zachować się inaczej w zależności od programu, który go otworzy — plik, który widzisz, nie musi być tym samym, co widzi twój współpracownik.
  • PDF niesie więcej, niż pokazuje: załączniki, ukryte warstwy, historię zmian i metadane, których nie zamierzałeś wysłać.

Nic z tego nie czyni PDF-ów niebezpiecznymi w codziennym sensie. Otworzysz ich w tym miesiącu kilkadziesiąt i z każdym będzie dobrze. Znaczy to jednak, że model, który większość z nas nosi w głowie — „to tylko dokument” — jest błędny w sposób, który czasem ma znaczenie.

Ustawienie, o którym prawie nikt nie wie

Standardowa rada brzmi „wyłącz JavaScript w czytniku PDF” i jest dobra. Sama w sobie jest jednak niepełna — bo większość ludzi nie otwiera już PDF-ów w czytniku PDF. Otwiera je w karcie przeglądarki, a przeglądarka ma własny, osobny przełącznik.

Firefox dostarczany jest ze skryptami w PDF włączonymi. Ustawienie nazywa się pdfjs.enableScripting i znajduje się w about:config; do Firefoksa 87 miało wartość false, od Firefoksa 88 ma true. Ogólny przełącznik javascript.enabled go nie dotyka — podgląd PDF to osobny świat z osobnym ustawieniem.

Chrome i Edge w ogóle nie udostępniają osobnego przełącznika dla skryptów w PDF. Skrypt w pliku podlega uprawnieniu JavaScriptu dla witryny, z której plik pochodzi — można je wyłączyć dla pojedynczej strony w panelu przy pasku adresu albo globalnie pod chrome://settings/content/javascript, co jest narzędziem znacznie grubszym.

Adobe Acrobat Reader ma ten przełącznik, o którym wszyscy mówią: Preferencje → JavaScript → Włącz JavaScript programu Acrobat. To jego warto odznaczyć, bo Acrobat jest czytnikiem z dużym API, a prawie nikt świadomie nie używa skryptowanych PDF-ów w zwykłej pracy.

Praktyczny wniosek: wyłączenie tego w Acrobacie i zostawienie przeglądarki w spokoju to rozsądny, proporcjonalny wybór. Przekonanie, że wyłączyło się to wszędzie, gdy wyłączyło się tylko w Acrobacie — już nie.

Co z tą wiedzą zrobić

Praktyczna reakcja jest niewielka i warta tych dziesięciu minut.

Wyłącz JavaScript w czytniku desktopowym. W Acrobat Readerze to Preferencje → JavaScript. Usuwa całą kategorię ryzyka i nie kosztuje nic poza — trzeba przyznać — możliwością zagrania w DOOM-a w polu formularza.

Aktualizuj czytnik. Skrypty to jedna droga do środka. Druga to błędy w kodzie dekodującym czcionki i obrazy, a te naprawiają właśnie aktualizacje — i to one, historycznie, są częstszą drogą.

Traktuj niespodziewane dokumenty jako niespodziewane. Faktura od firmy, u której nigdy nic nie kupiłeś, zasługuje na chwilę zastanowienia, w jakimkolwiek formacie przyszła. To jest warte więcej niż jakiekolwiek ustawienie.

Zauważ, co łączy te trzy punkty: żaden nie wymaga rezygnacji z PDF-ów ani podejrzliwości wobec dokumentów w ogóle. To odpowiednik zamykania drzwi na klucz — tanie, nudne i rozsądne właśnie dlatego, że ryzyko jest małe, ale niezerowe.

Dlaczego ten projekt zasłużył na uwagę, którą dostał

Łatwo byłoby wrzucić doompdf do szuflady „ciekawostki z internetu” i przejść dalej. Twierdzę, że jest pożyteczniejszy, z powodu, który nie ma nic wspólnego z teatrem bezpieczeństwa.

Rozumienie formatów plików większość ludzi buduje wyłącznie na tym, do czego formaty służą. Dokumenty są do czytania. Arkusze do liczb. Obrazy do oglądania. Ten model działa niemal zawsze i właśnie dlatego tak trudno go ruszyć — a wyjaśnienie „PDF może zawierać aktywną treść” spotyka się zwykle z uprzejmym sceptycyzmem.

Grywalna gra w dokumencie robi w dziesięć sekund to, z czym artykuł mocuje się przez tysiąc słów. Zamienia abstrakcyjne twierdzenie w coś, w co można kliknąć.

Głębszy wniosek sięga daleko poza PDF-y. Formaty przez dekady obrastają w funkcje. Każdy dodatek miał sens dla kogoś, kto rozwiązywał realny problem — sprawdzanie poprawności formularza naprawdę się przydaje, podobnie jak dokument umiejący sprawdzić własne rachunki. Efekt jest taki, że zwyczajne rzeczy, którymi wymieniamy się codziennie, potrafią znacznie więcej, niż sugerują ich nazwy. A możliwość, która raz znalazła się w specyfikacji, jest dostępna dla każdego, kto tę specyfikację przeczyta.

Co z tego wynika dla codziennych plików

Nic z powyższego nie jest argumentem przeciwko PDF-owi. Pozostaje najlepszym formatem do wysłania dokumentu, który wszędzie wygląda tak samo, na dowolnej maszynie, także za wiele lat. To naprawdę trudny problem, a PDF go rozwiązał. Funkcje, dzięki którym doompdf jest możliwy, to te same funkcje, dzięki którym możliwy jest wypełnialny formularz podatkowy.

To argument za tym, żeby wiedzieć, z czym się pracuje. Ta sama wszechstronność, która pozwala dokumentowi nieść grę, pozwala mu też nieść skrypty, załączniki, ukryte warstwy i metadane, których nie zamierzałeś wysłać. Warto je rozumieć i żadna z nich nie jest powodem do niepokoju.

To także część powodu, dla którego PDF Manipulator działa w całości na twoim komputerze. Przy scalaniu, dzieleniu czy konwersji plików im mniej stron trzecich, tym lepiej — nie dlatego, że usługi online są podejrzane, ale dlatego, że dokument, który nigdy nie opuścił twojej maszyny, jest po prostu prostszy do ogarnięcia niż taki, który był na czyimś serwerze.

Pracuj na plikach PDF w pełni offline — PDF Manipulator jest darmowy →

Źródła

Zostaw komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *

Przewijanie do góry