Всё произошло очень быстро: какая‑то ностальгическая статья про сборники Classic Fond — и вот я уже качаю образы «Лучшие игры для IBM PC» с Internet Archive. Первым скачался 25-й диск. Открыл и вспомнил всё: школу, переход рядом с ВДНХ, палатки. Ешь беляш, смотришь, какие альбомы вышли, ну и, конечно, сборники Classic Fond.

Мне захотелось покопаться во внутренностях базы: посмотреть, какие в то время делали защиты, фишки и трюки.

Но ещё до распаковки BASE.EXE я наткнулся на интересный артефакт. На первых девяти дисках в папке CHEAT лежит запароленный архив AUTORS.ZIP, а в readme рядом есть такой фрагмент:
В: Как стать Вашим дилером и что для этого нужно? Как с вами связаться?
О: Напишите о своих возможностях по адресу, указанному в read.me. Если нас заинтересуют Ваши предложения, мы с Вами свяжемся. К сожалению, по понятным причинам, прямо указать свои координаты на можем. Впрочем, если Вы неумеренно круты, наши координаты находятся в файле \CHEAT\autors.zip Звоните!
Адрес — это просто абонентский ящик: «121467 г. Москва, а/я 98, Classic Fond».
Судя по документу, под словом «дилер» подразумевается обычный продавец дисков. Непонятно, зачем потенциальному продавцу предлагать технический челлендж со взломом архива. Куда логичнее было бы таким образом искать технически подкованных специалистов в те лихие времена.
Посмотрим, что внутри AUTORS.ZIP

Кстати, их всех ZIP архивов на диске (а их 311) пароль стоял только на одном — AUTORS.ZIP. Запароленные игры стали появляться позже.
Я решил погуглить, как и кто вскрывал этот архив, но, к моему удивлению, совершенно ничего не нашёл. Судя по дате, указанной внутри ZIP-архива, файл создан 22 августа 1994 года.
Примерно к этому же времени относится работа Эли Бихама и Пола Кохера об атаке на шифр PKZIP. Она вошла в материалы FSE 1994, опубликованные в 1995 году.
“In this paper we describe a known plaintext attack on the PKZIP stream cipher which takes a few hours on a personal computer and requires about 13–40 (compressed) known plaintext bytes, or the first 30–200 uncompressed bytes, when the file is compressed.”
В этой статье мы описываем атаку на потоковый шифр PKZIP по известному открытому тексту. Она занимает несколько часов на персональном компьютере и требует примерно 13–40 байт известного открытого текста (после сжатия) либо первых 30–200 байт исходных данных, если файл сжат.
Неочевидно, что авторы задумывали такой вектор атаки — файл AUTORS.ZIP с первого диска «Лучшие игры для IBM PC #1» датирован 22 августа 1994 года, а статья Бихама и Кохера вышла лишь в начале 1995 года. В теории человек мог прочитать статью и на ее основе написать программу, которая бы эксплуатировала эту уязвимость (надо было знать некоторое количество известной информации внутри архива), но мы попробуем вскрыть этот документ инструментами того времени, даже не прибегая к уязвимостям в PKZIP — сделаем теплый ламповый реверс в духе 1994 года
Что видно без пароля

