Взлом метро: копирование и подделка билетов метрополитена || Дамп nfc

Как все начиналось

Интерес к системам подземки появился у меня давно, можно сказать, со школьной скамьи, когда в ходу еще были билеты с магнитной полосой. Тогда же (с десяток лет назад) ввели в оборот бесконтактную социальную карту для учащихся. Я стал интересоваться, что же это такое и как работает. Но в те времена и у меня не было достаточно навыков, да и информации, особенно по этим технологиям, в открытом доступе было немного.

Пришлось отложить идею исследований в долгий ящик, но я пообещал себе, что обязательно к ней вернусь… Года три назад у меня снова проснулся интерес к теме метро. Я активно изучал магнитные билеты (информации по этой теме в интернетах было предостаточно) и даже собрал маленький станочек для изготовления дубликатов из двух головок от катушечных магнитофонов и небольшого количества рассыпухи.

Не забыл и про свою социальную карту (уже студенческую). Но после изучения документации мне стало понятно, что система практически неприступна — чип MF1S50 Mifare Classic 1K, на базе которых изготавливаются социальные карты, защищен двумя 48‑битными ключами. На аппаратном уровне взломать его так просто не получится, а перебирать ключи можно до скончания солнечной системы.

Встречайте: «Ультралайт»

Билеты «Ультралайт» появились в нашем метро недавно, но сразу же вызвали у общественности бурный интерес. Их начали курочить, рвать, расклеивать утюгом и применять прочие методы терморектального криптоанализа. Надо признаться, жажда знаний заставила и меня раскурочить парочку. В результате их изучения и поисков в интернетах было установлено — это не что иное, как Mifare Ultralight, «облегченная» совместимая версия Mifare Classic.

Поехали!

Для начала, разумеется, просто необходимо было где-то раздобыть беспроводной картовод, поддерживающий «Ультралайт». Было два варианта: или собрать самому (что заняло бы много времени), или купить уже готовое устройство. При мысли о втором варианте, памятуя о ценах трехгодичной давности, у меня пошли мурашки по коже.

Взлом метро: копирование и подделка билетов метрополитена || Дамп nfc

Но я все же решился посмотреть актуальные цены. И не зря! Я был приятно удивлен, узнав, что можно купить полностью функциональный девайс (OmniKey CardMan 5321), который поддерживает кучу проводных и беспроводных карт по привлекательной цене — 4000 рубликов. Конечно, не мало, но с другой стороны, это и не 10000;

тем более, покупка готового ридера давала возможность сразу сосредоточиться на исследованиях билетов, а не на конструировании и отладке железа, которая могла затянуться на неопределенный срок. Вместе с ридером у той же фирмы (ISBC) был приобретен очень удобный оригинальный SDK местного производства.

Итак, за пару дней неспешного кодинга родилась маленькая программка, с помощью которой можно было в удобной форме наблюдать и править всю внутреннюю структуру «Ультралайтов». Тогда я начал изучать билеты.

Глухая стена

В процессе изучения через мой ридер прошло очень много билетов. Какие-то я, закатав рукава, доставал «из помойки», какие-то покупал — смотрел, что на них записано, затем проходил и смотрел еще раз. Это были билеты почти всех типов, за исключением, пожалуй, проездного «Ультралайта» на 70 поездок. Через пару недель у меня накопилась большая и отсортированная база дампов разных билетов и в разных состояниях.

Были и дампы, снятые с одного и того же билета после каждой поездки, и несколько билетов с метрополитеновскими номерами, идущими подряд. В мою коллекцию попало даже несколько дампов двух разных временных единых социальных билетов (один был выдан сроком на 5 дней, другой на 30), снятых через некоторый временной интервал.

Взлом метро: копирование и подделка билетов метрополитена || Дамп nfc

