W poprzednim artykule omawiałem ze szczegółami budowę pliku ATTRIBUTEZ.TXT. Teraz pora na kolejny i zarazem ostatni plik z tej samej kategorii, a mianowicie – plik CHEATZ.TXT. W związku z tym, że oba pliki mają ze sobą wiele wspólnego, przed przeczytaniem tego artykułu polecam najpierw zapoznać się z artykułem poświęconym plikowi ATTRIBUTEZ.TXT, nawet pobieżnie. Powinno to dać pewien zarys tego, z czym się teraz mierzymy.

Plik CHEATZ.TXT miał dla mnie szczególne znaczenie. Po pierwsze, sposób szyfrowania wykorzystany w pliku ATTRIBUTEZ.TXT odkryto podczas mojej nieobecności – byłem wówczas w trakcie stosunkowo dłuższej przerwy od Gruntzów i jak wróciłem na forum, stanąłem przed faktem dokonanym. Śmiesznie się czułem na samą myśl, że tak wielkie odkrycie ominęło mnie szerokim łukiem. Po drugie, okazało się, że plik ATTRIBUTEZ.TXT zawiera naprawdę ważne rzeczy, w tym – kody do gry. Z całych 148KB, jakie zajmuje plik, prawie 5.5KB stanowią same kody (jest ich łącznie 69). Tymczasem plik CHEATZ.TXT nie ma nawet 1KB i jest ponad sześć razy mniejszy niż same kody z pliku ATTRIBUTEZ.TXT! Prowokuje to pytanie, co też takiego znajduje się w tym pliku? Czy rzeczywiście są tam kody do gry, jak sugerowałaby nazwa? Jeżeli tak, to musiałoby ich być naprawdę niewiele, o wiele mniej niż w pliku ATTRIBUTEZ.TXT. A po trzecie – wystarczy spojrzeć na samą lokalizację pliku. Pełna ścieżka do niego to mianowicie STATEZ\CREDITZ\PALETTEZ\CHEATZ.TXT. Ciekawe, czy ma ona jakikolwiek związek z zawartością pliku.


1. Rekonesans

Tak więc usiadłem przy biurku i zastanowiłem się, od czego zacząć. Oczywiście w pierwszej kolejności spróbowałem odszyfrować ten plik korzystając z dokładnie takiego samego algorytmu i klucza, co w przypadku pliku ATTRIBUTEZ.TXT. To byłoby jednak zbyt proste i rzeczywiście – próba zakończyła się porażką. Gdyby sposób zadziałał, nie pisałbym o tym pliku osobnego artykułu 😉 Tak więc dumam dalej.

Algorytm szyfrowania oraz klucz do pliku ATTRIBUTEZ.TXT wygrzebano z samego pliku wykonywalnego. Zagadnienie deasemblacji samo w sobie zasługuje na osobny artykuł i to o sporych rozmiarach. Nie jest to łatwy temat, szczególnie kiedy nie zna się asemblera. Z tego też względu postaram się nie wchodzić w szczegóły deasemblacji, rezerwując sobie temat na inną okazję. Wspomnę może jedynie, że do tego celu zwykle używam programu IDA (Interactive Disassembler) w wersji 5.0 (akurat ta konkretna wersja to freeware). Tak więc przeglądając sobie binarkę znalazłem ostatecznie moment deszyfrowania pliku ATTRIBUTEZ.TXT. Znalazłem moment inicjowania procesu szyfrowania, znalazłem zawartość klucza oraz znalazłem funkcję deszyfrującą pojedynczy blok. Zachęcony tym faktem zacząłem więc szukać ewentualnego miejsca deszyfrowania pliku CHEATZ.TXT. Ale po jakimś czasie dalszego przeszukiwania doszedłem do smutnej i trochę zaskakującej konkluzji – takiego miejsca w ogóle nie ma. Okazuje się bowiem, że gra w ogóle nie wczytuje pliku CHEATZ.TXT z archiwum, a tym bardziej nie deszyfruje go. W tym momencie wszystko stało się jasne – to dlatego w temacie zapoczątkowanym przez użytkownika Friedslick6 na forum XeNTaX uzyskana ostatecznie odpowiedź dotyczyła jedynie pliku ATTRIBUTEZ.TXT, a o pliku CHEATZ.TXT nikt nie wspomniał nawet słowem.