Из вывода PKUNZIP -vmt можно узнать, что внутри лежит AUTORS.DOC размером 11 байт с CRC32 B8AB1F5A. Имя файла, размер и контрольная сумма видны без пароля. Вспоминаем фразу из readme: «Наши координаты находятся в файле \CHEAT\autors.zip. Звоните!»
Можно сделать смелое предположение, что внутри телефон. Причём записанный ровно в 11 байтах: например, девять символов номера и перевод строки CRLF.
Что это может быть? В DOS‑кодировке строка Тел. 777-77-77 занимает 14 байт, просто 777-77-77 — девять. А вот 777-77-77<CR><LF> или 0957777777<SPC>дадут нужные 11.
План простой: составить шаблоны возможной записи телефонного номера и проверить CRC32 каждой строки. Коллизии вполне возможны: два разных номера могут дать одну и ту же контрольную сумму. Но если мы действительно в 1994 году, никто не мешает позвонить по всем совпадениям со словами: «Я вскрыл ваш архив, давайте знакомиться».
Перебираем телефоны
Воспользуемся популярным в то время Borland C++ 3.1.
#include <stdio.h> #include <string.h> #include <dos.h> /* Параметры AUTORS.ZIP из вывода PKUNZIP. */ #define TARGET_CRC 0xB8AB1F5AUL #define FILE_LENGTH 11 #define TOTAL_NUMBERS 10000000UL char *mask[] = { "Т.###-##-##", "т.###-##-##", "T.###-##-##", "t.###-##-##", "тел.#######", "Тел.#######", "ТЕЛ.#######", "tel.#######", "Tel.#######", "TEL.#######", "тел:#######", "Тел:#######", "ТЕЛ:#######", "tel:#######", "Tel:#######", "TEL:#######", "тел #######", "Тел #######", "ТЕЛ #######", "tel #######", "Tel #######", "TEL #######", "Т.#######\r\n", "т.#######\r\n", "T.#######\r\n", "t.#######\r\n", "###-##-##\r\n", "### ## ##\r\n", "###.##.##\r\n", "095-#######", "095 #######", NULL };
Попробуем логичные сочетания, которые дают 11 байт. Конечно, пространство поиска можно сильно уменьшить — например, проверять только существовавшие телефонные префиксы. Но пока пойдём в лоб — у нас получается 31 шаблон по 10 миллионов номеров — всего 310 миллионов вариантов. CRC32 посчитаем по учебнику: таблица, полином 0xEDB88320, XOR с 0xFFFFFFFF.
Сами строки будем генерировать прямо во время перебора:
/* Перебор шаблонов телефонных номеров. */ for (t = 0; mask[t] != NULL; t++) { if (strlen(mask[t]) != FILE_LENGTH) continue; /* Перебор номеров от 0000000 до 9999999. */ for (n = 0; n < TOTAL_NUMBERS; n++) { sprintf(digits, "%07lu", n); /* Подстановка цифр вместо символов #. */ for (i = 0, j = 0; mask[t][i]; i++) text[i] = (mask[t][i] == '#') ? digits[j++] : mask[t][i]; text[i] = '\0'; if (crc32(text) == TARGET_CRC) { printf("Found: %s\n", text); } } }
A нашел настоящий 286 компьютер, и прогнал на нем небольшой бенчмарк — получилось около 6 к в секунду, что для 310 миллионов вариантов дает около 15 часов в худшем случае, что довольно терпимо, но если хочется быстрей, можно попробовать выкинуть невалидные номера из списка.

На дисках 1994–1995 годов был телефонный справочник SONATA. У него есть недокументированная функция: выгрузить в файл по одному телефону на АТС. У меня получилось 555 записей — 555 префиксов, которые есть в этой версии справочника. Если ограничиться ими, можно почти вдвое сократить поиск, но пока запустим перебор всех подряд номеров:

Всего через 19 минут нашлось первое совпадение: Т.220-34-17

Но всё же надо проверить остальные варианты. То, что строка Т.220-34-17 имеет нужную CRC32, ещё не гарантирует, что именно она лежит в архиве. Полный перебор покажет, есть ли другие совпадения среди наших шаблонов. Так что оставим компьютер работать. (UPD: 48 часов заняло в итоге)
Кому звоним
Пока изучим номер: префикс АТС 220 есть в справочнике, номер выглядит как московский. SONATA.EXE из 1995 года его не находит, зато поиск в интернете даёт интересный документ «ОАОЭиЭ Мосэнерго. Инвестиционный портрет». В разделе «Реквизиты» есть наш телефон:
Наименование: Мосэнерго
Юридическое наименование: Открытое акционерное общество энергетики и электрификации Мосэнерго
Юридический адрес: 113035, г. Москва, Раушская наб., д. 8 Почтовый адрес: 113035, г. Москва, Раушская наб., д. 8
Телефон: (095) 220–35-30, 220–38-84, 220–34-17 Факс: (095) 220–34-70
Судя по содержанию, документ относится к 1999 году. В отчёте за 2000 год встречаются похожие номера, но уже с префиксом 957.