Это оказались очень интересные экземпляры, и при этом очень редкие (мне они доставались из первых рук с немедленным возвратом, только на «прочитать»). По сути, это почти единственный тип «Ультралайтов», который работает не только в метро, но и на наземном транспорте. К тому же, только у этого типа билетов вообще нет ограничения на количество поездок. Впоследствии, именно они сослужили мне большую службу…

Весь этот зоопарк я собирал с одной целью — четко определить структуру и формат записи данных на билете. Конечно, какие-то поля были видны сразу, невооруженным глазом, но некоторые нет. Например, я не сразу понял, где записан номер билета метро (тот самый, который на нем напечатан). Осознание пришло совершенно случайно.

Дело в том, что я (как и, думаю, большинство из нас), смотря в хекс, привык выравнивать для себя информацию по байтам и мыслить, минимум, байтами. Выяснилось, что здесь этот подход неверен. Глядя на дамп билета, нужно мыслить более мелкими единицами — тетрадами, а иногда и битами. Понял я это тогда, когда «узрел» наконец номер билета, — он оказался сдвинут на 4 бита относительно начала байта, а оставшиеся 4 бита с той и с другой стороны номера занимала прочая служебная информация.

Через некоторое время формат записи данных на билеты стал почти полностью понятен. Стало очевидно, где и как хранятся все даты, счетчики, идентификаторы. Оставалась лишь пара полей, назначение которых было неясно просто потому, что от дампа к дампу данные в них были одинаковы.

Но на этом вся радость и закончилась — глупо было бы предполагать, что такие билеты могут оставить незащищенными. В каждом дампе было 32 бита различной информации, никак не коррелировавшей с остальным содержимым. Я предположил, что это своего рода контрольная сумма, «хэш» данных, написанных на билете.

Все попытки прикинуть или рассчитать эти 32 бита обернулись полным провалом (в частности, было предположение, что это какой-то вид CRC32, с нестандартным полиномом и стартовым значением). При попытке изменить хотя бы полтора бита информации внутри билета терминал проверки в метро высвечивал «ПЛОХОЙ БИЛЕТ», увесистым домкратом заколачивая последние гвозди в крышку гроба.

image

Конечно, были попытки обойти систему и другими способами, например, попытаться скопировать билет на чистую карту один-в-один (тут, увы, помешал заводской серийник, который, как выяснилось, тоже участвовал в генерации «хэша») или выставить биты блокировок так, чтобы запретить турникету изменять содержимое билета.

Проверочный терминал такой «вечный» билетик признавал, но турникет пускать отказывался… Таким образом, я уперся в стену. В ту большую, крепкую бетонную стену, об которую многие имеют привычку убиваться с разбега. Не найдя никакой информации на форумах и досках, я решил, что на этом мои исследования закончены — путей больше нет, и поставил жирную точку. Как выяснилось, зря…

Странное знакомство

Сентябрьский вечер ничем не отличался от других. Уже почти наступила ночь, на улице было прохладно и сыро. Я сидел перед экраном монитора, и, попивая теплый, чуть сладкий зеленый чай, мирно разводил плату для очередной своей поделки. DipTarce, немного башорга, аська… Кто-то позвонил по скайпу — отвлекают!

Опять аська, опять DipTrace — в общем, все как обычно. В очередной раз на передний план вывалилось окно аськи — кто-то, доселе мне неизвестный, написал «Привет». Я, ничтоже сумняшеся, ответил тем же. Следующее сообщение явилось переломным во всей истории: «Ты вроде метро интересуешься, у меня тут кое-какое барахлишко есть. Если интересно, давай встретимся, я тебе передам».

Сначала меня это немного смутило и насторожило (может быть, развод или подстава, а может, и «спецслужбы» заинтересовались — паранойя берет свое), но потом я подумал: почему бы и нет? Спецслужбы мной интересоваться вряд ли бы стали, а почвы для развода, и уж тем более, для подставы тут вроде бы и нет.