Naturalnie mina trochę mi zrzedła po dokonaniu tego odkrycia. Postanowiłem oczywiście dalej prowadzić tę nierówną walkę, ale szczerze mówiąc – nie liczyłem na wiele. Ale fakt, że gra w ogóle nie korzystała z tego pliku, świadczy o tym, że jest on reliktem z czasów tworzenia gry, który nie został wykasowany z ostatecznej wersji. W takich okolicznościach zawartość tego pliku zyskuje status niemalże kolekcjonerski, tak jak chociażby animacje ataku Grunta z magiczną różdżką, czy też Grunta z Warpstone. Po prostu muszę to mieć!


2. Dochodzenie

Tak więc trzeba zacząć od początku i tym samym otworzyłem plik CHEATZ.TXT w HEX edytorze. Wprawdzie sam plik jest bardzo krótki, ale już w pierwszym momencie jedna istotna rzecz przykuła moją uwagę: parokrotnie powtarzający się na początku pliku 8-bajtowy blok. Przypominam, że na coś bardzo podobnego napotkaliśmy się podczas analizowania pliku ATTRIBUTEZ.TXT, gdzie powtarzającym się blokiem okazał się ostatecznie ciąg ośmiu gwiazdek (“********“). Niemalże identyczny rozkład tych bloków w obu plikach sugerowałby, że również i w pliku CHEATZ.TXT na początku pojawia się analogiczny komentarz z wielokrotnie powtarzającymi się gwiazdkami.

Na tym etapie stwierdziłem, że spokojnie mogę już założyć, że również i w tym pliku zastosowane zostało szyfrowanie symetryczne Blowfish, tak samo jak w pliku ATTRIBUTEZ.TXT. Pozostaje więc jedynie znalezienie klucza, użytego podczas szyfrowania. W przypadku pliku ATTRIBUTEZ.TXT był to ciąg znaków “1212”. Stwierdziłem, że jedyną opcją znalezienia klucza jest napisanie algorytmu brute force, który by testował każdą możliwą kombinację hasła. I tutaj oczywiście zaczynają się schody, bo nie mogę testować tak po prostu każdej możliwej kombinacji – cechą charakterystyczną takiego algorytmu jest wykładnicza złożoność obliczeniowa względem długości klucza. Jeżeli klucz byłby odpowiednio długi, wszystkich możliwych kombinacji klucza mogłoby być tak dużo, że sam program musiałby działać tysiące lat by je wszystkie przeanalizować. Więc na dwoje babka wróżyła – albo został wybrany prosty klucz i uda mi się go znaleźć, albo po jakimś czasie po prostu stwierdzę, że nie da się go znaleźć.

Załóżmy więc, że wygenerowaliśmy sobie jakiś klucz i deszyfrujemy nim plik. Jeżeli widzimy same krzaki – nie trafiliśmy z kluczem. Jeżeli natomiast widzimy coś interesującego – krzyczymy “bingo” i kończymy. Musimy jednak ten proces zautomatyzować. W efekcie pojawia się pytanie, skąd program ma wiedzieć, że uzyskany po deszyfrowaniu tekst ma sens i tym samym klucz jest poprawny? I tutaj sobie przypominamy o tym powtarzającym się 8-bajtowym bloku na początku pliku. Istnieje bowiem całkiem spora szansa, że reprezentuje on ciąg ośmiu gwiazdek, tak jak miało to miejsce w przypadku pliku ATTRIBUTEZ.TXT. Tryb kodowania ECB (patrz poprzedni artykuł) ma to do siebie, że każdy blok danych jest szyfrowany niezależnie od pozostałych. Można więc zdeszyfrować taki jeden pojedynczy blok i sprawdzić, czy odpowiada mu ciąg ośmiu gwiazdek. Jeżeli tak – mamy pozamiatane.

A co, jeżeli nie wpadlibyśmy na ten pomysł z ośmioma gwiazdkami, albo nie mielibyśmy takiej wiedzy? Zakładając, że oryginalny dokument jest zwyczajnym plikiem tekstowym, można próbować analizy statystycznej: cały dokument byłby deszyfrowany wygenerowanym przez nas kluczem, a następnie zliczalibyśmy, jaki procent wszystkich bajtów stanowią drukowalne znaki ASCII. Jeżeli jest to wartość bliska stu procent, jest szansa, że trafiliśmy z kluczem. A jeżeli oryginalny dokument byłby plikiem binarnym … ? Bez znajomości jakiegokolwiek wzorca, raczej byłoby nam ciężko cokolwiek z tym fantem zrobić.