Возможно, часть номеров АТС 220 перенесли на новую нумерацию. (220-35-30 превратился в 957-35-30,а наш таинственный номер в 957-34-17)
Пока это только зацепка. К сожалению, я не нашёл ничего, что объясняло бы, кому принадлежал номер в 1994 году. Он мог принадлежать какой‑то организации, а потом ближе к 1999 году перейти в «Мосэнерго». Надеюсь, на Хабре найдутся свидетели тех времён и расскажут историю целиком.
Удивительно, но в интернете очень мало информации о том, кто делал эти выпуски, да и о Classic Fond вообще. Я смог найти упоминания только двух имен: Олег «Palek» Палько и Денис Жулитов.
У Олега есть интервью Литрес, где он прямо говорит о сборнике:
Litres: Это я слышу от пирата?
Palek: В 90-х все были пиратами. Я тогда делал сборник «Лучшие игры для IBM PC», все игры посмотрел до 2000-го года. И не считал себя плохим, потому что тогда играми почти никто не торговал.
Олег — писатель, так что, возможно, именно он отвечал за тексты на дисках и обзоры игр, которые до сих пор очень приятно читать.
А если распаковать одну из более поздних версий BASE.EXE — внутри находится строка: (С) 1996 -= Classic Fond =-, program by Denis Julitov

Имя Denis Julitov находится и в титрах нашумевшей Big Rigs, и еще пары проектов.