После недолгой беседы мы договорились о встрече днем, в центре зала одной из станций московского метро. Незнакомец оказался высоким молодым человеком, в очках, с большим черным полиэтиленовым пакетом в руках. Мы поздоровались, затем он передал мне пакет со словами: «На, держи. Мне это все равно не пригодилось, может тебе будет полезно».

image

Заглянув внутрь, я увидел два метрошных терминала, переложенных газетами, несколько хаотично разбросанных белых пластиковых карточек и болванку в коробочке. На мой вопрос о том, сколько я за это должен (денег), парень помотал головой, улыбнулся и сказал: «Да ты что, никто ничего никому не должен, занимайся…

Контакт из аськи я на всякий случай удалил, заодно почистив контакт-лист на сервере и прибрав логи (еще раз привет, паранойя). В конце концов, напишет еще раз, если что. Но больше он мне так и не написал…

Явление софта народу

Придя домой, я разобрал пакет. Второй из терминалов оказался автобусным валидатором (тяжеленный, блин!); карточки были Mifare Classic 1K (чистые), а на диске красовался один единственный архив. После беглого ознакомления с содержимым выяснилось — это софт, который используется на кассах метро. Отложив в сторону терминал и валидатор, я решил вплотную заняться изучением интересного софта.

Примерно за час из бардака, который распаковался, мне удалось выстроить и запустить у себя на компьютере эту программу. Еще час потребовался, чтобы разобраться в ее структуре. Прочесав все ini-файлы (с комментариями, любезно оставленными разработчиком), я уже имел полное представление что это, как это работает и с чем это едят. Едят, как выяснилось, с ридером Parsec PR-P08, поэтому, за отсутствием оного, попробовать софт в действии не удалось.

Разработчиком значилась фирма «Смартек» — крупный государственный подрядчик, разрабатывающий системы такого рода (подробнее можно почитать на их сайте). Программа была написана на Delphi с использованием рантайм-bpl’ок. Причем, софт имел модульную структуру, и все подпрограммы, классы и компоненты располагались в отдельных DLL или bpl’ках с говорящими названиями (вот это был и самый главный фэйл раз- работчиков).

После беглого анализа внутренностей софта я выяснил, что, во-первых, информация обо всех выданных билетах передается в централизованную базу данных (к слову, это Oracle) и, во-вторых, в программе используется некий механизм ключей. Программа могла общаться с БД не только в режиме реального времени.

Итак, я взялся за дизассемблер и приступил к работе. Механизм состоял из двух файлов — CryptKeyRef.dll и keys.d (единственный «хитрый» файл во всей программе, который, кроме как на файл с ключами, больше ни на что не похож). А пользовалась всем этим добром рантайм-bpl’ина SmLayout.bpl. Эта библиотека оказалась просто находкой для моих исследований — в ней содержались классы для работы с внутренним наполнением билетов.

Так как это рантайм-bpl, то достаточно было просто взглянуть на ее таблицу экспорта, чтобы уже процентов на 60 понять, что к чему. Более детальный анализ расставил все на свои места. Помнишь, в начале статьи я говорил о том, что в структуре «Ультралайта» остались еще несколько полей, назначение которых было непонятным?

image

Одно из этих полей — так называемый «идентификатор раскладки». По сути, все билеты метро строятся из фиксированной заголовочной части и переменной части данных. Так вот, это поле «Layout» в заголовке как раз и определяло, каким образом и какие данные расположены в оставшейся части билета. Таких раскладок существует несколько (каждая под свой тип билета), и в SmLayout.

Добив полностью весь Layout 8 (который используется в «Ультралайтах») и перепроверив, обо всех ли полях в структуре билета у меня было верное представление, я взялся за механизм ключей. Действительно, он отвечал за генерацию «хэша». Как работает механизм, стало полностью ясно после изучения работы метода, отвечавшего за вычисление «хэша».

Сначала, из файла с ключами (keys.d) выбирается верный ключ. Система устроена так, что у каждого типа билетов есть свой идентификатор (в комплекте присутствовала полная таблица с идентификаторами и названиями билетов, в виде текстового файла со значениями, разделенными запятой). Состоит он из идентификатора зоны (приложения) и идентификатора типа карты.