Tak więc wszystko jest kwestią założeń. Założeń jak długi ma być klucz, założeń z jakich znaków może się składać. Już nie wspominając o założeniu, że blok ma ostatecznie dawać ciąg ośmiu gwiazdek – przecież równie dobrze może to być jakikolwiek inny ciąg ośmiu znaków. I albo z tymi założeniami trafię, albo nie. Na dobry początek założyłem więc, że klucz ma cztery znaki długości (tak, jak w pliku ATTRIBUTEZ.TXT). Każdy znak (a właściwie bajt) może mieć jedną z 256 możliwych wartości, przez co jest ponad 4 miliardy możliwych kluczy. Na moim komputerze, jeżeli teraz uruchomiłbym program, skończyłby za jakieś 41 godzin. Uwierzcie mi, w kontekście łamania kluczy w ten sposób, to nie jest długo. Mimo to, postanowiłem wstępnie założyć że klucz jest mniej skomplikowany i okroić zestaw możliwych znaków. Zacząłem od samych cyfr 0-9. Każdy znak to wówczas 10 możliwości, a wszystkich możliwych kluczy jest wówczas 10 tysięcy. Program w ułamek sekundy je przeanalizował i nie znalazł takiego, który dawałby w wyniku osiem gwiazdek. W drugim podejściu rozszerzyłem ten zestaw do wszystkich znaków drukowalnych, od wartości ASCII 0x20 (spacja) do 0x7E (znak tyldy “~”); w sumie – 95 znaków, co daje ponad 81 milionów możliwych kombinacji klucza. Włączyłem program i poszedłem coś zjeść. Program działał 47 minut.

A jak wróciłem do komputera, krzyknąłem “bingo”.


3. Grand finale

Po jakichś 20 minutach działania algorytmu, program znalazł klucz dający w rezultacie osiem gwiazdek. Kluczem okazał się ciąg znaków “K3V1“. Okazuje się, że plik rzeczywiście zawiera kody do gry, tak jak sugerowała jego nazwa. Jest ich sześć i są analogicznie zakodowane, jak w pliku ATTRIBUTEZ.TXT. Poniżej jest dostępna ich odkodowana wersja:

Wśród sześciu kodów do gry występujących w pliku, trzy z nich występują już w pliku ATTRIBUTEZ.TXT, ale pod innymi nazwami. Są to kody:

  • MPLC – jest to kod MPILOVETHISGAME, umożliwiający tworzenie nowych Gruntów podczas gry za pomocą klawisza “I”
  • MPPD – jest to kod MPIHATETHISGAME, umożliwiający usuwanie Gruntów podczas gry za pomocą klawisza “K”
  • MPFIRE – jest to kod MPLETSBLOWSTUFFUP, umożliwiający wytworzenie zdalnego wybuchu za pomocą klawisza “F9”

Pozostałe trzy kody są już jednak zupełną nowością:

  • MPCLEARCHEATZ – nazwa kodu powinna mówić sama za siebie. Kod kasuje negatywny efekt korzystania z kodów, a mianowicie umożliwia ponowny zapis gry
  • MPWARPSTONEZ – chyba najbardziej wyczekiwany kod ze wszystkich. Umożliwia zdalne zdobycie kawałka Warpstone
  • MPGOOPUDDLE – jest to kod umożliwiający wytwarzanie Goo Puddle w miejscu kursora za pomocą klawisza “P”

Można jedynie snuć hipotezy odnośnie tego, skąd jest ten plik. Być może programiści planowali od samego początku umieścić kody do gry w osobnym, dedykowanym do tego pliku. Po jakimś czasie mogli jednak zmienić zdanie i kody umieścili ostatecznie w pliku ATTRIBUTEZ.TXT, zostawiając plik CHEATZ.TXT w archiwum (albo przez przypadek, albo do późniejszego wglądu). Faktem jednak jest, że te trzy “nowe” kody, które są w pliku CHEATZ.TXT, są dosyć potężne i umożliwiają już kompletne manipulowanie poziomem i jego zakończeniem. Mogło być tak, że programiści stwierdzili, że kody te pozwalają graczowi na zbyt wiele i po prostu ostatecznie je usunęli z pliku ATTRIBUTEZ.TXT skutecznie uniemożliwiając ich wykorzystanie podczas gry. Żeby te kody przywrócić do stanu używalności, trzeba by zmodyfikować plik ATTRIBUTEZ.TXT. Ale jest też jeszcze inny ciekawy sposób na zrealizowanie tego celu, z którym nie wiąże się modyfikowanie żadnych plików. Ale na to zarezerwuję sobie – tak – znowu kolejny artykuł 🙂

Tomalla