Я пока только‑только подступился к BASE.EXE: получил распакованный EXE, определил компилятор (BC 3.1), вытащил пароли от ZIP‑архивов с играми и даже появились предположения, как они генерировались. Внутри обнаружились интересная реализация виртуальной файловой системы (vfs 1.0) и очень много ругательств на английском языке. Если найдётся что‑то ещё интересное, обязательно сделаю отдельную статью.
Но вернемся к нашему архиву.
Проверяем на современном компьютере
Пока 286-й проверяет оставшиеся номера, попробуем другим способом убедиться, что нашли нужную строку. Теперь уже на современном компьютере, с помощью bkcrack — она реализует атаку по известному открытому тексту — как раз на основе исследований Бихама и Кохера, о которых мы говорили выше.
AUTORS.DOC хранится без сжатия (Stored). Для атаки bkcrack нужны хотя бы 12 известных байт: 11 у нас уже есть, а ещё один программа автоматически берёт из служебных данных ZIP.
Сделаем файл с найденной строкой в CP866. (Я забыл, что Windows 3.1 и 3.11 были уже повсюду в том году, потом отдельно проверил CP1251 и KOI8-R)
$ printf 'Т.220-34-17' | iconv -f UTF-8 -t CP866 > autors.txt
И запустим bkcrack:
$ ./bkcrack -C AUTORS.ZIP -c AUTORS.DOC -p autors.txt bkcrack 1.8.1 - 2025-10-25 [14:59:01] Z reduction using 4 bytes of known plaintext 100.0 % (4 / 4) [14:59:01] Attack on 1234513 Z values at index 6 Keys: 63aa72a7 a18eedca 254c6c2e 9.9 % (121602 / 1234513) Found a solution. Stopping. You may resume the attack with the option: --continue-attack 121602 [15:01:42] Keys 63aa72a7 a18eedca 254c6c2e
За пару минут нашлись три 32-битных ключа. Это ещё не пароль, а три внутренних 32-битных ключа ZipCrypto, определяющих состояние шифра. Но их уже достаточно, чтобы сделать копию архива без пароля и получить AUTORS.DOC:
$ ./bkcrack -C AUTORS.ZIP -k 63aa72a7 a18eedca 254c6c2e -D AUTORS_CLEAR.ZIP
Распаковываем:
$ unzip AUTORS_CLEAR.ZIP | iconv -f CP866 -t UTF-8 Archive: AUTORS_CLEAR.ZIP Как связаться с издателем диска. extracting: AUTORS.DOC $ stat -x AUTORS.DOC | grep Birth Birth: Mon Aug 22 18:39:12 1994 $ stat -x AUTORS.ZIP | grep Birth Birth: Mon Aug 22 22:40:36 1994
Сдвиг на четыре часа связан с интерпретацией старых DOS‑меток времени в macOS. Cтарые DOS‑метки времени не самый надёжный источник информации, но я прямо представил, как дождливым августовским днём 1994 года кто‑то записал телефон в файл, а минуту спустя запустил PKZIP.
Теперь можно посмотреть содержимое уже расшифрованного файла:
$ iconv -f CP866 -t UTF-8 AUTORS.DOC Т.220-34-17%
В распакованном AUTORS.DOC оказалась та самая строка — Т.220-34-17. CRC32 совпала с контрольной суммой из архива, найденные ключи подошли, файл распаковался. Казалось бы, дело закрыто.
Но тут есть подвох: мы сами подсказали bkcrack, какой текст хотим увидеть. Для такого короткого файла можно подобрать другую строку с той же CRC32, восстановить по ней подходящие ключи и успешно расшифровать архив — я проверил это на практике. Поэтому успешная расшифровка ещё не доказывает, что изначально в архиве лежал именно этот телефонный номер.
Задача была бы гораздо проще, если бы в архиве находился ещё один зашифрованный файл с предсказуемым содержимым. Например, EXE‑файл с характерным заголовком MZ или что‑нибудь ещё, что позволило бы независимо проверить правильность найденных ключей.
Перебор по шаблону на 286 завершился за 48 часов и других совпадений не нашел. Я решил расширить поиск — и среди найденных коллизий оказались строки, похожие на телефон:
Строка | Кодировка | CRC32 |
|---|---|---|
| CP866 |
|
| CP866 |
|
| ASCII |
|
| CP866 |
|
| CP866 |
|
| ASCII |
|
| KOI8-R |
|
| Windows-1251 |
|
| ASCII |
|
| ASCII |
|
| ASCII |
|
Исходная версия Т.220-34-17 выглядит наиболее убедительно, но в 1994 году я бы не поленился позвонить по всем номерам. Прогнал все номера через базу TEL.EXE и SONATA.EXE — совпадений нет.
А пароль?
Можно попробовать восстановить и сам пароль. Сразу скажу: тут долго ничего хорошего не выходило.
Для найденного набора ключей я проверил все возможные значения байтов в паролях длиной до 12 байт включительно — ничего не нашлось. Дальше всё стало медленно. Даже с учётом того, что bkcrack использует обратимость отдельных операций шифра и не перебирает каждый пароль целиком, пространство поиска огромное. Примерно за двое суток нашёлся один эквивалентный пароль — строка, которая приводит шифратор к тем же трём ключам, но не обязательно совпадает с паролем, который набрали авторы архива.
$ bkcrack-1.8.1-cp866 -k 63aa72a7 a18eedca 254c6c2e --charset-file x cp866-ascii.bin -r 0..255 '?x' -j 8 --continue-recovery 25516b93202020 bkcrack 1.8.1 - 2025-10-25 [01:41:19] Recovering password length 13... Password: /h.H☉Eu (as bytes: 2f 68 2e a1 a9 48 87 e2 98 89 f8 45 75) Some characters are not in the expected charset. Continuing. 10.6 % (2759 / 25921)
Если прочитать эти байты в CP866, получится:
/h.бйHЗтШЙ°Eu
Технически такой пароль можно набрать и на клавиатуре — например, через Alt и цифровую клавиатуру (Alt+248) для ввода символа с кодом 0xF8. Но по моим ощущения это лишь эквивалентный пароль. В статье Бихама и Кохера как раз упоминаются такие случаи:
Thus,we expect to remain with only the right key (or an equivalent) in trials of up to
13-byte keys. Note that keys longer than 12 bytes will almost always have equiv‑
alents with up to 12 (or sometimes 13) bytes, since the internal representation
is only 12-bytes long.
Таким образом, мы ожидаем, что при переборе ключей длиной до 13 байт останется только правильный ключ (или его эквивалент). Заметим, что ключи длиннее 12 байт почти всегда имеют эквиваленты длиной не более 12 байт (а иногда — 13 байт), поскольку внутреннее представление ключа занимает всего 12 байт.
Важно уточнить, что пароль я ищу по ключам, полученным для строки Т.220–34-17 как наиболее убедительной версии. Поэтому утверждать, что исходный пароль однозначно длиннее 12 байт, нельзя. Пока я считаю это направление наиболее перспективным.
По примерным оценкам, чтобы добить 13-байтовые пароли, понадобится около недели, 14 байт — уже 4,5 года, а 15 — аж 710 лет. Hashcat на GPU не дает сильного прироста. Учитывая, какие длинные пароли использовались для игровых архивов на дисках Classic Fond, надежды найти исходный пароль мало:
1993 — IMAGINE_WHO_ARE_YOU_A6B9A6DB3Dj2AD7F7D7CEDEN968EC081DD7DB97BCB6708B68B3DB68F 1993TRIS — C9070696199B11F9C2C0200F8C09 3DPINBAL — iu202020iTysi20gic20iidv20ia2020vessir 3DTETRIS — DAMNED_LAMER_7968FF78BDBCEB5960FBF24AND7968ED70F8F96jA24CEDBA62A0F0F 777 — inisiTvi20nhced20asighs20Thuyita20 AB — 20y20rnes20nnssttissiit20tsihiinru ABC — IMAGINE_WHO_ARE_YOU_0FCCECq796F7F9F9D7B9j0F97DEBC2ADE2A7j1DF71DD73D2AEEB9 ABUSE — aiare20n202020ius20stit20hvssrgi20u2020 ACESW95 — iu202020iTysi20gic20iidv20ia2020vessir AD3WIZ — FB9BB3EE3BC7HF83B12DB1F24 ADDALOT — VAF3FE3DDgB23BFFBA05DF1CAD AIRHAVOC — SON_OF_BITCH_8BBFjCCDE3DD78B0F97jD70FF778BDB0FB9jC7qBF2A97N0FC08 AIRPOWER — sni20c20202020sndheiusi20u20rTii20s2020t AIR_SVGA — uegg20nti20saee20rrtir20uhsv20s20esn ALUNSER — tniei202020sdi20hst20eTesgggg20ssns20 AMY'S — 20neesgnsd20ni20gyn20hniis20ur20avti ANATOMIK — iechTi20nii20eisdi20dsnrceaeh20rvi
Подведем итоги:
Мы успешно открыли зашифрованный AUTORS.ZIP с дисков «Лучшие игры для IBM PC» от Classic Fond и получили файл со строкой Т.220-34-17 . Потом повторили и получили другую строку. А затем ещё одну.
Список всех найденных мной вариантов AUTORS.DOC, похожих на телефонные номера, я выложил здесь — github/classic‑fond‑reverse. Интуитивно Т.220-34-17 выглядит наиболее убедительно, плюс этот номер действительно встречается в документах той эпохи, но доказать, что именно его авторы записали в архив в 1994 году, пока не удалось.
После моей предыдущей статьи про реверс «Поля чудес» в комментариях нашлось столько полезной информации, что появилась надежда и на этот раз отыскать кого‑нибудь из непосредственных участников событий. Очень хочется узнать, кто и зачем придумал этот челлендж, удавалось ли кому‑нибудь вскрыть архив в 90-е или позже и звонил ли кто‑нибудь по найденному номеру в 1994–1996 годах. Да и кому вообще принадлежал этот номер в те годы? И почему после 1996 года архив исчез с дисков?
Спасибо, что дочитали до конца.