Так вот, исходя из этих чисел, в файле ключей выбирается кейринг, внутри которого может быть уже несколько ключей (на случай, когда новый ключ ввели, а старые билеты еще используются). Запись нового билета происходит с использованием самого первого, а проверка на валидность — с использованием всех ключей в кейринге.

Далее выбранный ключ расшифровывается с помощью CryptKeyRef.dll (зачем их хранят зашифрованными, ума не приложу). После чего расшифрованный ключ и почти все данные билета, а также его аппаратный серийный номер и число (метод генерации «хэша», который указывается для кейринга в keys.d) — передаются в функцию ckCalcHashCode, находящуюся в той же CryptKeyRef.dll.

На выходе мы получаем значение, на котором я в свое время и «застрял» — тот самый «хэш». Разумеется, я написал маленькую программку, которая, используя эти функции из CryptKeyRef.dll и файл keys.d, могла проверять и, в случае чего, пересчитывать «хэш» внутри любого дампа. Я перепроверил все на нескольких дампах, и, получив положительный результат, ушел, довольный, спать.

Протухшие ключи

Несмотря на теоретический успех, хотелось проверить все, так сказать, «в бою». На следующий день, возвращаясь с работы, я специально прикупил свежий «Ультралайт» на одну поездку, чтобы посмотреть, действуют ли мои ключи или уже нет (судя по всему, они были старенькие). Можно, конечно, сразу было попробовать записать «сфабрикованный» «Ультралайт» и пойти проверить, но на тот момент у меня закончились пустые карты, да и немного страшновато идти «наобум» — вдруг что?

По приходу домой я первым делом, даже не помыв руки, с нетерпением бросился проверять свежий билет своими ключами. И тут меня поджидал большой облом — «хэш», записанный в билете не проходил ни по одному из ключей. Стало быть, ключи действительно уже протухли и на смену им пришли новые. Это полностью перечеркивало все мои труды. Мне немного взгрустнулось. Я заварил зеленого чая, поиграл немного на фортепиано (да-да) и сел дальше разводить свою неоконченную плату…

Еще не все потеряно

Идея пришла ко мне неожиданно, когда я в очередной раз зачем-то смотрел внутрь файла с ключами. Я заметил, что в «ходовом» кейринге (который используется для расчета 1-, 2-, 5‑поездочных и прочих «Ультралайтов») было два ключа — новый (на тот момент, разумеется) и, по всей видимости, — старый. Но был также кейринг, в котором лежал всего один ключ.

image

Раньше я не обращал на него внимания, а концентрировался на «ходовом». Для расчета каких билетов используется этот ключ, я не знал. Когда я посмотрел, что за тип билета привязан к кейрингу, то у меня вспыхнула маленькая искорка надежды. Дело в том, что этот тип билета был — ВЕСБ. Да, именно тот редкий тип билета, — временный проездной на все виды транспорта.

Я прикинул, что если билет единый, то этот ключ должен использоваться не только в метро, но и на наземном транспорте, где его очень сложно и долго заменять на новый. К тому же, ключ в кейринге всего один, что косвенно подтверждало мою догадку. Ко всему прочему, я вспомнил, что, когда вычищал метрошную программу от разного «мусора», там было нечто, похожее на архив старых файлов ключей.

Уже без единой капли сомнения я склепал свой собственный ВЕСБ (благо, у меня были дампы такого типа, что в разы упростило задачу — я просто поменял в дампах даты и номер), а «хэш» рассчитал с использованием этого ключа. Итак, настало время проверки (тем более, я как раз купил еще немного чистого пластика).

Зайдя в вестибюль, я сначала приложил свой «билет» к проверочному терминалу. На табло высветился срок действия билета, который я указал, и загорелся зеленый светодиод. Стало быть, работает. Сделав гримасу попроще и спрятав белоснежный пластик в рукав, я подошел к турникету, приложил руку к валидатору и… спокойно прошел на весело загоревшийся зеленый. Это ознаменовало окончательную победу.

А что же дальше?

А дальше начались эксперименты, в ходе которых было выяснено множество интересных вещей. Например, по такому «левому» ВЕСБу можно ходить всего два-три дня. Дело в том, что номер, который внутри билета я указываю «от балды», при каждом проходе сохраняется в памяти головы турникета, а через какое-то время отсылается вместе с остальными в центр обработки данных.

Там система не находит реально выданного билета с таким номером и вносит его в стоп-лист, который затем рассылается по всем турникетам метро. И так должно происходить со всеми типами билетов, не только с ВЕСБ — в дополнение к «хэшу» и часто меняющимся ключам это очень хорошая защита. Обойти ее, по понятным причинам, не представляется возможным.

В дальнейшем я взялся за метрошный и автобусный терминалы, привел их в порядок, изучил и запустил на стенде. Теперь, чтобы проверить очередную догадку, уже не надо было бежать со свежеиспеченным билетиком-мутантом в метро, а стало возможным проверять их «не отходя от кассы». Тем более, терминал метро оказался такой же старый (ко всему прочему и глючный), как и мои ключи. Так что я мог попробовать «в работе» и любые другие типы билетов «Ультралайт» — то, чего я никогда не смогу сделать «вживую» в метро.

Параллельно с этими экспериментами я продолжал заниматься софтом. Так как велось много споров о том, что же за алгоритм используется при вычислении «хэша», я решил полностью восстановить его, переписав алгоритм с нуля на «людском» языке программирования, а в процессе как раз надеялся понять, какой же это алгоритм — что-то широко известное или же какая-то своя, внутренняя разработка.

image

Попутно меня посещало много разных мыслей (в том числе, что это может быть и AES), но при детальном изучении уже работающего кода без использования Смартековских библиотек выяснилось, что алгоритм этот — «всего-на-всего» ГОСТ — отечественный стандарт шифрования (всю необходимую информацию о нем ты сможешь без труда найти в Сети). Конкретно, для вычисления «хэша» использовался цикл 16‑З. «Хэш», по сути, это не что иное, как имитовставка ГОСТ.

The End, или Подведем итоги

Системы метро, а в частности, новые билеты «Ультралайт», вопреки мнениям и догадкам, оказались хорошо защищены. Очень радует, что разработчики использовали надежный и проверенный временем ГОСТ, а не стали изобретать велосипед. С такой защитой подделать билет «Ультралайт», не имея доступа к конфиденциальным данным (ключевой информации), просто невозможно. Замечательно продумана и система сменных ключей, и механизм стоп-листов.

Конечно, не обошлось без недостатков и ошибок. Самая большая из них — программное обеспечение, которое никак не защищено. Достаточно было отказаться от использования рантайм-bpl, и это затруднило бы анализ в десятки раз! Как вариант, — обработка особо важных частей программы AsProtect’ом или ExeCryptor’ом, с последующей запаковкой всех файлов MoleBox’ом свели бы возможность анализа почти к нулю.

Инструментарий-то недорогой. А использование хорошей (желательно, малоизвестной или сделанной на заказ) защиты подобного рода, но с аппаратными ключами сделало бы разбор программы полностью невозможным. Разумеется, Метрополитен — это режимное предприятие, но не стоит при этом забывать про человеческий фактор.

Ведь еще Кевин Митник говорил (и не только говорил, но и демонстрировал на собственном примере, за что и сел, гы), что иногда для достижения цели проще и эффективнее использовать «социальную инженерию», нежели пытаться сломать непробиваемую защиту.Что ж, на этой ноте я и закончу свое повествование.

Взлом метро: копирование и подделка билетов метрополитена || Дамп nfc

INFO

Взлом метро: копирование и подделка билетов метрополитена || Дамп nfc
Полную версию статьи читай в ноябрьском номере Хакера

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *